From dc75d55f72af11bdf81b081dad8f5e84be3ed2e2 Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Wed, 8 Jun 2022 14:02:15 -0400 Subject: [PATCH 0001/1400] allow modfailcondition to arbitrarily trigger fail --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 19 +++++++++++++++++++ osu.Game/Rulesets/Scoring/HealthProcessor.cs | 14 ++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index 4425ece513..1aab0ab880 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -19,12 +19,31 @@ namespace osu.Game.Rulesets.Mods public virtual bool PerformFail() => true; public virtual bool RestartOnFail => Restart.Value; + private HealthProcessor healthProcessorInternal; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { + healthProcessorInternal = healthProcessor; healthProcessor.FailConditions += FailCondition; } + /// + /// Immediately triggers a failure on the loaded . + /// + protected void TriggerArbitraryFailure() => healthProcessorInternal.TriggerFailure(); + + /// + /// Determines whether should trigger a failure. Called every time a + /// judgement is applied to . + /// + /// The loaded . + /// The latest . + /// Whether the fail condition has been met. + /// + /// This method should only be used to trigger failures based on . + /// Using outside values to evaluate failure may introduce event ordering discrepancies, use + /// an with instead. + /// protected abstract bool FailCondition(HealthProcessor healthProcessor, JudgementResult result); } } diff --git a/osu.Game/Rulesets/Scoring/HealthProcessor.cs b/osu.Game/Rulesets/Scoring/HealthProcessor.cs index 0f51560476..4f5ff95477 100644 --- a/osu.Game/Rulesets/Scoring/HealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/HealthProcessor.cs @@ -33,6 +33,15 @@ namespace osu.Game.Rulesets.Scoring /// public bool HasFailed { get; private set; } + /// + /// Immediately triggers a failure for this HealthProcessor. + /// + public void TriggerFailure() + { + if (Failed?.Invoke() != false) + HasFailed = true; + } + protected override void ApplyResultInternal(JudgementResult result) { result.HealthAtJudgement = Health.Value; @@ -44,10 +53,7 @@ namespace osu.Game.Rulesets.Scoring Health.Value += GetHealthIncreaseFor(result); if (meetsAnyFailCondition(result)) - { - if (Failed?.Invoke() != false) - HasFailed = true; - } + TriggerFailure(); } protected override void RevertResultInternal(JudgementResult result) From 21c5499da16eb88f12d6f5bee8d28b1557559b2f Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Fri, 10 Jun 2022 13:11:17 -0400 Subject: [PATCH 0002/1400] remove arbitrary from method name --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index 1aab0ab880..9500734408 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mods /// /// Immediately triggers a failure on the loaded . /// - protected void TriggerArbitraryFailure() => healthProcessorInternal.TriggerFailure(); + protected void TriggerFailure() => healthProcessorInternal.TriggerFailure(); /// /// Determines whether should trigger a failure. Called every time a @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mods /// /// This method should only be used to trigger failures based on . /// Using outside values to evaluate failure may introduce event ordering discrepancies, use - /// an with instead. + /// an with instead. /// protected abstract bool FailCondition(HealthProcessor healthProcessor, JudgementResult result); } From 6e64a8f55ef5838a5d58625668138fb3c85e34db Mon Sep 17 00:00:00 2001 From: Gabe Livengood <47010459+ggliv@users.noreply.github.com> Date: Fri, 10 Jun 2022 13:13:35 -0400 Subject: [PATCH 0003/1400] use event to trigger failure --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index 9500734408..63cebc9747 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -19,18 +19,18 @@ namespace osu.Game.Rulesets.Mods public virtual bool PerformFail() => true; public virtual bool RestartOnFail => Restart.Value; - private HealthProcessor healthProcessorInternal; + private event Action failureTriggered; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - healthProcessorInternal = healthProcessor; + failureTriggered = healthProcessor.TriggerFailure; healthProcessor.FailConditions += FailCondition; } /// /// Immediately triggers a failure on the loaded . /// - protected void TriggerFailure() => healthProcessorInternal.TriggerFailure(); + protected void TriggerFailure() => failureTriggered?.Invoke(); /// /// Determines whether should trigger a failure. Called every time a From c1077d909ca5e41270522714e8457733a36043f2 Mon Sep 17 00:00:00 2001 From: Ryuki Date: Sat, 17 Sep 2022 21:09:34 +0200 Subject: [PATCH 0004/1400] Basic avatar HUD implementation --- osu.Game/Screens/Play/HUD/SkinnableAvatar.cs | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/SkinnableAvatar.cs diff --git a/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs b/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs new file mode 100644 index 0000000000..abec4402a7 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; +using osu.Game.Skinning; +using osu.Game.Users.Drawables; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public class SkinnableAvatar : CompositeDrawable, ISkinnableDrawable + { + [SettingSource("Corner radius", "How much the edges should be rounded.")] + public new BindableFloat CornerRadius { get; set; } = new BindableFloat(0) + { + MinValue = 0, + MaxValue = 100, + Precision = 0.01f + }; + + [Resolved] + private GameplayState gameplayState { get; set; } = null!; + + private readonly UpdateableAvatar avatar; + + public SkinnableAvatar() + { + Size = new Vector2(128f); + InternalChild = avatar = new UpdateableAvatar(isInteractive: false) + { + RelativeSizeAxes = Axes.Both, + Masking = true + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + avatar.User = gameplayState.Score.ScoreInfo.User; + CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue); + } + + public bool UsesFixedAnchor { get; set; } + } +} From ecf71df8a23bfca5cbe5a78daef23908135d92c2 Mon Sep 17 00:00:00 2001 From: Ryuki Date: Sun, 18 Sep 2022 00:04:56 +0200 Subject: [PATCH 0005/1400] Change CornerRadius Max Value --- osu.Game/Screens/Play/HUD/SkinnableAvatar.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs b/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs index abec4402a7..d675176a0a 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs +++ b/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs @@ -15,10 +15,10 @@ namespace osu.Game.Screens.Play.HUD public class SkinnableAvatar : CompositeDrawable, ISkinnableDrawable { [SettingSource("Corner radius", "How much the edges should be rounded.")] - public new BindableFloat CornerRadius { get; set; } = new BindableFloat(0) + public new BindableFloat CornerRadius { get; set; } = new BindableFloat { MinValue = 0, - MaxValue = 100, + MaxValue = 63, Precision = 0.01f }; From 579d5b51eb25e90e7bc28f284b28c5edc14fc249 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 20:34:41 +0900 Subject: [PATCH 0006/1400] Add and consume sample bank constants --- .../TestSceneAutoJuiceStream.cs | 2 +- .../Editor/TestSceneSliderSplitting.cs | 4 +- .../Formats/LegacyBeatmapDecoderTest.cs | 14 +++--- ...estSceneHitObjectSamplePointAdjustments.cs | 45 ++++++++++--------- .../TestSceneGameplaySampleTriggerSource.cs | 4 +- osu.Game/Audio/HitSampleInfo.cs | 9 ++++ .../ControlPoints/SampleControlPoint.cs | 4 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 3 +- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 6 +-- 9 files changed, 51 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 202228c9e7..e47a687f24 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_NORMAL, volume: 100) }) }); } diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs index 015952c59a..d642d6a5ed 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { if (slider is null) return; - slider.SampleControlPoint.SampleBank = "soft"; + slider.SampleControlPoint.SampleBank = HitSampleInfo.BANK_SOFT; slider.SampleControlPoint.SampleVolume = 70; sample = new HitSampleInfo("hitwhistle"); slider.Samples.Add(sample); @@ -207,7 +207,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddAssert("sliders have hitsounds", hasHitsounds); bool hasHitsounds() => sample is not null && - EditorBeatmap.HitObjects.All(o => o.SampleControlPoint.SampleBank == "soft" && + EditorBeatmap.HitObjects.All(o => o.SampleControlPoint.SampleBank == HitSampleInfo.BANK_SOFT && o.SampleControlPoint.SampleVolume == 70 && o.Samples.Contains(sample)); } diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index fdd0167ed3..d9817802f3 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -206,17 +206,17 @@ namespace osu.Game.Tests.Beatmaps.Formats var soundPoint = controlPoints.SamplePointAt(0); Assert.AreEqual(956, soundPoint.Time); - Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(HitSampleInfo.BANK_SOFT, soundPoint.SampleBank); Assert.AreEqual(60, soundPoint.SampleVolume); soundPoint = controlPoints.SamplePointAt(53373); Assert.AreEqual(53373, soundPoint.Time); - Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(HitSampleInfo.BANK_SOFT, soundPoint.SampleBank); Assert.AreEqual(60, soundPoint.SampleVolume); soundPoint = controlPoints.SamplePointAt(119637); Assert.AreEqual(119637, soundPoint.Time); - Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(HitSampleInfo.BANK_SOFT, soundPoint.SampleBank); Assert.AreEqual(80, soundPoint.SampleVolume); var effectPoint = controlPoints.EffectPointAt(0); @@ -261,10 +261,10 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(controlPoints.EffectPointAt(2500).KiaiMode, Is.False); Assert.That(controlPoints.EffectPointAt(3500).KiaiMode, Is.True); - Assert.That(controlPoints.SamplePointAt(500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.SamplePointAt(1500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal")); - Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePointAt(500).SampleBank, Is.EqualTo(HitSampleInfo.BANK_DRUM)); + Assert.That(controlPoints.SamplePointAt(1500).SampleBank, Is.EqualTo(HitSampleInfo.BANK_DRUM)); + Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo(HitSampleInfo.BANK_NORMAL)); + Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo(HitSampleInfo.BANK_DRUM)); Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500).Within(0.1)); Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500).Within(0.1)); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index 6313842dfd..31939f6971 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -7,6 +7,7 @@ using System.Linq; using Humanizer; using NUnit.Framework; using osu.Framework.Testing; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; @@ -41,7 +42,7 @@ namespace osu.Game.Tests.Visual.Editing Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2, SampleControlPoint = new SampleControlPoint { - SampleBank = "normal", + SampleBank = HitSampleInfo.BANK_NORMAL, SampleVolume = 80 } }); @@ -52,7 +53,7 @@ namespace osu.Game.Tests.Visual.Editing Position = (OsuPlayfield.BASE_SIZE + new Vector2(100, 0)) / 2, SampleControlPoint = new SampleControlPoint { - SampleBank = "soft", + SampleBank = HitSampleInfo.BANK_SOFT, SampleVolume = 60 } }); @@ -70,7 +71,7 @@ namespace osu.Game.Tests.Visual.Editing public void TestSingleSelection() { clickSamplePiece(0); - samplePopoverHasSingleBank("normal"); + samplePopoverHasSingleBank(HitSampleInfo.BANK_NORMAL); samplePopoverHasSingleVolume(80); dismissPopover(); @@ -80,14 +81,14 @@ namespace osu.Game.Tests.Visual.Editing AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First())); clickSamplePiece(1); - samplePopoverHasSingleBank("soft"); + samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT); samplePopoverHasSingleVolume(60); setVolumeViaPopover(90); hitObjectHasSampleVolume(1, 90); - setBankViaPopover("drum"); - hitObjectHasSampleBank(1, "drum"); + setBankViaPopover(HitSampleInfo.BANK_DRUM); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM); } [Test] @@ -136,27 +137,27 @@ namespace osu.Game.Tests.Visual.Editing AddStep("unify sample bank", () => { foreach (var h in EditorBeatmap.HitObjects) - h.SampleControlPoint.SampleBank = "soft"; + h.SampleControlPoint.SampleBank = HitSampleInfo.BANK_SOFT; }); AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); clickSamplePiece(0); - samplePopoverHasSingleBank("soft"); + samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT); dismissPopover(); clickSamplePiece(1); - samplePopoverHasSingleBank("soft"); + samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT); setBankViaPopover(string.Empty); - hitObjectHasSampleBank(0, "soft"); - hitObjectHasSampleBank(1, "soft"); - samplePopoverHasSingleBank("soft"); + hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT); + samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT); - setBankViaPopover("drum"); - hitObjectHasSampleBank(0, "drum"); - hitObjectHasSampleBank(1, "drum"); - samplePopoverHasSingleBank("drum"); + setBankViaPopover(HitSampleInfo.BANK_DRUM); + hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM); + samplePopoverHasSingleBank(HitSampleInfo.BANK_DRUM); } [Test] @@ -172,14 +173,14 @@ namespace osu.Game.Tests.Visual.Editing samplePopoverHasIndeterminateBank(); setBankViaPopover(string.Empty); - hitObjectHasSampleBank(0, "normal"); - hitObjectHasSampleBank(1, "soft"); + hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT); samplePopoverHasIndeterminateBank(); - setBankViaPopover("normal"); - hitObjectHasSampleBank(0, "normal"); - hitObjectHasSampleBank(1, "normal"); - samplePopoverHasSingleBank("normal"); + setBankViaPopover(HitSampleInfo.BANK_NORMAL); + hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_NORMAL); + samplePopoverHasSingleBank(HitSampleInfo.BANK_NORMAL); } private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} sample piece", () => diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index b6da562bd0..6e53302624 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -57,13 +57,13 @@ namespace osu.Game.Tests.Visual.Gameplay { StartTime = t += spacing, Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }, - SampleControlPoint = new SampleControlPoint { SampleBank = "soft" }, + SampleControlPoint = new SampleControlPoint { SampleBank = HitSampleInfo.BANK_SOFT }, }, new HitCircle { StartTime = t + spacing, Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE) }, - SampleControlPoint = new SampleControlPoint { SampleBank = "soft" }, + SampleControlPoint = new SampleControlPoint { SampleBank = HitSampleInfo.BANK_SOFT }, }, }); diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index efa5562cb8..81cfed23f5 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -19,11 +19,20 @@ namespace osu.Game.Audio public const string HIT_FINISH = @"hitfinish"; public const string HIT_CLAP = @"hitclap"; + public const string BANK_NORMAL = @"normal"; + public const string BANK_SOFT = @"soft"; + public const string BANK_DRUM = @"drum"; + /// /// All valid sample addition constants. /// public static IEnumerable AllAdditions => new[] { HIT_WHISTLE, HIT_FINISH, HIT_CLAP }; + /// + /// All valid bank constants. + /// + public static IEnumerable AllBanks => new[] { BANK_NORMAL, BANK_SOFT, BANK_DRUM }; + /// /// The name of the sample to load. /// diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index c454439c5c..e7b869cfa7 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// public class SampleControlPoint : ControlPoint, IEquatable { - public const string DEFAULT_BANK = "normal"; + public const string DEFAULT_BANK = HitSampleInfo.BANK_NORMAL; public static readonly SampleControlPoint DEFAULT = new SampleControlPoint { @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// - /// The speed multiplier at this control point. + /// The sample bank at this control point. /// public string SampleBank { diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 75500fbc4e..b3e6f50366 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -10,6 +10,7 @@ using System.Linq; using osu.Framework.Extensions; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Logging; +using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Legacy; using osu.Game.Beatmaps.Timing; @@ -412,7 +413,7 @@ namespace osu.Game.Beatmaps.Formats string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") - stringSampleSet = @"normal"; + stringSampleSet = HitSampleInfo.HIT_NORMAL; if (timingChange) { diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 03c63ff4f2..52d1ea60a5 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -547,13 +547,13 @@ namespace osu.Game.Beatmaps.Formats { switch (sampleBank?.ToLowerInvariant()) { - case "normal": + case HitSampleInfo.BANK_NORMAL: return LegacySampleBank.Normal; - case "soft": + case HitSampleInfo.BANK_SOFT: return LegacySampleBank.Soft; - case "drum": + case HitSampleInfo.BANK_DRUM: return LegacySampleBank.Drum; default: From 9222cb379f7c5cdb1ad7a25f73df28242e5b1406 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 20:53:18 +0900 Subject: [PATCH 0007/1400] Add sample bank suport to editor selection handler --- .../Components/EditorSelectionHandler.cs | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 0bdfc5b0a0..1670328e58 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -48,11 +48,40 @@ namespace osu.Game.Screens.Edit.Compose.Components /// public readonly Dictionary> SelectionSampleStates = new Dictionary>(); + /// + /// The state of each sample bank type for all selected hitobjects. + /// + public readonly Dictionary> SelectionBankStates = new Dictionary>(); + /// /// Set up ternary state bindables and bind them to selection/hitobject changes (in both directions) /// private void createStateBindables() { + foreach (string bankName in HitSampleInfo.AllBanks) + { + var bindable = new Bindable + { + Description = bankName.Titleize() + }; + + bindable.ValueChanged += state => + { + switch (state.NewValue) + { + case TernaryState.False: + RemoveSampleBank(bankName); + break; + + case TernaryState.True: + AddSampleBank(bankName); + break; + } + }; + + SelectionBankStates[bankName] = bindable; + } + foreach (string sampleName in HitSampleInfo.AllAdditions) { var bindable = new Bindable @@ -104,12 +133,48 @@ namespace osu.Game.Screens.Edit.Compose.Components { bindable.Value = GetStateFromSelection(SelectedItems, h => h.Samples.Any(s => s.Name == sampleName)); } + + foreach ((string bankName, var bindable) in SelectionBankStates) + { + bindable.Value = GetStateFromSelection(SelectedItems, h => h.SampleControlPoint.SampleBank == bankName); + } } #endregion #region Ternary state changes + /// + /// Adds a sample bank to all selected s. + /// + /// The name of the sample bank. + public void AddSampleBank(string bankName) + { + EditorBeatmap.PerformOnSelection(h => + { + if (h.SampleControlPoint.SampleBank == bankName) + return; + + h.SampleControlPoint.SampleBank = bankName; + EditorBeatmap.Update(h); + }); + } + + /// + /// Removes a sample bank from all selected s. + /// + /// The name of the sample bank. + public void RemoveSampleBank(string bankName) + { + EditorBeatmap.PerformOnSelection(h => + { + if (h.SampleControlPoint.SampleBank == bankName) + h.SampleControlPoint.SampleBankBindable.SetDefault(); + + EditorBeatmap.Update(h); + }); + } + /// /// Adds a hit sample to all selected s. /// @@ -174,11 +239,17 @@ namespace osu.Game.Screens.Edit.Compose.Components yield return new TernaryStateToggleMenuItem("New combo") { State = { BindTarget = SelectionNewComboState } }; } - yield return new OsuMenuItem("Sound") + yield return new OsuMenuItem("Sample") { Items = SelectionSampleStates.Select(kvp => new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray() }; + + yield return new OsuMenuItem("Bank") + { + Items = SelectionBankStates.Select(kvp => + new TernaryStateToggleMenuItem(kvp.Value.Description) { State = { BindTarget = kvp.Value } }).ToArray() + }; } #endregion From 50e24ddd872bcd8e6c5c543d8fa6fcecac0f7b3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 21:35:08 +0900 Subject: [PATCH 0008/1400] Add icon and radio button logic --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 20 ++++++++- .../Components/ComposeBlueprintContainer.cs | 42 ++++++++++++++++++- .../Components/EditorSelectionHandler.cs | 35 +++++++++++++++- 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 3bed835854..8857bb2dae 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -71,6 +71,8 @@ namespace osu.Game.Rulesets.Edit private FillFlowContainer togglesCollection; + private FillFlowContainer sampleBankTogglesCollection; + private IBindable hasTiming; protected HitObjectComposer(Ruleset ruleset) @@ -146,6 +148,16 @@ namespace osu.Game.Rulesets.Edit Direction = FillDirection.Vertical, Spacing = new Vector2(0, 5), }, + }, + new EditorToolboxGroup("bank (Shift-Q~R)") + { + Child = sampleBankTogglesCollection = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + }, } } }, @@ -161,6 +173,8 @@ namespace osu.Game.Rulesets.Edit TernaryStates = CreateTernaryButtons().ToArray(); togglesCollection.AddRange(TernaryStates.Select(b => new DrawableTernaryButton(b))); + sampleBankTogglesCollection.AddRange(BlueprintContainer.SampleBankTernaryStates.Select(b => new DrawableTernaryButton(b))); + setSelectTool(); EditorBeatmap.SelectedHitObjects.CollectionChanged += selectionChanged; @@ -213,7 +227,7 @@ namespace osu.Game.Rulesets.Edit /// /// Create all ternary states required to be displayed to the user. /// - protected virtual IEnumerable CreateTernaryButtons() => BlueprintContainer.TernaryStates; + protected virtual IEnumerable CreateTernaryButtons() => BlueprintContainer.MainTernaryStates; /// /// Construct a relevant blueprint container. This will manage hitobject selection/placement input handling and display logic. @@ -255,7 +269,9 @@ namespace osu.Game.Rulesets.Edit if (checkRightToggleFromKey(e.Key, out int rightIndex)) { - var item = togglesCollection.ElementAtOrDefault(rightIndex); + var item = e.ShiftPressed + ? sampleBankTogglesCollection.ElementAtOrDefault(rightIndex) + : togglesCollection.ElementAtOrDefault(rightIndex); if (item is DrawableTernaryButton button) { diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index ec07da43a0..5adc60f6a7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -14,6 +14,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Audio; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; @@ -55,7 +57,8 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - TernaryStates = CreateTernaryButtons().ToArray(); + MainTernaryStates = CreateTernaryButtons().ToArray(); + SampleBankTernaryStates = createSampleBankTernaryButtons().ToArray(); AddInternal(placementBlueprintContainer); } @@ -172,7 +175,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// A collection of states which will be displayed to the user in the toolbox. /// - public TernaryButton[] TernaryStates { get; private set; } + public TernaryButton[] MainTernaryStates { get; private set; } + + public TernaryButton[] SampleBankTernaryStates { get; private set; } /// /// Create all ternary states required to be displayed to the user. @@ -186,6 +191,39 @@ namespace osu.Game.Screens.Edit.Compose.Components yield return new TernaryButton(kvp.Value, kvp.Key.Replace("hit", string.Empty).Titleize(), () => getIconForSample(kvp.Key)); } + private IEnumerable createSampleBankTernaryButtons() + { + foreach (var kvp in SelectionHandler.SelectionBankStates) + yield return new TernaryButton(kvp.Value, kvp.Key.Titleize(), () => getIconForBank(kvp.Key)); + } + + private Drawable getIconForBank(string sampleName) + { + return new Container + { + Size = new Vector2(30, 20), + Children = new Drawable[] + { + new SpriteIcon + { + Size = new Vector2(8), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.Solid.VolumeOff + }, + new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + X = 10, + Y = -1, + Font = OsuFont.Default.With(weight: FontWeight.Bold, size: 20), + Text = $"{char.ToUpper(sampleName.First())}" + } + } + }; + } + private Drawable getIconForSample(string sampleName) { switch (sampleName) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 1670328e58..750dedac20 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -11,6 +11,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Audio; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -70,11 +71,38 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (state.NewValue) { case TernaryState.False: - RemoveSampleBank(bankName); + if (SelectedItems.Count == 0) + { + // Ensure that if this is the last selected bank, it should remain selected. + if (SelectionBankStates.Values.All(b => b.Value == TernaryState.False)) + bindable.Value = TernaryState.True; + } + else + { + // Never remove a sample bank. + // These are basically radio buttons, not toggles. + if (SelectedItems.All(h => h.SampleControlPoint.SampleBank == bankName)) + bindable.Value = TernaryState.True; + } + break; case TernaryState.True: - AddSampleBank(bankName); + if (SelectedItems.Count == 0) + { + // Ensure the user can't stack multiple bank selections when there's no hitobject selection. + // Note that in normal scenarios this is sorted out by the feedback from applying the bank to the selected objects. + foreach (var other in SelectionBankStates.Values) + { + if (other != bindable) + other.Value = TernaryState.False; + } + } + else + { + AddSampleBank(bankName); + } + break; } }; @@ -82,6 +110,9 @@ namespace osu.Game.Screens.Edit.Compose.Components SelectionBankStates[bankName] = bindable; } + // start with normal selected. + SelectionBankStates[SampleControlPoint.DEFAULT_BANK].Value = TernaryState.True; + foreach (string sampleName in HitSampleInfo.AllAdditions) { var bindable = new Bindable From 372a655be1637d8823d89532d24a28f283798906 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 21:39:51 +0900 Subject: [PATCH 0009/1400] Ensure placement uses currently selected bank --- .../Components/ComposeBlueprintContainer.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 5adc60f6a7..1c9ac83630 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -77,9 +77,10 @@ namespace osu.Game.Screens.Edit.Compose.Components // we own SelectionHandler so don't need to worry about making bindable copies (for simplicity) foreach (var kvp in SelectionHandler.SelectionSampleStates) - { kvp.Value.BindValueChanged(_ => updatePlacementSamples()); - } + + foreach (var kvp in SelectionHandler.SelectionBankStates) + kvp.Value.BindValueChanged(_ => updatePlacementSamples()); } protected override void TransferBlueprintFor(HitObject hitObject, DrawableHitObject drawableObject) @@ -146,6 +147,9 @@ namespace osu.Game.Screens.Edit.Compose.Components foreach (var kvp in SelectionHandler.SelectionSampleStates) sampleChanged(kvp.Key, kvp.Value.Value); + + foreach (var kvp in SelectionHandler.SelectionBankStates) + bankChanged(kvp.Key, kvp.Value.Value); } private void sampleChanged(string sampleName, TernaryState state) @@ -170,6 +174,18 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + private void bankChanged(string bankName, TernaryState state) + { + if (currentPlacement == null) return; + + switch (state) + { + case TernaryState.True: + currentPlacement.HitObject.SampleControlPoint.SampleBank = bankName; + break; + } + } + public readonly Bindable NewCombo = new Bindable { Description = "New Combo" }; /// From b9f41611a7777951b8eebbb83ab5c9a6b27e1e12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 21:48:18 +0900 Subject: [PATCH 0010/1400] Fix bank potentially being overwritten during placement --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index c8196b6865..132214a0bd 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -74,9 +74,13 @@ namespace osu.Game.Rulesets.Edit /// Whether this call is committing a value for HitObject.StartTime and continuing with further adjustments. protected void BeginPlacement(bool commitStart = false) { + // Store and copy the bank, since it is managed by the editor UI. + string bank = HitObject.SampleControlPoint.SampleBank; + var nearestSampleControlPoint = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.SampleControlPoint?.DeepClone() as SampleControlPoint; HitObject.SampleControlPoint = nearestSampleControlPoint ?? new SampleControlPoint(); + HitObject.SampleControlPoint.SampleBank = bank; placementHandler.BeginPlacement(HitObject); if (commitStart) From 677b8d09f8773626b36f0e686520fb871b53220d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Oct 2022 23:54:12 +0900 Subject: [PATCH 0011/1400] Fix huge oversight causing test failures --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index b3e6f50366..ae57ee6f5a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -413,7 +413,7 @@ namespace osu.Game.Beatmaps.Formats string stringSampleSet = sampleSet.ToString().ToLowerInvariant(); if (stringSampleSet == @"none") - stringSampleSet = HitSampleInfo.HIT_NORMAL; + stringSampleSet = HitSampleInfo.BANK_NORMAL; if (timingChange) { From 849b50a38fe821720944fff0b560f33dceb25286 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Oct 2022 00:16:33 +0900 Subject: [PATCH 0012/1400] Use `ToUpperInvariant` for added safety MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 1c9ac83630..eebc4c8e0e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -234,7 +234,7 @@ namespace osu.Game.Screens.Edit.Compose.Components X = 10, Y = -1, Font = OsuFont.Default.With(weight: FontWeight.Bold, size: 20), - Text = $"{char.ToUpper(sampleName.First())}" + Text = $"{char.ToUpperInvariant(sampleName.First())}" } } }; From e1a21e0cf96df3c7deb4b4fbaf8636ef2ad7611d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 17 Nov 2022 00:01:29 +0900 Subject: [PATCH 0013/1400] create a task to export to avoid block main thread Code quality and remove some #nullable disable --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 7 +-- osu.Game/Database/LegacyBeatmapExporter.cs | 7 ++- osu.Game/Database/LegacyExporter.cs | 54 ++++++++++++++++--- osu.Game/Database/LegacyScoreExporter.cs | 11 ++-- osu.Game/Database/LegacyScoreImporter.cs | 2 - osu.Game/Database/LegacySkinExporter.cs | 7 ++- osu.Game/Database/LegacySkinImporter.cs | 2 - osu.Game/Database/RealmAccess.cs | 5 -- .../Online/Leaderboards/LeaderboardScore.cs | 5 +- .../Overlays/Settings/Sections/SkinSection.cs | 9 +++- osu.Game/Screens/Edit/Editor.cs | 5 +- 11 files changed, 78 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 5c20f46787..7a5f6dbd7c 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -15,6 +15,7 @@ using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; +using osu.Game.Overlays; using osu.Game.Skinning; using SharpCompress.Archives.Zip; @@ -122,7 +123,7 @@ namespace osu.Game.Tests.Skins.IO import1.PerformRead(s => { - new LegacySkinExporter(osu.Dependencies.Get()).ExportModelTo(s, exportStream); + new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); }); string exportFilename = import1.GetDisplayString(); @@ -204,7 +205,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); - new LegacySkinExporter(osu.Dependencies.Get()).ExportModelTo(s, exportStream); + new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); Assert.Greater(exportStream.Length, 0); }); @@ -239,7 +240,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); - new LegacySkinExporter(osu.Dependencies.Get()).ExportModelTo(s, exportStream); + new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); Assert.Greater(exportStream.Length, 0); }); diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index d064b9ed58..3e11e898f3 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Platform; using osu.Game.Beatmaps; +using osu.Game.Overlays; namespace osu.Game.Database { @@ -12,8 +11,8 @@ namespace osu.Game.Database { protected override string FileExtension => ".osz"; - public LegacyBeatmapExporter(Storage storage) - : base(storage) + public LegacyBeatmapExporter(Storage storage, INotificationOverlay? notificationOverlay) + : base(storage, notificationOverlay) { } } diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 16d7441dde..ed16e4bc80 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -1,11 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.IO; +using System.Threading.Tasks; using osu.Framework.Platform; using osu.Game.Extensions; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using SharpCompress.Archives.Zip; namespace osu.Game.Database @@ -25,10 +26,17 @@ namespace osu.Game.Database private readonly Storage exportStorage; - protected LegacyExporter(Storage storage) + private readonly INotificationOverlay? notificationOverlay; + + protected ProgressNotification Notification = null!; + + private string filename = null!; + + protected LegacyExporter(Storage storage, INotificationOverlay? notificationOverlay) { exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); + this.notificationOverlay = notificationOverlay; } /// @@ -37,12 +45,25 @@ namespace osu.Game.Database /// The item to export. public void Export(TModel item) { - string filename = $"{item.GetDisplayString().GetValidFilename()}{FileExtension}"; + filename = $"{item.GetDisplayString().GetValidFilename()}{FileExtension}"; - using (var stream = exportStorage.CreateFileSafely(filename)) - ExportModelTo(item, stream); + Stream stream = exportStorage.CreateFileSafely(filename); - exportStorage.PresentFileExternally(filename); + Notification = new ProgressNotification + { + State = ProgressNotificationState.Active, + Text = "Exporting...", + CompletionText = "Export completed" + }; + Notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + Notification.CancelRequested += () => + { + stream.Dispose(); + return true; + }; + + ExportModelTo(item, stream); + notificationOverlay?.Post(Notification); } /// @@ -57,7 +78,24 @@ namespace osu.Game.Database foreach (var file in model.Files) archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - archive.SaveTo(outputStream); + Task.Factory.StartNew(() => + { + archive.SaveTo(outputStream); + }, Notification.CancellationToken).ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + { + outputStream.Dispose(); + Notification.State = ProgressNotificationState.Completed; + } + else + { + if (Notification.State == ProgressNotificationState.Cancelled) return; + + Notification.State = ProgressNotificationState.Cancelled; + Notification.Text = "Export Failed"; + } + }); } } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 6fa02b957d..1564c7b077 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -1,12 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.IO; using System.Linq; using osu.Framework.Platform; using osu.Game.Extensions; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Scoring; namespace osu.Game.Database @@ -15,8 +15,8 @@ namespace osu.Game.Database { protected override string FileExtension => ".osr"; - public LegacyScoreExporter(Storage storage) - : base(storage) + public LegacyScoreExporter(Storage storage, INotificationOverlay? notificationOverlay) + : base(storage, notificationOverlay) { } @@ -28,6 +28,9 @@ namespace osu.Game.Database using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) inputStream.CopyTo(outputStream); + + Notification.State = ProgressNotificationState.Completed; + outputStream.Dispose(); } } } diff --git a/osu.Game/Database/LegacyScoreImporter.cs b/osu.Game/Database/LegacyScoreImporter.cs index f61241141e..131b4ffb0e 100644 --- a/osu.Game/Database/LegacyScoreImporter.cs +++ b/osu.Game/Database/LegacyScoreImporter.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. -#nullable disable - using System; using System.Collections.Generic; using System.IO; diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 1d5364fb8d..a78d69e7b9 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Platform; +using osu.Game.Overlays; using osu.Game.Skinning; namespace osu.Game.Database @@ -12,8 +11,8 @@ namespace osu.Game.Database { protected override string FileExtension => ".osk"; - public LegacySkinExporter(Storage storage) - : base(storage) + public LegacySkinExporter(Storage storage, INotificationOverlay? notificationOverlay) + : base(storage, notificationOverlay) { } } diff --git a/osu.Game/Database/LegacySkinImporter.cs b/osu.Game/Database/LegacySkinImporter.cs index 42b2f2e1d8..2f05ccae45 100644 --- a/osu.Game/Database/LegacySkinImporter.cs +++ b/osu.Game/Database/LegacySkinImporter.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. -#nullable disable - using osu.Game.Skinning; namespace osu.Game.Database diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1a938c12e5..5a7ead1c59 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -173,11 +173,6 @@ namespace osu.Game.Database if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal)) Filename += realm_extension; -#if DEBUG - if (!DebugUtils.IsNUnitRunning) - applyFilenameSchemaSuffix(ref Filename); -#endif - string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}"; // Attempt to recover a newer database version if available. diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index a7b6bd044d..72f1a94ec8 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -75,6 +75,9 @@ namespace osu.Game.Online.Leaderboards [Resolved] private Storage storage { get; set; } + [Resolved] + private INotificationOverlay notificationOverlay { get; set; } + public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => Score; @@ -427,7 +430,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage).Export(Score))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage, notificationOverlay).Export(Score))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index f602b73065..df6f719b1e 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -141,11 +141,16 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private Storage storage { get; set; } + [CanBeNull] + private INotificationOverlay notificationOverlay; + private Bindable currentSkin; [BackgroundDependencyLoader] - private void load() + private void load(INotificationOverlay notificationOverlay) { + this.notificationOverlay = notificationOverlay; + Text = SkinSettingsStrings.ExportSkinButton; Action = export; } @@ -162,7 +167,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage).Export(s)); + currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage, notificationOverlay).Export(s)); } catch (Exception e) { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index bb390dfbf3..03bdd69f34 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -93,6 +93,9 @@ namespace osu.Game.Screens.Edit [Resolved] private Storage storage { get; set; } + [Resolved] + private INotificationOverlay notificationOverlay { get; set; } + [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -938,7 +941,7 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { Save(); - new LegacyBeatmapExporter(storage).Export(Beatmap.Value.BeatmapSetInfo); + new LegacyBeatmapExporter(storage, notificationOverlay).Export(Beatmap.Value.BeatmapSetInfo); } /// From 4b29941b4705a38ea26ce4ca617caf75c3be4f1a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 17 Nov 2022 23:38:24 +0900 Subject: [PATCH 0014/1400] add `LegacyExportManager` --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 4 +- osu.Game/Database/LegacyBeatmapExporter.cs | 8 +- osu.Game/Database/LegacyExportManager.cs | 55 +++++++++ osu.Game/Database/LegacyExporter.cs | 102 ---------------- osu.Game/Database/LegacyModelExporter.cs | 113 ++++++++++++++++++ osu.Game/Database/LegacyScoreExporter.cs | 34 +++--- osu.Game/Database/LegacySkinExporter.cs | 8 +- .../Online/Leaderboards/LeaderboardScore.cs | 5 +- osu.Game/OsuGame.cs | 4 + .../Overlays/Settings/Sections/SkinSection.cs | 10 +- osu.Game/Screens/Edit/Editor.cs | 9 +- 11 files changed, 209 insertions(+), 143 deletions(-) create mode 100644 osu.Game/Database/LegacyExportManager.cs delete mode 100644 osu.Game/Database/LegacyExporter.cs create mode 100644 osu.Game/Database/LegacyModelExporter.cs diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 7a5f6dbd7c..ef68b06476 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -121,9 +121,9 @@ namespace osu.Game.Tests.Skins.IO var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "custom.osk")); assertCorrectMetadata(import1, "name 1 [custom]", "author 1", osu); - import1.PerformRead(s => + import1.PerformRead(async s => { - new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); + await new LegacyExportManager().ExportAsync(s, exportStream); }); string exportFilename = import1.GetDisplayString(); diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 3e11e898f3..140ce43fbd 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -3,16 +3,16 @@ using osu.Framework.Platform; using osu.Game.Beatmaps; -using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; namespace osu.Game.Database { - public class LegacyBeatmapExporter : LegacyExporter + public class LegacyBeatmapExporter : LegacyModelExporter { protected override string FileExtension => ".osz"; - public LegacyBeatmapExporter(Storage storage, INotificationOverlay? notificationOverlay) - : base(storage, notificationOverlay) + public LegacyBeatmapExporter(Storage storage, RealmAccess realm, ProgressNotification notification) + : base(storage, realm, notification) { } } diff --git a/osu.Game/Database/LegacyExportManager.cs b/osu.Game/Database/LegacyExportManager.cs new file mode 100644 index 0000000000..18cd93ea35 --- /dev/null +++ b/osu.Game/Database/LegacyExportManager.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; +using osu.Game.Scoring; +using osu.Game.Skinning; + +namespace osu.Game.Database +{ + [ExcludeFromDynamicCompile] + public class LegacyExportManager : Component + { + [Resolved] + private RealmAccess realmAccess { get; set; } = null!; + + [Resolved] + private Storage exportStorage { get; set; } = null!; + + [Resolved] + private INotificationOverlay? notifications { get; set; } + + public async Task ExportAsync(IHasGuidPrimaryKey item) + { + var notification = new ProgressNotification + { + State = ProgressNotificationState.Active, + Text = "Exporting...", + CompletionText = "Export completed" + }; + notifications?.Post(notification); + + switch (item) + { + case SkinInfo: + await new LegacySkinExporter(exportStorage, realmAccess, notification).ExportASync(item); + break; + + case ScoreInfo: + await new LegacyScoreExporter(exportStorage, realmAccess, notification).ExportASync(item, false); + break; + + case BeatmapSetInfo: + await new LegacyBeatmapExporter(exportStorage, realmAccess, notification).ExportASync(item); + break; + } + } + } +} diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs deleted file mode 100644 index ed16e4bc80..0000000000 --- a/osu.Game/Database/LegacyExporter.cs +++ /dev/null @@ -1,102 +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.IO; -using System.Threading.Tasks; -using osu.Framework.Platform; -using osu.Game.Extensions; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; -using SharpCompress.Archives.Zip; - -namespace osu.Game.Database -{ - /// - /// A class which handles exporting legacy user data of a single type from osu-stable. - /// - public abstract class LegacyExporter - where TModel : class, IHasNamedFiles - { - /// - /// The file extension for exports (including the leading '.'). - /// - protected abstract string FileExtension { get; } - - protected readonly Storage UserFileStorage; - - private readonly Storage exportStorage; - - private readonly INotificationOverlay? notificationOverlay; - - protected ProgressNotification Notification = null!; - - private string filename = null!; - - protected LegacyExporter(Storage storage, INotificationOverlay? notificationOverlay) - { - exportStorage = storage.GetStorageForDirectory(@"exports"); - UserFileStorage = storage.GetStorageForDirectory(@"files"); - this.notificationOverlay = notificationOverlay; - } - - /// - /// Exports an item to a legacy (.zip based) package. - /// - /// The item to export. - public void Export(TModel item) - { - filename = $"{item.GetDisplayString().GetValidFilename()}{FileExtension}"; - - Stream stream = exportStorage.CreateFileSafely(filename); - - Notification = new ProgressNotification - { - State = ProgressNotificationState.Active, - Text = "Exporting...", - CompletionText = "Export completed" - }; - Notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - Notification.CancelRequested += () => - { - stream.Dispose(); - return true; - }; - - ExportModelTo(item, stream); - notificationOverlay?.Post(Notification); - } - - /// - /// Exports an item to the given output stream. - /// - /// The item to export. - /// The output stream to export to. - public virtual void ExportModelTo(TModel model, Stream outputStream) - { - using (var archive = ZipArchive.Create()) - { - foreach (var file in model.Files) - archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - - Task.Factory.StartNew(() => - { - archive.SaveTo(outputStream); - }, Notification.CancellationToken).ContinueWith(t => - { - if (t.IsCompletedSuccessfully) - { - outputStream.Dispose(); - Notification.State = ProgressNotificationState.Completed; - } - else - { - if (Notification.State == ProgressNotificationState.Cancelled) return; - - Notification.State = ProgressNotificationState.Cancelled; - Notification.Text = "Export Failed"; - } - }); - } - } - } -} diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs new file mode 100644 index 0000000000..d181226803 --- /dev/null +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -0,0 +1,113 @@ +// 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.Linq; +using System.Threading.Tasks; +using osu.Framework.Platform; +using osu.Game.Extensions; +using osu.Game.Overlays.Notifications; +using Realms; +using SharpCompress.Archives.Zip; + +namespace osu.Game.Database +{ + /// + /// A class which handles exporting legacy user data of a single type from osu-stable. + /// + public abstract class LegacyModelExporter + where TModel : RealmObject + { + /// + /// The file extension for exports (including the leading '.'). + /// + protected abstract string FileExtension { get; } + + protected readonly Storage UserFileStorage; + + private readonly Storage exportStorage; + + private readonly RealmAccess realmAccess; + + private readonly ProgressNotification notification; + + protected ProgressNotification Notification = null!; + + private string filename = null!; + + protected LegacyModelExporter(Storage storage, RealmAccess realm, ProgressNotification notification) + { + exportStorage = storage.GetStorageForDirectory(@"exports"); + UserFileStorage = storage.GetStorageForDirectory(@"files"); + this.notification = notification; + realmAccess = realm; + } + + public async Task ExportASync(IHasGuidPrimaryKey uuid, bool needZipArchive = true) + { + Guid id = uuid.ID; + await Task.Run(() => + { + realmAccess.Run(r => + { + if (r.Find(id) is IHasNamedFiles model) + { + filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; + } + else + { + return; + } + + using (var outputStream = exportStorage.CreateFileSafely(filename)) + { + if (needZipArchive) + { + using (var archive = ZipArchive.Create()) + { + float i = 0; + + foreach (var file in model.Files) + { + if (notification.CancellationToken.IsCancellationRequested) return; + archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } + + notification.Text = "Saving Zip Archive..."; + archive.SaveTo(outputStream); + } + } + else + { + var file = model.Files.SingleOrDefault(); + if (file == null) + return; + + using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) + inputStream.CopyTo(outputStream); + } + } + }); + }).ContinueWith(t => + { + if (t.IsFaulted) + { + notification.State = ProgressNotificationState.Cancelled; + return; + } + + if (notification.CancellationToken.IsCancellationRequested) + { + return; + } + + notification.CompletionText = "Export Complete, Click to open the folder"; + notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + notification.State = ProgressNotificationState.Completed; + }); + } + } +} diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 1564c7b077..ffbec0530b 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -1,36 +1,32 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.IO; -using System.Linq; using osu.Framework.Platform; -using osu.Game.Extensions; -using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Scoring; namespace osu.Game.Database { - public class LegacyScoreExporter : LegacyExporter + public class LegacyScoreExporter : LegacyModelExporter { protected override string FileExtension => ".osr"; - public LegacyScoreExporter(Storage storage, INotificationOverlay? notificationOverlay) - : base(storage, notificationOverlay) + public LegacyScoreExporter(Storage storage, RealmAccess realm, ProgressNotification notification) + : base(storage, realm, notification) { } - public override void ExportModelTo(ScoreInfo model, Stream outputStream) - { - var file = model.Files.SingleOrDefault(); - if (file == null) - return; - - using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - inputStream.CopyTo(outputStream); - - Notification.State = ProgressNotificationState.Completed; - outputStream.Dispose(); - } + //public override void ExportModelTo(ScoreInfo model, Stream outputStream) + //{ + // var file = model.Files.SingleOrDefault(); + // if (file == null) + // return; + // + // using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) + // inputStream.CopyTo(outputStream); + // + // Notification.State = ProgressNotificationState.Completed; + // outputStream.Dispose(); + //} } } diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index a78d69e7b9..a35636c248 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -2,17 +2,17 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Platform; -using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Skinning; namespace osu.Game.Database { - public class LegacySkinExporter : LegacyExporter + public class LegacySkinExporter : LegacyModelExporter { protected override string FileExtension => ".osk"; - public LegacySkinExporter(Storage storage, INotificationOverlay? notificationOverlay) - : base(storage, notificationOverlay) + public LegacySkinExporter(Storage storage, RealmAccess realm, ProgressNotification notification) + : base(storage, realm, notification) { } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 72f1a94ec8..e2f640a44c 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -76,7 +77,7 @@ namespace osu.Game.Online.Leaderboards private Storage storage { get; set; } [Resolved] - private INotificationOverlay notificationOverlay { get; set; } + private LegacyExportManager exporter { get; set; } public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => Score; @@ -430,7 +431,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage, notificationOverlay).Export(Score))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => exporter.ExportAsync(Score)))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a93c187e53..09647f9d1e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -126,6 +126,9 @@ namespace osu.Game [Cached] private readonly LegacyImportManager legacyImportManager = new LegacyImportManager(); + [Cached] + private readonly LegacyExportManager legacyExportManager = new LegacyExportManager(); + [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); @@ -868,6 +871,7 @@ namespace osu.Game }), rightFloatingOverlayContent.Add, true); loadComponentSingleFile(legacyImportManager, Add); + loadComponentSingleFile(legacyExportManager, Add); loadComponentSingleFile(screenshotManager, Add); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index df6f719b1e..6cd9e591e1 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -141,16 +141,14 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private Storage storage { get; set; } - [CanBeNull] - private INotificationOverlay notificationOverlay; + [Resolved] + private LegacyExportManager exporter { get; set; } private Bindable currentSkin; [BackgroundDependencyLoader] - private void load(INotificationOverlay notificationOverlay) + private void load() { - this.notificationOverlay = notificationOverlay; - Text = SkinSettingsStrings.ExportSkinButton; Action = export; } @@ -167,7 +165,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage, notificationOverlay).Export(s)); + currentSkin.Value.SkinInfo.PerformRead(s => exporter.ExportAsync(s)); } catch (Exception e) { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 03bdd69f34..e266239f34 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; @@ -93,9 +94,6 @@ namespace osu.Game.Screens.Edit [Resolved] private Storage storage { get; set; } - [Resolved] - private INotificationOverlay notificationOverlay { get; set; } - [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -185,6 +183,9 @@ namespace osu.Game.Screens.Edit private Bindable editorBackgroundDim; private Bindable editorHitMarkers; + [Resolved] + private LegacyExportManager exporter { get; set; } + public Editor(EditorLoader loader = null) { this.loader = loader; @@ -941,7 +942,7 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { Save(); - new LegacyBeatmapExporter(storage, notificationOverlay).Export(Beatmap.Value.BeatmapSetInfo); + Task.Run(() => exporter.ExportAsync(Beatmap.Value.BeatmapSetInfo)); } /// From fc4a6cb125c50668765d8b43f5bcf88cb242f28c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 19 Nov 2022 01:02:35 +0900 Subject: [PATCH 0015/1400] working with test --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 31 +++--- osu.Game/Database/LegacyBeatmapExporter.cs | 5 +- osu.Game/Database/LegacyExportManager.cs | 2 +- osu.Game/Database/LegacyModelExporter.cs | 106 +++++++++++---------- osu.Game/Database/LegacyScoreExporter.cs | 52 +++++++--- osu.Game/Database/LegacySkinExporter.cs | 5 +- 6 files changed, 113 insertions(+), 88 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index ef68b06476..0c3c459e87 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -10,12 +10,11 @@ using System.Runtime.CompilerServices; using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; -using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Skinning; using SharpCompress.Archives.Zip; @@ -121,9 +120,9 @@ namespace osu.Game.Tests.Skins.IO var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "custom.osk")); assertCorrectMetadata(import1, "name 1 [custom]", "author 1", osu); - import1.PerformRead(async s => + await import1.PerformRead(async s => { - await new LegacyExportManager().ExportAsync(s, exportStream); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); }); string exportFilename = import1.GetDisplayString(); @@ -190,7 +189,7 @@ namespace osu.Game.Tests.Skins.IO }); [Test] - public Task TestExportThenImportDefaultSkin() => runSkinTest(osu => + public Task TestExportThenImportDefaultSkin() => runSkinTest(async osu => { var skinManager = osu.Dependencies.Get(); @@ -200,30 +199,28 @@ namespace osu.Game.Tests.Skins.IO Guid originalSkinId = skinManager.CurrentSkinInfo.Value.ID; - skinManager.CurrentSkinInfo.Value.PerformRead(s => + await skinManager.CurrentSkinInfo.Value.PerformRead(async s => { Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); - new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); Assert.Greater(exportStream.Length, 0); }); - var imported = skinManager.Import(new ImportTask(exportStream, "exported.osk")); + var imported = await skinManager.Import(new ImportTask(exportStream, "exported.osk")); - imported.GetResultSafely().PerformRead(s => + imported.PerformRead(s => { Assert.IsFalse(s.Protected); Assert.AreNotEqual(originalSkinId, s.ID); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); }); - - return Task.CompletedTask; }); [Test] - public Task TestExportThenImportClassicSkin() => runSkinTest(osu => + public Task TestExportThenImportClassicSkin() => runSkinTest(async osu => { var skinManager = osu.Dependencies.Get(); @@ -235,26 +232,24 @@ namespace osu.Game.Tests.Skins.IO Guid originalSkinId = skinManager.CurrentSkinInfo.Value.ID; - skinManager.CurrentSkinInfo.Value.PerformRead(s => + await skinManager.CurrentSkinInfo.Value.PerformRead(async s => { Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); - new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportModelTo(s, exportStream); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); Assert.Greater(exportStream.Length, 0); }); - var imported = skinManager.Import(new ImportTask(exportStream, "exported.osk")); + var imported = await skinManager.Import(new ImportTask(exportStream, "exported.osk")); - imported.GetResultSafely().PerformRead(s => + imported.PerformRead(s => { Assert.IsFalse(s.Protected); Assert.AreNotEqual(originalSkinId, s.ID); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); }); - - return Task.CompletedTask; }); #endregion diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 140ce43fbd..5505d141ee 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.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 System.IO; using osu.Framework.Platform; using osu.Game.Beatmaps; using osu.Game.Overlays.Notifications; @@ -11,8 +12,8 @@ namespace osu.Game.Database { protected override string FileExtension => ".osz"; - public LegacyBeatmapExporter(Storage storage, RealmAccess realm, ProgressNotification notification) - : base(storage, realm, notification) + public LegacyBeatmapExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) + : base(storage, realm, notification, stream) { } } diff --git a/osu.Game/Database/LegacyExportManager.cs b/osu.Game/Database/LegacyExportManager.cs index 18cd93ea35..08594ab020 100644 --- a/osu.Game/Database/LegacyExportManager.cs +++ b/osu.Game/Database/LegacyExportManager.cs @@ -43,7 +43,7 @@ namespace osu.Game.Database break; case ScoreInfo: - await new LegacyScoreExporter(exportStorage, realmAccess, notification).ExportASync(item, false); + await new LegacyScoreExporter(exportStorage, realmAccess, notification).ExportASync(item); break; case BeatmapSetInfo: diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index d181226803..a4b0f7ba9d 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.IO; using System.Linq; using System.Threading.Tasks; using osu.Framework.Platform; @@ -25,89 +26,92 @@ namespace osu.Game.Database protected readonly Storage UserFileStorage; - private readonly Storage exportStorage; + protected readonly Storage ExportStorage; - private readonly RealmAccess realmAccess; + protected readonly RealmAccess RealmAccess; - private readonly ProgressNotification notification; + protected readonly ProgressNotification Notification; - protected ProgressNotification Notification = null!; + protected string Filename = null!; - private string filename = null!; + protected Stream? OutputStream; - protected LegacyModelExporter(Storage storage, RealmAccess realm, ProgressNotification notification) + protected bool ShouldDisposeStream; + + protected LegacyModelExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) { - exportStorage = storage.GetStorageForDirectory(@"exports"); + ExportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); - this.notification = notification; - realmAccess = realm; + Notification = notification; + RealmAccess = realm; + OutputStream = stream; + ShouldDisposeStream = false; } - public async Task ExportASync(IHasGuidPrimaryKey uuid, bool needZipArchive = true) + public virtual async Task ExportASync(IHasGuidPrimaryKey uuid) { Guid id = uuid.ID; await Task.Run(() => { - realmAccess.Run(r => + RealmAccess.Run(r => { if (r.Find(id) is IHasNamedFiles model) { - filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; + Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; } else { return; } - using (var outputStream = exportStorage.CreateFileSafely(filename)) + if (OutputStream == null) { - if (needZipArchive) + OutputStream = ExportStorage.CreateFileSafely(Filename); + ShouldDisposeStream = true; + } + + using (var archive = ZipArchive.Create()) + { + float i = 0; + + foreach (var file in model.Files) { - using (var archive = ZipArchive.Create()) - { - float i = 0; + if (Notification.CancellationToken.IsCancellationRequested) return; - foreach (var file in model.Files) - { - if (notification.CancellationToken.IsCancellationRequested) return; - archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; - } - - notification.Text = "Saving Zip Archive..."; - archive.SaveTo(outputStream); - } + archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + i++; + Notification.Progress = i / model.Files.Count(); + Notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; } - else - { - var file = model.Files.SingleOrDefault(); - if (file == null) - return; - using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - inputStream.CopyTo(outputStream); - } + Notification.Text = "Saving Zip Archive..."; + archive.SaveTo(OutputStream); } }); - }).ContinueWith(t => + }).ContinueWith(OnComplete); + } + + protected void OnComplete(Task t) + { + if (ShouldDisposeStream) { - if (t.IsFaulted) - { - notification.State = ProgressNotificationState.Cancelled; - return; - } + OutputStream?.Dispose(); + } - if (notification.CancellationToken.IsCancellationRequested) - { - return; - } + if (t.IsFaulted) + { + Notification.State = ProgressNotificationState.Cancelled; + return; + } - notification.CompletionText = "Export Complete, Click to open the folder"; - notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - notification.State = ProgressNotificationState.Completed; - }); + if (Notification.CancellationToken.IsCancellationRequested) + { + return; + } + + Notification.CompletionText = "Export Complete, Click to open the folder"; + Notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(Filename); + Notification.State = ProgressNotificationState.Completed; } } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index ffbec0530b..3004c02978 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -1,7 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.IO; +using System.Linq; +using System.Threading.Tasks; using osu.Framework.Platform; +using osu.Game.Extensions; using osu.Game.Overlays.Notifications; using osu.Game.Scoring; @@ -11,22 +15,42 @@ namespace osu.Game.Database { protected override string FileExtension => ".osr"; - public LegacyScoreExporter(Storage storage, RealmAccess realm, ProgressNotification notification) - : base(storage, realm, notification) + public LegacyScoreExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) + : base(storage, realm, notification, stream) { } - //public override void ExportModelTo(ScoreInfo model, Stream outputStream) - //{ - // var file = model.Files.SingleOrDefault(); - // if (file == null) - // return; - // - // using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - // inputStream.CopyTo(outputStream); - // - // Notification.State = ProgressNotificationState.Completed; - // outputStream.Dispose(); - //} + public override async Task ExportASync(IHasGuidPrimaryKey uuid) + { + await Task.Run(() => + { + RealmAccess.Run(r => + { + if (r.Find(uuid.ID) is IHasNamedFiles model) + { + Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; + } + else + { + return; + } + + var file = model.Files.SingleOrDefault(); + if (file == null) + return; + + if (Notification.CancellationToken.IsCancellationRequested) return; + + if (OutputStream == null) + { + OutputStream = ExportStorage.CreateFileSafely(Filename); + ShouldDisposeStream = true; + } + + using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) + inputStream.CopyTo(OutputStream); + }); + }).ContinueWith(OnComplete); + } } } diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index a35636c248..4168763324 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.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 System.IO; using osu.Framework.Platform; using osu.Game.Overlays.Notifications; using osu.Game.Skinning; @@ -11,8 +12,8 @@ namespace osu.Game.Database { protected override string FileExtension => ".osk"; - public LegacySkinExporter(Storage storage, RealmAccess realm, ProgressNotification notification) - : base(storage, realm, notification) + public LegacySkinExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) + : base(storage, realm, notification, stream) { } } From 4e457871f3a518b05d6d95e7637c74b7ddc978fb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 19 Nov 2022 01:03:09 +0900 Subject: [PATCH 0016/1400] impossible null and remove storage --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 12 ++++-------- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 8 ++------ osu.Game/Screens/Edit/Editor.cs | 8 ++------ 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e2f640a44c..b374736648 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -18,7 +18,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; -using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Graphics; @@ -67,16 +66,13 @@ namespace osu.Game.Online.Leaderboards private List statisticsLabels; - [Resolved(CanBeNull = true)] + [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } - [Resolved(CanBeNull = true)] + [Resolved(canBeNull: true)] private SongSelect songSelect { get; set; } - [Resolved] - private Storage storage { get; set; } - - [Resolved] + [Resolved(canBeNull: true)] private LegacyExportManager exporter { get; set; } public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); @@ -431,7 +427,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => exporter.ExportAsync(Score)))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => exporter?.ExportAsync(Score)))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 6cd9e591e1..e5a26c19fc 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; @@ -138,10 +137,7 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private SkinManager skins { get; set; } - [Resolved] - private Storage storage { get; set; } - - [Resolved] + [Resolved(canBeNull: true)] private LegacyExportManager exporter { get; set; } private Bindable currentSkin; @@ -165,7 +161,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - currentSkin.Value.SkinInfo.PerformRead(s => exporter.ExportAsync(s)); + currentSkin.Value.SkinInfo.PerformRead(s => exporter?.ExportAsync(s)); } catch (Exception e) { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index e266239f34..77f14f689a 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -21,7 +21,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Threading; @@ -91,9 +90,6 @@ namespace osu.Game.Screens.Edit [Resolved] private RulesetStore rulesets { get; set; } - [Resolved] - private Storage storage { get; set; } - [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -183,7 +179,7 @@ namespace osu.Game.Screens.Edit private Bindable editorBackgroundDim; private Bindable editorHitMarkers; - [Resolved] + [Resolved(canBeNull: true)] private LegacyExportManager exporter { get; set; } public Editor(EditorLoader loader = null) @@ -942,7 +938,7 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { Save(); - Task.Run(() => exporter.ExportAsync(Beatmap.Value.BeatmapSetInfo)); + Task.Run(() => exporter?.ExportAsync(Beatmap.Value.BeatmapSetInfo)); } /// From 28867fbbb1750640a30113d576500d0a82502db7 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 19 Nov 2022 12:34:35 +0900 Subject: [PATCH 0017/1400] Add comment --- osu.Game/Database/LegacyExportManager.cs | 18 ++++++++++++++---- osu.Game/Database/LegacyModelExporter.cs | 6 ++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/LegacyExportManager.cs b/osu.Game/Database/LegacyExportManager.cs index 08594ab020..19fca623c5 100644 --- a/osu.Game/Database/LegacyExportManager.cs +++ b/osu.Game/Database/LegacyExportManager.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 System.IO; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -14,6 +15,9 @@ using osu.Game.Skinning; namespace osu.Game.Database { + /// + /// A class which centrally manage legacy file exports. + /// [ExcludeFromDynamicCompile] public class LegacyExportManager : Component { @@ -26,7 +30,13 @@ namespace osu.Game.Database [Resolved] private INotificationOverlay? notifications { get; set; } - public async Task ExportAsync(IHasGuidPrimaryKey item) + /// + /// Identify the model type and and automatically assigned to the corresponding exporter. + /// + /// The model should export. + /// The stream if requires a specific output-stream + /// + public async Task ExportAsync(IHasGuidPrimaryKey item, Stream? stream = null) { var notification = new ProgressNotification { @@ -39,15 +49,15 @@ namespace osu.Game.Database switch (item) { case SkinInfo: - await new LegacySkinExporter(exportStorage, realmAccess, notification).ExportASync(item); + await new LegacySkinExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); break; case ScoreInfo: - await new LegacyScoreExporter(exportStorage, realmAccess, notification).ExportASync(item); + await new LegacyScoreExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); break; case BeatmapSetInfo: - await new LegacyBeatmapExporter(exportStorage, realmAccess, notification).ExportASync(item); + await new LegacyBeatmapExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); break; } } diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index a4b0f7ba9d..d734d3341c 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -48,6 +48,12 @@ namespace osu.Game.Database ShouldDisposeStream = false; } + /// + /// Export model to + /// if is null, model will export to default folder. + /// + /// The model which have Guid. + /// public virtual async Task ExportASync(IHasGuidPrimaryKey uuid) { Guid id = uuid.ID; From 2653bd2f997c305d1497d74da66e33be9630cc84 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 19 Nov 2022 12:57:56 +0900 Subject: [PATCH 0018/1400] Make notification cannot cancel when Saving Zip Archive This operation cannot be stopped(if not dispose stream). so make it cannot cancel --- osu.Game/Database/LegacyModelExporter.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index d734d3341c..9fa6f64ee4 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -56,6 +56,9 @@ namespace osu.Game.Database /// public virtual async Task ExportASync(IHasGuidPrimaryKey uuid) { + bool canCancel = true; + Notification.CancelRequested += () => canCancel; + Guid id = uuid.ID; await Task.Run(() => { @@ -91,6 +94,7 @@ namespace osu.Game.Database } Notification.Text = "Saving Zip Archive..."; + canCancel = false; archive.SaveTo(OutputStream); } }); From 60ef88844c31459dfa94a5ffdb1fdf41530f2c96 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 17:09:56 +0900 Subject: [PATCH 0019/1400] Recover accidentally deleted codes --- osu.Game/Database/RealmAccess.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 5a7ead1c59..1a938c12e5 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -173,6 +173,11 @@ namespace osu.Game.Database if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal)) Filename += realm_extension; +#if DEBUG + if (!DebugUtils.IsNUnitRunning) + applyFilenameSchemaSuffix(ref Filename); +#endif + string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}"; // Attempt to recover a newer database version if available. From ed53168267485ba0ca2bdc97057fd43566770cd4 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 17:42:11 +0900 Subject: [PATCH 0020/1400] typo fix --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 6 +++--- osu.Game/Database/LegacyExportManager.cs | 4 ++-- osu.Game/Database/LegacyModelExporter.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 0c3c459e87..c4dde59e3f 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Skins.IO await import1.PerformRead(async s => { - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); }); string exportFilename = import1.GetDisplayString(); @@ -204,7 +204,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); Assert.Greater(exportStream.Length, 0); }); @@ -237,7 +237,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportASync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); Assert.Greater(exportStream.Length, 0); }); diff --git a/osu.Game/Database/LegacyExportManager.cs b/osu.Game/Database/LegacyExportManager.cs index 19fca623c5..a694a0705e 100644 --- a/osu.Game/Database/LegacyExportManager.cs +++ b/osu.Game/Database/LegacyExportManager.cs @@ -49,7 +49,7 @@ namespace osu.Game.Database switch (item) { case SkinInfo: - await new LegacySkinExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); + await new LegacySkinExporter(exportStorage, realmAccess, notification, stream).ExportAsync(item); break; case ScoreInfo: @@ -57,7 +57,7 @@ namespace osu.Game.Database break; case BeatmapSetInfo: - await new LegacyBeatmapExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); + await new LegacyBeatmapExporter(exportStorage, realmAccess, notification, stream).ExportAsync(item); break; } } diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 9fa6f64ee4..01ebbdcaff 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -54,11 +54,11 @@ namespace osu.Game.Database /// /// The model which have Guid. /// - public virtual async Task ExportASync(IHasGuidPrimaryKey uuid) { bool canCancel = true; Notification.CancelRequested += () => canCancel; + public virtual async Task ExportAsync(IHasGuidPrimaryKey uuid) Guid id = uuid.ID; await Task.Run(() => { From e37d30a3733871eb39622d6f5ea95d6cfe22a5a6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 18:58:01 +0900 Subject: [PATCH 0021/1400] refactor based on reviews removed LegacyExportManager Separated the method of CreateZip method and the default export method --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 7 +- osu.Game/Database/LegacyBeatmapExporter.cs | 11 +- osu.Game/Database/LegacyExportManager.cs | 65 --------- osu.Game/Database/LegacyModelExporter.cs | 128 +++++++++--------- osu.Game/Database/LegacyScoreExporter.cs | 33 ++--- osu.Game/Database/LegacySkinExporter.cs | 11 +- .../Online/Leaderboards/LeaderboardScore.cs | 13 +- osu.Game/OsuGame.cs | 4 - .../Overlays/Settings/Sections/SkinSection.cs | 13 +- osu.Game/Screens/Edit/Editor.cs | 12 +- 10 files changed, 113 insertions(+), 184 deletions(-) delete mode 100644 osu.Game/Database/LegacyExportManager.cs diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index c4dde59e3f..703c63b91a 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -14,7 +14,6 @@ using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.IO; -using osu.Game.Overlays.Notifications; using osu.Game.Skinning; using SharpCompress.Archives.Zip; @@ -122,7 +121,7 @@ namespace osu.Game.Tests.Skins.IO await import1.PerformRead(async s => { - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); }); string exportFilename = import1.GetDisplayString(); @@ -204,7 +203,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); Assert.Greater(exportStream.Length, 0); }); @@ -237,7 +236,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get(), new ProgressNotification(), exportStream).ExportAsync(s); + await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); Assert.Greater(exportStream.Length, 0); }); diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 5505d141ee..22bccbcda6 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -1,20 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.IO; using osu.Framework.Platform; using osu.Game.Beatmaps; -using osu.Game.Overlays.Notifications; +using osu.Game.Overlays; namespace osu.Game.Database { public class LegacyBeatmapExporter : LegacyModelExporter { - protected override string FileExtension => ".osz"; - - public LegacyBeatmapExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) - : base(storage, realm, notification, stream) + public LegacyBeatmapExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) + : base(storage, realm, notifications) { } + + protected override string FileExtension => ".osz"; } } diff --git a/osu.Game/Database/LegacyExportManager.cs b/osu.Game/Database/LegacyExportManager.cs deleted file mode 100644 index a694a0705e..0000000000 --- a/osu.Game/Database/LegacyExportManager.cs +++ /dev/null @@ -1,65 +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.IO; -using System.Threading.Tasks; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Platform; -using osu.Framework.Testing; -using osu.Game.Beatmaps; -using osu.Game.Overlays; -using osu.Game.Overlays.Notifications; -using osu.Game.Scoring; -using osu.Game.Skinning; - -namespace osu.Game.Database -{ - /// - /// A class which centrally manage legacy file exports. - /// - [ExcludeFromDynamicCompile] - public class LegacyExportManager : Component - { - [Resolved] - private RealmAccess realmAccess { get; set; } = null!; - - [Resolved] - private Storage exportStorage { get; set; } = null!; - - [Resolved] - private INotificationOverlay? notifications { get; set; } - - /// - /// Identify the model type and and automatically assigned to the corresponding exporter. - /// - /// The model should export. - /// The stream if requires a specific output-stream - /// - public async Task ExportAsync(IHasGuidPrimaryKey item, Stream? stream = null) - { - var notification = new ProgressNotification - { - State = ProgressNotificationState.Active, - Text = "Exporting...", - CompletionText = "Export completed" - }; - notifications?.Post(notification); - - switch (item) - { - case SkinInfo: - await new LegacySkinExporter(exportStorage, realmAccess, notification, stream).ExportAsync(item); - break; - - case ScoreInfo: - await new LegacyScoreExporter(exportStorage, realmAccess, notification, stream).ExportASync(item); - break; - - case BeatmapSetInfo: - await new LegacyBeatmapExporter(exportStorage, realmAccess, notification, stream).ExportAsync(item); - break; - } - } - } -} diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 01ebbdcaff..83167e7319 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -5,8 +5,10 @@ using System; using System.IO; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Extensions; +using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using Realms; using SharpCompress.Archives.Zip; @@ -16,112 +18,106 @@ namespace osu.Game.Database /// /// A class which handles exporting legacy user data of a single type from osu-stable. /// - public abstract class LegacyModelExporter - where TModel : RealmObject + public abstract class LegacyModelExporter : Component + where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { /// /// The file extension for exports (including the leading '.'). /// protected abstract string FileExtension { get; } - protected readonly Storage UserFileStorage; + protected Storage UserFileStorage; + protected Storage ExportStorage; - protected readonly Storage ExportStorage; + protected RealmAccess RealmAccess; - protected readonly RealmAccess RealmAccess; - - protected readonly ProgressNotification Notification; + private readonly ProgressNotification notification; protected string Filename = null!; - protected Stream? OutputStream; + private bool canCancel = true; - protected bool ShouldDisposeStream; - - protected LegacyModelExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) + protected LegacyModelExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) { ExportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); - Notification = notification; RealmAccess = realm; - OutputStream = stream; - ShouldDisposeStream = false; + + notification = new ProgressNotification + { + State = ProgressNotificationState.Active, + Text = "Exporting...", + CompletionText = "Export completed" + }; + notification.CancelRequested += () => canCancel; + + notifications?.Post(notification); } - /// - /// Export model to - /// if is null, model will export to default folder. - /// - /// The model which have Guid. - /// + public async Task ExportAsync(RealmObject item) { - bool canCancel = true; - Notification.CancelRequested += () => canCancel; + if (item is TModel model) + { + Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; - public virtual async Task ExportAsync(IHasGuidPrimaryKey uuid) + using (var stream = ExportStorage.CreateFileSafely(Filename)) + { + await ExportToStreamAsync(model, stream); + } + } + } + + public virtual async Task ExportToStreamAsync(TModel uuid, Stream stream) + { Guid id = uuid.ID; await Task.Run(() => { RealmAccess.Run(r => { - if (r.Find(id) is IHasNamedFiles model) - { - Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; - } - else - { - return; - } - - if (OutputStream == null) - { - OutputStream = ExportStorage.CreateFileSafely(Filename); - ShouldDisposeStream = true; - } - - using (var archive = ZipArchive.Create()) - { - float i = 0; - - foreach (var file in model.Files) - { - if (Notification.CancellationToken.IsCancellationRequested) return; - - archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - i++; - Notification.Progress = i / model.Files.Count(); - Notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; - } - - Notification.Text = "Saving Zip Archive..."; - canCancel = false; - archive.SaveTo(OutputStream); - } + TModel model = r.Find(id); + createZipArchive(model, stream); }); }).ContinueWith(OnComplete); } + private void createZipArchive(TModel model, Stream outputStream) + { + using (var archive = ZipArchive.Create()) + { + float i = 0; + + foreach (var file in model.Files) + { + if (notification.CancellationToken.IsCancellationRequested) return; + + archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } + + notification.Text = "Saving Zip Archive..."; + canCancel = false; + archive.SaveTo(outputStream); + } + } + protected void OnComplete(Task t) { - if (ShouldDisposeStream) - { - OutputStream?.Dispose(); - } - if (t.IsFaulted) { - Notification.State = ProgressNotificationState.Cancelled; + notification.State = ProgressNotificationState.Cancelled; return; } - if (Notification.CancellationToken.IsCancellationRequested) + if (notification.CancellationToken.IsCancellationRequested) { return; } - Notification.CompletionText = "Export Complete, Click to open the folder"; - Notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(Filename); - Notification.State = ProgressNotificationState.Completed; + notification.CompletionText = "Export Complete, Click to open the folder"; + notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(Filename); + notification.State = ProgressNotificationState.Completed; } } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 3004c02978..e00bc2a0ca 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -6,49 +6,36 @@ using System.Linq; using System.Threading.Tasks; using osu.Framework.Platform; using osu.Game.Extensions; -using osu.Game.Overlays.Notifications; +using osu.Game.Overlays; using osu.Game.Scoring; namespace osu.Game.Database { public class LegacyScoreExporter : LegacyModelExporter { - protected override string FileExtension => ".osr"; - - public LegacyScoreExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) - : base(storage, realm, notification, stream) + public LegacyScoreExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) + : base(storage, realm, notifications) { } - public override async Task ExportASync(IHasGuidPrimaryKey uuid) + protected override string FileExtension => ".osr"; + + public override async Task ExportToStreamAsync(ScoreInfo uuid, Stream stream) { await Task.Run(() => { RealmAccess.Run(r => { - if (r.Find(uuid.ID) is IHasNamedFiles model) - { - Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; - } - else - { - return; - } + ScoreInfo model = r.Find(uuid.ID); + + Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; var file = model.Files.SingleOrDefault(); if (file == null) return; - if (Notification.CancellationToken.IsCancellationRequested) return; - - if (OutputStream == null) - { - OutputStream = ExportStorage.CreateFileSafely(Filename); - ShouldDisposeStream = true; - } - using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - inputStream.CopyTo(OutputStream); + inputStream.CopyTo(stream); }); }).ContinueWith(OnComplete); } diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 4168763324..6e65963f29 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -1,20 +1,19 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.IO; using osu.Framework.Platform; -using osu.Game.Overlays.Notifications; +using osu.Game.Overlays; using osu.Game.Skinning; namespace osu.Game.Database { public class LegacySkinExporter : LegacyModelExporter { - protected override string FileExtension => ".osk"; - - public LegacySkinExporter(Storage storage, RealmAccess realm, ProgressNotification notification, Stream? stream = null) - : base(storage, realm, notification, stream) + public LegacySkinExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) + : base(storage, realm, notifications) { } + + protected override string FileExtension => ".osk"; } } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index b374736648..0a9f2a81bd 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -34,6 +34,7 @@ using osuTK.Graphics; using osu.Game.Online.API; using osu.Game.Resources.Localisation.Web; using osu.Game.Utils; +using osu.Framework.Platform; namespace osu.Game.Online.Leaderboards { @@ -72,8 +73,14 @@ namespace osu.Game.Online.Leaderboards [Resolved(canBeNull: true)] private SongSelect songSelect { get; set; } - [Resolved(canBeNull: true)] - private LegacyExportManager exporter { get; set; } + [Resolved] + private Storage storage { get; set; } + + [Resolved] + private RealmAccess realm { get; set; } + + [Resolved] + private INotificationOverlay notifications { get; set; } public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => Score; @@ -427,7 +434,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => exporter?.ExportAsync(Score)))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => new LegacyScoreExporter(storage, realm, notifications).ExportAsync(Score)))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 09647f9d1e..a93c187e53 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -126,9 +126,6 @@ namespace osu.Game [Cached] private readonly LegacyImportManager legacyImportManager = new LegacyImportManager(); - [Cached] - private readonly LegacyExportManager legacyExportManager = new LegacyExportManager(); - [Cached] private readonly ScreenshotManager screenshotManager = new ScreenshotManager(); @@ -871,7 +868,6 @@ namespace osu.Game }), rightFloatingOverlayContent.Add, true); loadComponentSingleFile(legacyImportManager, Add); - loadComponentSingleFile(legacyExportManager, Add); loadComponentSingleFile(screenshotManager, Add); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index e5a26c19fc..46e760283d 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; +using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; @@ -137,8 +138,14 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private SkinManager skins { get; set; } - [Resolved(canBeNull: true)] - private LegacyExportManager exporter { get; set; } + [Resolved] + private Storage storage { get; set; } + + [Resolved] + private RealmAccess realm { get; set; } + + [Resolved] + private INotificationOverlay notifications { get; set; } private Bindable currentSkin; @@ -161,7 +168,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - currentSkin.Value.SkinInfo.PerformRead(s => exporter?.ExportAsync(s)); + currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage, realm, notifications).ExportAsync(s)); } catch (Exception e) { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 77f14f689a..e53c550a1a 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -21,6 +21,7 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Logging; +using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Threading; @@ -90,6 +91,12 @@ namespace osu.Game.Screens.Edit [Resolved] private RulesetStore rulesets { get; set; } + [Resolved] + private Storage storage { get; set; } + + [Resolved] + private RealmAccess realm { get; set; } + [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -179,9 +186,6 @@ namespace osu.Game.Screens.Edit private Bindable editorBackgroundDim; private Bindable editorHitMarkers; - [Resolved(canBeNull: true)] - private LegacyExportManager exporter { get; set; } - public Editor(EditorLoader loader = null) { this.loader = loader; @@ -938,7 +942,7 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { Save(); - Task.Run(() => exporter?.ExportAsync(Beatmap.Value.BeatmapSetInfo)); + Task.Run(() => new LegacyBeatmapExporter(storage, realm, notifications).ExportAsync(Beatmap.Value.BeatmapSetInfo)); } /// From 9c6421a462d67e30d9bf9d4b2cdf9171765ae97e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 19:00:10 +0900 Subject: [PATCH 0022/1400] log the error --- osu.Game/Database/LegacyModelExporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 83167e7319..9769a6d42a 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using osu.Framework.Graphics; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays; @@ -107,6 +108,8 @@ namespace osu.Game.Database if (t.IsFaulted) { notification.State = ProgressNotificationState.Cancelled; + Logger.Error(t.Exception, "An error occurred while exporting"); + return; } From 564f136945c0f3fef744014c5762f44145e325ae Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 19:04:05 +0900 Subject: [PATCH 0023/1400] add xmldoc --- osu.Game/Database/LegacyModelExporter.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 9769a6d42a..47068a8d2b 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -55,6 +55,11 @@ namespace osu.Game.Database notifications?.Post(notification); } + /// + /// Export the model to default folder. + /// + /// The model should export. + /// public async Task ExportAsync(RealmObject item) { if (item is TModel model) @@ -68,6 +73,12 @@ namespace osu.Game.Database } } + /// + /// Export te model corresponding to uuid to given stream. + /// + /// The medel which have . + /// The stream to export. + /// public virtual async Task ExportToStreamAsync(TModel uuid, Stream stream) { Guid id = uuid.ID; From 162f0bb95e1c525ce926935fafbcf98f3a76bdac Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 19:05:26 +0900 Subject: [PATCH 0024/1400] filename can be private --- osu.Game/Database/LegacyModelExporter.cs | 8 ++++---- osu.Game/Database/LegacyScoreExporter.cs | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 47068a8d2b..3780f2b9cc 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -34,7 +34,7 @@ namespace osu.Game.Database private readonly ProgressNotification notification; - protected string Filename = null!; + private string filename = ""; private bool canCancel = true; @@ -64,9 +64,9 @@ namespace osu.Game.Database { if (item is TModel model) { - Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; + filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; - using (var stream = ExportStorage.CreateFileSafely(Filename)) + using (var stream = ExportStorage.CreateFileSafely(filename)) { await ExportToStreamAsync(model, stream); } @@ -130,7 +130,7 @@ namespace osu.Game.Database } notification.CompletionText = "Export Complete, Click to open the folder"; - notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(Filename); + notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(filename); notification.State = ProgressNotificationState.Completed; } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index e00bc2a0ca..ae0fbf8d19 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -28,8 +28,6 @@ namespace osu.Game.Database { ScoreInfo model = r.Find(uuid.ID); - Filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; - var file = model.Files.SingleOrDefault(); if (file == null) return; From c509c5be40a449b872053e129358dd747b7e72f1 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 21 Nov 2022 19:45:30 +0900 Subject: [PATCH 0025/1400] impossible null --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 +- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 0a9f2a81bd..27c3e0ce47 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -79,7 +79,7 @@ namespace osu.Game.Online.Leaderboards [Resolved] private RealmAccess realm { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private INotificationOverlay notifications { get; set; } public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 46e760283d..eb51c18e31 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private RealmAccess realm { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private INotificationOverlay notifications { get; set; } private Bindable currentSkin; From 6adac853e85f7ebf81f61fa90a3d3afc8f556d0a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 27 Nov 2022 09:58:54 +0900 Subject: [PATCH 0026/1400] Spite sync method `ExportToStream` `uuid` to `model` --- osu.Game/Database/LegacyModelExporter.cs | 14 ++++++++------ osu.Game/Database/LegacyScoreExporter.cs | 21 ++++++--------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 3780f2b9cc..3523d18f29 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -74,24 +74,26 @@ namespace osu.Game.Database } /// - /// Export te model corresponding to uuid to given stream. + /// Export te model corresponding to model to given stream. /// - /// The medel which have . + /// The medel which have . /// The stream to export. /// - public virtual async Task ExportToStreamAsync(TModel uuid, Stream stream) + public async Task ExportToStreamAsync(TModel model, Stream stream) { - Guid id = uuid.ID; + Guid id = model.ID; await Task.Run(() => { RealmAccess.Run(r => { - TModel model = r.Find(id); - createZipArchive(model, stream); + TModel refetchModel = r.Find(id); + ExportToStream(refetchModel, stream); }); }).ContinueWith(OnComplete); } + protected virtual void ExportToStream(TModel model, Stream outputStream) => createZipArchive(model, outputStream); + private void createZipArchive(TModel model, Stream outputStream) { using (var archive = ZipArchive.Create()) diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index ae0fbf8d19..eb46bc6db2 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays; @@ -20,22 +19,14 @@ namespace osu.Game.Database protected override string FileExtension => ".osr"; - public override async Task ExportToStreamAsync(ScoreInfo uuid, Stream stream) + protected override void ExportToStream(ScoreInfo model, Stream stream) { - await Task.Run(() => - { - RealmAccess.Run(r => - { - ScoreInfo model = r.Find(uuid.ID); + var file = model.Files.SingleOrDefault(); + if (file == null) + return; - var file = model.Files.SingleOrDefault(); - if (file == null) - return; - - using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - inputStream.CopyTo(stream); - }); - }).ContinueWith(OnComplete); + using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) + inputStream.CopyTo(stream); } } } From 19afce67767b95e67aaf06ea1df8c5b291797ddd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 9 Dec 2022 23:41:07 +0900 Subject: [PATCH 0027/1400] Fix overwriting existing files https://github.com/ppy/osu/pull/21468 --- osu.Game/Database/LegacyModelExporter.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 3523d18f29..5c4b7a4578 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -11,6 +12,7 @@ using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Utils; using Realms; using SharpCompress.Archives.Zip; @@ -64,7 +66,11 @@ namespace osu.Game.Database { if (item is TModel model) { - filename = $"{model.GetDisplayString().GetValidFilename()}{FileExtension}"; + string itemFilename = item.GetDisplayString().GetValidFilename(); + + IEnumerable existingExports = ExportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); + + string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); using (var stream = ExportStorage.CreateFileSafely(filename)) { From 405985ec5b09769ca5d9031eadc2c8ad801b399d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 9 Dec 2022 23:57:03 +0900 Subject: [PATCH 0028/1400] remove Component exportStorage to private notification should post when export instead of class being constructed --- osu.Game/Database/LegacyModelExporter.cs | 25 ++++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 5c4b7a4578..ae092d15e8 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; -using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Extensions; @@ -21,7 +20,7 @@ namespace osu.Game.Database /// /// A class which handles exporting legacy user data of a single type from osu-stable. /// - public abstract class LegacyModelExporter : Component + public abstract class LegacyModelExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { /// @@ -30,22 +29,23 @@ namespace osu.Game.Database protected abstract string FileExtension { get; } protected Storage UserFileStorage; - protected Storage ExportStorage; + private readonly Storage exportStorage; protected RealmAccess RealmAccess; private readonly ProgressNotification notification; - private string filename = ""; - private bool canCancel = true; + private readonly INotificationOverlay? notifications; + protected LegacyModelExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) { - ExportStorage = storage.GetStorageForDirectory(@"exports"); + exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); RealmAccess = realm; + this.notifications = notifications; notification = new ProgressNotification { State = ProgressNotificationState.Active, @@ -53,8 +53,6 @@ namespace osu.Game.Database CompletionText = "Export completed" }; notification.CancelRequested += () => canCancel; - - notifications?.Post(notification); } /// @@ -66,13 +64,15 @@ namespace osu.Game.Database { if (item is TModel model) { + notifications?.Post(notification); + string itemFilename = item.GetDisplayString().GetValidFilename(); - - IEnumerable existingExports = ExportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); - + IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - using (var stream = ExportStorage.CreateFileSafely(filename)) + notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + + using (var stream = exportStorage.CreateFileSafely(filename)) { await ExportToStreamAsync(model, stream); } @@ -138,7 +138,6 @@ namespace osu.Game.Database } notification.CompletionText = "Export Complete, Click to open the folder"; - notification.CompletionClickAction += () => ExportStorage.PresentFileExternally(filename); notification.State = ProgressNotificationState.Completed; } } From 951302fe61374cb8b4cc1dedf830c6d8fe748ae6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 10 Dec 2022 00:43:03 +0900 Subject: [PATCH 0029/1400] ExportAsync use TModel --- osu.Game/Database/LegacyModelExporter.cs | 27 +++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index ae092d15e8..ad61338c8b 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -58,24 +58,21 @@ namespace osu.Game.Database /// /// Export the model to default folder. /// - /// The model should export. + /// The model should export. /// - public async Task ExportAsync(RealmObject item) + public async Task ExportAsync(TModel model) { - if (item is TModel model) + notifications?.Post(notification); + + string itemFilename = model.GetDisplayString().GetValidFilename(); + IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); + string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); + + notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + + using (var stream = exportStorage.CreateFileSafely(filename)) { - notifications?.Post(notification); - - string itemFilename = item.GetDisplayString().GetValidFilename(); - IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); - string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - - notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - - using (var stream = exportStorage.CreateFileSafely(filename)) - { - await ExportToStreamAsync(model, stream); - } + await ExportToStreamAsync(model, stream); } } From fa30f3348ff11e68c42b9b63082b5409ee479746 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 11 Dec 2022 16:53:11 +0900 Subject: [PATCH 0030/1400] `onComplete` should private --- osu.Game/Database/LegacyModelExporter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index ad61338c8b..4ea56c0056 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -92,7 +92,7 @@ namespace osu.Game.Database TModel refetchModel = r.Find(id); ExportToStream(refetchModel, stream); }); - }).ContinueWith(OnComplete); + }).ContinueWith(onComplete); } protected virtual void ExportToStream(TModel model, Stream outputStream) => createZipArchive(model, outputStream); @@ -119,7 +119,7 @@ namespace osu.Game.Database } } - protected void OnComplete(Task t) + private void onComplete(Task t) { if (t.IsFaulted) { From 2d5763340944ab99fcffb81f3c2915a441befa6e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 11 Dec 2022 16:54:20 +0900 Subject: [PATCH 0031/1400] rename method name and add xmldoc --- osu.Game/Database/LegacyModelExporter.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 4ea56c0056..cf41ffc780 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -95,9 +95,14 @@ namespace osu.Game.Database }).ContinueWith(onComplete); } - protected virtual void ExportToStream(TModel model, Stream outputStream) => createZipArchive(model, outputStream); + protected virtual void ExportToStream(TModel model, Stream outputStream) => exportZipArchive(model, outputStream); - private void createZipArchive(TModel model, Stream outputStream) + /// + /// Exports an item to Stream as a legacy (.zip based) package. + /// + /// The item to export. + /// The output stream to export to. + private void exportZipArchive(TModel model, Stream outputStream) { using (var archive = ZipArchive.Create()) { From a87bcccc42b2e69d619087b46b324499bfdd058a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 11 Dec 2022 16:55:44 +0900 Subject: [PATCH 0032/1400] xmldoc --- osu.Game/Database/LegacyModelExporter.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index cf41ffc780..18e840fedd 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -95,6 +95,12 @@ namespace osu.Game.Database }).ContinueWith(onComplete); } + /// + /// Exports an item to Stream. + /// Override if custom export method is required. + /// + /// The item to export. + /// The output stream to export to. protected virtual void ExportToStream(TModel model, Stream outputStream) => exportZipArchive(model, outputStream); /// From e02b8cb199ebdc13f18aaae292febbfb9c75ec89 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 11 Dec 2022 18:30:24 +0900 Subject: [PATCH 0033/1400] Group export methods into their respective managers --- osu.Game/Beatmaps/BeatmapManager.cs | 9 ++ osu.Game/Database/LegacyBeatmapExporter.cs | 5 +- osu.Game/Database/LegacyModelExporter.cs | 82 +++++++++---------- osu.Game/Database/LegacyScoreExporter.cs | 8 +- osu.Game/Database/LegacySkinExporter.cs | 5 +- .../Online/Leaderboards/LeaderboardScore.cs | 18 ++-- .../Overlays/Settings/Sections/SkinSection.cs | 12 +-- osu.Game/Scoring/ScoreManager.cs | 8 ++ osu.Game/Screens/Edit/Editor.cs | 11 +-- osu.Game/Skinning/SkinManager.cs | 9 ++ 10 files changed, 80 insertions(+), 87 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 965cc43815..34780082da 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -42,6 +42,8 @@ namespace osu.Game.Beatmaps private readonly WorkingBeatmapCache workingBeatmapCache; + private readonly LegacyBeatmapExporter beatmapExporter; + public Action<(BeatmapSetInfo beatmapSet, bool isBatch)>? ProcessBeatmap { private get; set; } public BeatmapManager(Storage storage, RealmAccess realm, IAPIProvider? api, AudioManager audioManager, IResourceStore gameResources, GameHost? host = null, @@ -66,6 +68,11 @@ namespace osu.Game.Beatmaps beatmapImporter.PostNotification = obj => PostNotification?.Invoke(obj); workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); + + beatmapExporter = new LegacyBeatmapExporter(storage, realm) + { + PostNotification = obj => PostNotification?.Invoke(obj) + }; } protected virtual WorkingBeatmapCache CreateWorkingBeatmapCache(AudioManager audioManager, IResourceStore resources, IResourceStore storage, WorkingBeatmap? defaultBeatmap, @@ -446,6 +453,8 @@ namespace osu.Game.Beatmaps public Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) => beatmapImporter.ImportAsUpdate(notification, importTask, original); + public void Export(BeatmapSetInfo beatmap) => Task.Run(() => beatmapExporter.ExportAsync(beatmap)); + private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { setInfo.Hash = beatmapImporter.ComputeHash(setInfo); diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 22bccbcda6..6349ebde2c 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -3,14 +3,13 @@ using osu.Framework.Platform; using osu.Game.Beatmaps; -using osu.Game.Overlays; namespace osu.Game.Database { public class LegacyBeatmapExporter : LegacyModelExporter { - public LegacyBeatmapExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) - : base(storage, realm, notifications) + public LegacyBeatmapExporter(Storage storage, RealmAccess realm) + : base(storage, realm) { } diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 18e840fedd..5150651b15 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Extensions; -using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Utils; using Realms; @@ -33,26 +32,16 @@ namespace osu.Game.Database protected RealmAccess RealmAccess; - private readonly ProgressNotification notification; - private bool canCancel = true; - private readonly INotificationOverlay? notifications; + private string filename = string.Empty; + public Action? PostNotification { get; set; } - protected LegacyModelExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) + protected LegacyModelExporter(Storage storage, RealmAccess realm) { exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); RealmAccess = realm; - - this.notifications = notifications; - notification = new ProgressNotification - { - State = ProgressNotificationState.Active, - Text = "Exporting...", - CompletionText = "Export completed" - }; - notification.CancelRequested += () => canCancel; } /// @@ -62,13 +51,9 @@ namespace osu.Game.Database /// public async Task ExportAsync(TModel model) { - notifications?.Post(notification); - string itemFilename = model.GetDisplayString().GetValidFilename(); IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); - string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - - notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); using (var stream = exportStorage.CreateFileSafely(filename)) { @@ -77,22 +62,50 @@ namespace osu.Game.Database } /// - /// Export te model corresponding to model to given stream. + /// Export model to stream. /// /// The medel which have . /// The stream to export. /// public async Task ExportToStreamAsync(TModel model, Stream stream) { + ProgressNotification notification = new ProgressNotification + { + State = ProgressNotificationState.Active, + Text = "Exporting...", + CompletionText = "Export completed" + }; + notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + notification.CancelRequested += () => canCancel; + PostNotification?.Invoke(notification); + canCancel = true; + Guid id = model.ID; await Task.Run(() => { RealmAccess.Run(r => { TModel refetchModel = r.Find(id); - ExportToStream(refetchModel, stream); + ExportToStream(refetchModel, stream, notification); }); - }).ContinueWith(onComplete); + }).ContinueWith(t => + { + if (t.IsFaulted) + { + notification.State = ProgressNotificationState.Cancelled; + Logger.Error(t.Exception, "An error occurred while exporting"); + + return; + } + + if (notification.CancellationToken.IsCancellationRequested) + { + return; + } + + notification.CompletionText = "Export Complete, Click to open the folder"; + notification.State = ProgressNotificationState.Completed; + }); } /// @@ -101,14 +114,16 @@ namespace osu.Game.Database /// /// The item to export. /// The output stream to export to. - protected virtual void ExportToStream(TModel model, Stream outputStream) => exportZipArchive(model, outputStream); + /// The notification will displayed to the user + protected virtual void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification) => exportZipArchive(model, outputStream, notification); /// /// Exports an item to Stream as a legacy (.zip based) package. /// /// The item to export. /// The output stream to export to. - private void exportZipArchive(TModel model, Stream outputStream) + /// The notification will displayed to the user + private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification) { using (var archive = ZipArchive.Create()) { @@ -129,24 +144,5 @@ namespace osu.Game.Database archive.SaveTo(outputStream); } } - - private void onComplete(Task t) - { - if (t.IsFaulted) - { - notification.State = ProgressNotificationState.Cancelled; - Logger.Error(t.Exception, "An error occurred while exporting"); - - return; - } - - if (notification.CancellationToken.IsCancellationRequested) - { - return; - } - - notification.CompletionText = "Export Complete, Click to open the folder"; - notification.State = ProgressNotificationState.Completed; - } } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index eb46bc6db2..1a30d823e1 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -5,21 +5,21 @@ using System.IO; using System.Linq; using osu.Framework.Platform; using osu.Game.Extensions; -using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; using osu.Game.Scoring; namespace osu.Game.Database { public class LegacyScoreExporter : LegacyModelExporter { - public LegacyScoreExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) - : base(storage, realm, notifications) + public LegacyScoreExporter(Storage storage, RealmAccess realm) + : base(storage, realm) { } protected override string FileExtension => ".osr"; - protected override void ExportToStream(ScoreInfo model, Stream stream) + protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification notification) { var file = model.Files.SingleOrDefault(); if (file == null) diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 6e65963f29..52d0e56cbf 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -2,15 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Platform; -using osu.Game.Overlays; using osu.Game.Skinning; namespace osu.Game.Database { public class LegacySkinExporter : LegacyModelExporter { - public LegacySkinExporter(Storage storage, RealmAccess realm, INotificationOverlay? notifications = null) - : base(storage, realm, notifications) + public LegacySkinExporter(Storage storage, RealmAccess realm) + : base(storage, realm) { } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index f0457de2dc..e5edf90d1a 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -18,7 +17,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Localisation; -using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -34,7 +32,6 @@ using osuTK.Graphics; using osu.Game.Online.API; using osu.Game.Resources.Localisation.Web; using osu.Game.Utils; -using osu.Framework.Platform; namespace osu.Game.Online.Leaderboards { @@ -73,18 +70,11 @@ namespace osu.Game.Online.Leaderboards [Resolved(canBeNull: true)] private SongSelect songSelect { get; set; } - [Resolved] - private Storage storage { get; set; } - - [Resolved] - private RealmAccess realm { get; set; } - - [Resolved(canBeNull: true)] - private INotificationOverlay notifications { get; set; } - public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => Score; + private ScoreManager scoreManager = null!; + public LeaderboardScore(ScoreInfo score, int? rank, bool isOnlineScope = true) { Score = score; @@ -103,6 +93,8 @@ namespace osu.Game.Online.Leaderboards statisticsLabels = GetStatistics(Score).Select(s => new ScoreComponentLabel(s)).ToList(); + this.scoreManager = scoreManager; + ClickableAvatar innerAvatar; Children = new Drawable[] @@ -434,7 +426,7 @@ namespace osu.Game.Online.Leaderboards if (Score.Files.Count > 0) { - items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => Task.Run(() => new LegacyScoreExporter(storage, realm, notifications).ExportAsync(Score)))); + items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(Score))); items.Add(new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score)))); } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 9400e803c8..6d338df2fe 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; @@ -138,15 +137,6 @@ namespace osu.Game.Overlays.Settings.Sections [Resolved] private SkinManager skins { get; set; } - [Resolved] - private Storage storage { get; set; } - - [Resolved] - private RealmAccess realm { get; set; } - - [Resolved(canBeNull: true)] - private INotificationOverlay notifications { get; set; } - private Bindable currentSkin; [BackgroundDependencyLoader] @@ -168,7 +158,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - currentSkin.Value.SkinInfo.PerformRead(s => new LegacySkinExporter(storage, realm, notifications).ExportAsync(s)); + skins.ExporCurrenttSkin(); } catch (Exception e) { diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index b2944ad219..525ff58778 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -27,6 +27,7 @@ namespace osu.Game.Scoring { private readonly OsuConfigManager configManager; private readonly ScoreImporter scoreImporter; + private readonly LegacyScoreExporter scoreExporter; public ScoreManager(RulesetStore rulesets, Func beatmaps, Storage storage, RealmAccess realm, IAPIProvider api, OsuConfigManager configManager = null) @@ -38,6 +39,11 @@ namespace osu.Game.Scoring { PostNotification = obj => PostNotification?.Invoke(obj) }; + + scoreExporter = new LegacyScoreExporter(storage, realm) + { + PostNotification = obj => PostNotification?.Invoke(obj) + }; } public Score GetScore(ScoreInfo score) => scoreImporter.GetScore(score); @@ -177,6 +183,8 @@ namespace osu.Game.Scoring public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks); + public void Export(ScoreInfo score) => Task.Run(() => scoreExporter.ExportAsync(score)); + public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original); public Live Import(ScoreInfo item, ArchiveReader archive = null, bool batchImport = false, CancellationToken cancellationToken = default) => diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 342ee2e219..69bcda69c1 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; @@ -21,7 +20,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Framework.Threading; @@ -30,7 +28,6 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; @@ -89,12 +86,6 @@ namespace osu.Game.Screens.Edit [Resolved] private RulesetStore rulesets { get; set; } - [Resolved] - private Storage storage { get; set; } - - [Resolved] - private RealmAccess realm { get; set; } - [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -958,7 +949,7 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() { Save(); - Task.Run(() => new LegacyBeatmapExporter(storage, realm, notifications).ExportAsync(Beatmap.Value.BeatmapSetInfo)); + beatmapManager.Export(Beatmap.Value.BeatmapSetInfo); } /// diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 4a5277f3bf..65a602b764 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -58,6 +58,8 @@ namespace osu.Game.Skinning private readonly SkinImporter skinImporter; + private readonly LegacySkinExporter skinExporter; + private readonly IResourceStore userFiles; private Skin argonSkin { get; } @@ -109,6 +111,11 @@ namespace osu.Game.Skinning SourceChanged?.Invoke(); }; + + skinExporter = new LegacySkinExporter(storage, realm) + { + PostNotification = obj => PostNotification?.Invoke(obj) + }; } public void SelectRandomSkin() @@ -280,6 +287,8 @@ namespace osu.Game.Skinning public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken); + public void ExporCurrenttSkin() => CurrentSkinInfo.Value.PerformRead(s => skinExporter.ExportAsync(s)); + #endregion public void Delete([CanBeNull] Expression> filter = null, bool silent = false) From 3d6d3b40257c17184311f1442b850747d1b3b287 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 20:59:11 +0900 Subject: [PATCH 0034/1400] fix weird async logic --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Scoring/ScoreManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 34780082da..56b87eaf11 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -453,7 +453,7 @@ namespace osu.Game.Beatmaps public Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) => beatmapImporter.ImportAsUpdate(notification, importTask, original); - public void Export(BeatmapSetInfo beatmap) => Task.Run(() => beatmapExporter.ExportAsync(beatmap)); + public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap); private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 525ff58778..f52172a200 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -183,7 +183,7 @@ namespace osu.Game.Scoring public Task>> Import(ProgressNotification notification, params ImportTask[] tasks) => scoreImporter.Import(notification, tasks); - public void Export(ScoreInfo score) => Task.Run(() => scoreExporter.ExportAsync(score)); + public Task Export(ScoreInfo score) => scoreExporter.ExportAsync(score); public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original); From c9cffc82484f32c70395509111149d5b0123b539 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 21:01:38 +0900 Subject: [PATCH 0035/1400] use resolved attribute --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e5edf90d1a..e4ea277756 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -73,7 +73,8 @@ namespace osu.Game.Online.Leaderboards public ITooltip GetCustomTooltip() => new LeaderboardScoreTooltip(); public virtual ScoreInfo TooltipContent => Score; - private ScoreManager scoreManager = null!; + [Resolved] + private ScoreManager scoreManager { get; set; } = null!; public LeaderboardScore(ScoreInfo score, int? rank, bool isOnlineScope = true) { @@ -87,14 +88,12 @@ namespace osu.Game.Online.Leaderboards } [BackgroundDependencyLoader] - private void load(IAPIProvider api, OsuColour colour, ScoreManager scoreManager) + private void load(IAPIProvider api, OsuColour colour) { var user = Score.User; statisticsLabels = GetStatistics(Score).Select(s => new ScoreComponentLabel(s)).ToList(); - this.scoreManager = scoreManager; - ClickableAvatar innerAvatar; Children = new Drawable[] From 6900d0120a70287ef531a4c0facd398508a76b06 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 21:39:48 +0900 Subject: [PATCH 0036/1400] change abstract implement --- osu.Game/Database/LegacyBeatmapExporter.cs | 2 +- osu.Game/Database/LegacyModelExporter.cs | 21 ++++++++++++++++----- osu.Game/Database/LegacySkinExporter.cs | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 6349ebde2c..107b91a234 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -6,7 +6,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Database { - public class LegacyBeatmapExporter : LegacyModelExporter + public class LegacyBeatmapExporter : LegacyArchiveExporter { public LegacyBeatmapExporter(Storage storage, RealmAccess realm) : base(storage, realm) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 5150651b15..6b5f8e7e96 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -32,7 +32,7 @@ namespace osu.Game.Database protected RealmAccess RealmAccess; - private bool canCancel = true; + protected bool CanCancel = true; private string filename = string.Empty; public Action? PostNotification { get; set; } @@ -76,9 +76,9 @@ namespace osu.Game.Database CompletionText = "Export completed" }; notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - notification.CancelRequested += () => canCancel; + notification.CancelRequested += () => CanCancel; PostNotification?.Invoke(notification); - canCancel = true; + CanCancel = true; Guid id = model.ID; await Task.Run(() => @@ -115,7 +115,18 @@ namespace osu.Game.Database /// The item to export. /// The output stream to export to. /// The notification will displayed to the user - protected virtual void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification) => exportZipArchive(model, outputStream, notification); + protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification); + } + + public abstract class LegacyArchiveExporter : LegacyModelExporter + where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey + { + protected LegacyArchiveExporter(Storage storage, RealmAccess realm) + : base(storage, realm) + { + } + + protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification) => exportZipArchive(model, outputStream, notification); /// /// Exports an item to Stream as a legacy (.zip based) package. @@ -140,7 +151,7 @@ namespace osu.Game.Database } notification.Text = "Saving Zip Archive..."; - canCancel = false; + CanCancel = false; archive.SaveTo(outputStream); } } diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 52d0e56cbf..d3e6a2f0f4 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -6,7 +6,7 @@ using osu.Game.Skinning; namespace osu.Game.Database { - public class LegacySkinExporter : LegacyModelExporter + public class LegacySkinExporter : LegacyArchiveExporter { public LegacySkinExporter(Storage storage, RealmAccess realm) : base(storage, realm) From 6ef5b2733f01a4ebd2ccd733a4e6c80c6158698f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 21:41:15 +0900 Subject: [PATCH 0037/1400] Export instead of ExportCurrentSkin --- osu.Game/Overlays/Settings/Sections/SkinSection.cs | 2 +- osu.Game/Skinning/SkinManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 6d338df2fe..1a64416b3e 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -158,7 +158,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - skins.ExporCurrenttSkin(); + skins.CurrentSkinInfo.Value.PerformRead(s => skins.ExportSkin(s)); } catch (Exception e) { diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 65a602b764..d4e7d252ac 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -287,7 +287,7 @@ namespace osu.Game.Skinning public Task> Import(ImportTask task, bool batchImport = false, CancellationToken cancellationToken = default) => skinImporter.Import(task, batchImport, cancellationToken); - public void ExporCurrenttSkin() => CurrentSkinInfo.Value.PerformRead(s => skinExporter.ExportAsync(s)); + public Task ExportSkin(SkinInfo skin) => skinExporter.ExportAsync(skin); #endregion From ec251664a7c4a2bbb6b022a046cf35960bd2497b Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 22:45:36 +0900 Subject: [PATCH 0038/1400] use ThrowIfCancellationRequested instead of CancelRequested --- osu.Game/Database/LegacyModelExporter.cs | 70 ++++++++++++++---------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 6b5f8e7e96..0ebcfaa07e 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -32,8 +32,6 @@ namespace osu.Game.Database protected RealmAccess RealmAccess; - protected bool CanCancel = true; - private string filename = string.Empty; public Action? PostNotification { get; set; } @@ -54,10 +52,16 @@ namespace osu.Game.Database string itemFilename = model.GetDisplayString().GetValidFilename(); IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); + bool success; using (var stream = exportStorage.CreateFileSafely(filename)) { - await ExportToStreamAsync(model, stream); + success = await ExportToStreamAsync(model, stream); + } + + if (!success) + { + exportStorage.Delete(filename); } } @@ -66,8 +70,8 @@ namespace osu.Game.Database /// /// The medel which have . /// The stream to export. - /// - public async Task ExportToStreamAsync(TModel model, Stream stream) + /// Whether the export was successful + public async Task ExportToStreamAsync(TModel model, Stream stream) { ProgressNotification notification = new ProgressNotification { @@ -76,35 +80,33 @@ namespace osu.Game.Database CompletionText = "Export completed" }; notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - notification.CancelRequested += () => CanCancel; PostNotification?.Invoke(notification); - CanCancel = true; Guid id = model.ID; - await Task.Run(() => + return await Task.Run(() => { RealmAccess.Run(r => { TModel refetchModel = r.Find(id); ExportToStream(refetchModel, stream, notification); }); - }).ContinueWith(t => + }, notification.CancellationToken).ContinueWith(t => { + if (t.IsCanceled) + { + return false; + } + if (t.IsFaulted) { notification.State = ProgressNotificationState.Cancelled; Logger.Error(t.Exception, "An error occurred while exporting"); - - return; - } - - if (notification.CancellationToken.IsCancellationRequested) - { - return; + return false; } notification.CompletionText = "Export Complete, Click to open the folder"; notification.State = ProgressNotificationState.Completed; + return true; }); } @@ -121,6 +123,8 @@ namespace osu.Game.Database public abstract class LegacyArchiveExporter : LegacyModelExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { + private bool canCancel = true; + protected LegacyArchiveExporter(Storage storage, RealmAccess realm) : base(storage, realm) { @@ -136,23 +140,33 @@ namespace osu.Game.Database /// The notification will displayed to the user private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification) { - using (var archive = ZipArchive.Create()) + try { - float i = 0; + notification.CancelRequested += () => canCancel; - foreach (var file in model.Files) + using (var archive = ZipArchive.Create()) { - if (notification.CancellationToken.IsCancellationRequested) return; + float i = 0; - archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + foreach (var file in model.Files) + { + notification.CancellationToken.ThrowIfCancellationRequested(); + + archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } + + notification.Text = "Saving Zip Archive..."; + canCancel = false; + archive.SaveTo(outputStream); } - - notification.Text = "Saving Zip Archive..."; - CanCancel = false; - archive.SaveTo(outputStream); + } + catch (OperationCanceledException) + { + Logger.Log("Export operat canceled"); + throw; } } } From f5226bd50b02068e42116940e12c1f47bbf158ce Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 23:12:25 +0900 Subject: [PATCH 0039/1400] use ZipWriter Export directly to stream instead of creating a archive so we can cancel this anytime --- osu.Game/Database/LegacyModelExporter.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 0ebcfaa07e..9e0c1e0c6d 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -12,7 +12,9 @@ using osu.Game.Extensions; using osu.Game.Overlays.Notifications; using osu.Game.Utils; using Realms; -using SharpCompress.Archives.Zip; +using SharpCompress.Common; +using SharpCompress.Writers; +using SharpCompress.Writers.Zip; namespace osu.Game.Database { @@ -123,8 +125,6 @@ namespace osu.Game.Database public abstract class LegacyArchiveExporter : LegacyModelExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { - private bool canCancel = true; - protected LegacyArchiveExporter(Storage storage, RealmAccess realm) : base(storage, realm) { @@ -142,9 +142,7 @@ namespace osu.Game.Database { try { - notification.CancelRequested += () => canCancel; - - using (var archive = ZipArchive.Create()) + using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) { float i = 0; @@ -152,15 +150,11 @@ namespace osu.Game.Database { notification.CancellationToken.ThrowIfCancellationRequested(); - archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + writer.Write(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); i++; notification.Progress = i / model.Files.Count(); notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; } - - notification.Text = "Saving Zip Archive..."; - canCancel = false; - archive.SaveTo(outputStream); } } catch (OperationCanceledException) From dadadaff65057cd16210ae9ba05634e308b5ec53 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 23:20:29 +0900 Subject: [PATCH 0040/1400] remove try catch --- osu.Game/Database/LegacyModelExporter.cs | 26 ++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 9e0c1e0c6d..824460cdc9 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -140,28 +140,20 @@ namespace osu.Game.Database /// The notification will displayed to the user private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification) { - try + using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) { - using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) + float i = 0; + + foreach (var file in model.Files) { - float i = 0; + notification.CancellationToken.ThrowIfCancellationRequested(); - foreach (var file in model.Files) - { - notification.CancellationToken.ThrowIfCancellationRequested(); - - writer.Write(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; - } + writer.Write(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; } } - catch (OperationCanceledException) - { - Logger.Log("Export operat canceled"); - throw; - } } } } From cd8420bc66c56aa7e686a579ebd9a18634861b45 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 23:34:40 +0900 Subject: [PATCH 0041/1400] Handle the case where the file cannot be found --- osu.Game/Database/LegacyModelExporter.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 824460cdc9..531a6f48da 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -143,12 +143,33 @@ namespace osu.Game.Database using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) { float i = 0; + bool fileMissing = false; foreach (var file in model.Files) { notification.CancellationToken.ThrowIfCancellationRequested(); - writer.Write(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); + using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) + { + // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. + if (stream == null) + { + // Only pop up once to prevent spam. + if (!fileMissing) + { + PostNotification?.Invoke(new SimpleErrorNotification + { + Text = "Some of your files are missing, they will not be included in the archive" + }); + fileMissing = true; + } + } + else + { + writer.Write(file.Filename, stream); + } + } + i++; notification.Progress = i / model.Files.Count(); notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; From 5912dfd443effad317f5085aba57f4b380868d6e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 15 Dec 2022 23:42:49 +0900 Subject: [PATCH 0042/1400] using declaration reshaper --- osu.Game/Database/LegacyModelExporter.cs | 49 ++++++++++++------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 531a6f48da..d896e4bce6 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -140,40 +140,39 @@ namespace osu.Game.Database /// The notification will displayed to the user private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification) { - using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) + using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); + + float i = 0; + bool fileMissing = false; + + foreach (var file in model.Files) { - float i = 0; - bool fileMissing = false; + notification.CancellationToken.ThrowIfCancellationRequested(); - foreach (var file in model.Files) + using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) { - notification.CancellationToken.ThrowIfCancellationRequested(); - - using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) + // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. + if (stream == null) { - // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. - if (stream == null) + // Only pop up once to prevent spam. + if (!fileMissing) { - // Only pop up once to prevent spam. - if (!fileMissing) + PostNotification?.Invoke(new SimpleErrorNotification { - PostNotification?.Invoke(new SimpleErrorNotification - { - Text = "Some of your files are missing, they will not be included in the archive" - }); - fileMissing = true; - } - } - else - { - writer.Write(file.Filename, stream); + Text = "Some of your files are missing, they will not be included in the archive" + }); + fileMissing = true; } } - - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + else + { + writer.Write(file.Filename, stream); + } } + + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; } } } From b37f1cce3fc4bfd3c5408a8fe32a4fdc796f3b8d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 20 Dec 2022 23:46:05 +0900 Subject: [PATCH 0043/1400] Added ability to report chat --- .../Visual/Online/TestSceneChatOverlay.cs | 38 +++++++ osu.Game/Overlays/Chat/ChatReportReason.cs | 36 ++++++ osu.Game/Overlays/Chat/DrawableUsername.cs | 16 ++- osu.Game/Overlays/Chat/ReportChatPopover.cs | 106 ++++++++++++++++++ osu.Game/Overlays/ChatOverlay.cs | 3 +- 5 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Overlays/Chat/ChatReportReason.cs create mode 100644 osu.Game/Overlays/Chat/ReportChatPopover.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 8cc4eabcd7..44d739a6e3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -30,6 +30,8 @@ using osu.Game.Overlays.Chat.Listing; using osu.Game.Overlays.Chat.ChannelList; using osuTK; using osuTK.Input; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Graphics.Sprites; namespace osu.Game.Tests.Visual.Online { @@ -530,6 +532,42 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestChatReport() + { + AddStep("Show overlay with channel", () => + { + chatOverlay.Show(); + channelManager.CurrentChannel.Value = channelManager.JoinChannel(testChannel1); + }); + + AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible); + waitForChannel1Visible(); + + AddStep("Right click username", () => + { + var username = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(username); + InputManager.Click(MouseButton.Right); + }); + + AddStep("Click report", () => + { + var btn = this.ChildrenOfType().First(x => x.Text == "Report"); + InputManager.MoveMouseTo(btn); + InputManager.Click(MouseButton.Left); + }); + + AddStep("Try to report", () => + { + var btn = this.ChildrenOfType().Single().ChildrenOfType().Single(); + InputManager.MoveMouseTo(btn); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("Report message sended", () => channelManager.CurrentChannel.Value.Messages.Any(x => x.Content.Contains("!report"))); + } + private void joinTestChannel(int i) { AddStep($"Join test channel {i}", () => channelManager.JoinChannel(testChannels[i])); diff --git a/osu.Game/Overlays/Chat/ChatReportReason.cs b/osu.Game/Overlays/Chat/ChatReportReason.cs new file mode 100644 index 0000000000..55593d29ad --- /dev/null +++ b/osu.Game/Overlays/Chat/ChatReportReason.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.ComponentModel; +using osu.Framework.Localisation; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Overlays.Chat +{ + public enum ChatReportReason + { + [Description("Insulting People")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsInsults))] + Insults, + + [Description("Spam")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsSpam))] + Spam, + + [Description("Cheating")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsCheating))] + FoulPlay, + + [Description("Unwanted Content")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsUnwantedContent))] + UnwantedContent, + + [Description("Nonsense")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsNonsense))] + Nonsense, + + [Description("Other")] + [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsOther))] + Other + } +} diff --git a/osu.Game/Overlays/Chat/DrawableUsername.cs b/osu.Game/Overlays/Chat/DrawableUsername.cs index 6bae498a6c..f70175f081 100644 --- a/osu.Game/Overlays/Chat/DrawableUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableUsername.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -25,7 +26,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Chat { - public partial class DrawableUsername : OsuClickableContainer, IHasContextMenu + public partial class DrawableUsername : OsuClickableContainer, IHasContextMenu, IHasPopover { public Color4 AccentColour { get; } @@ -152,12 +153,20 @@ namespace osu.Game.Overlays.Chat }; if (!user.Equals(api.LocalUser.Value)) + { items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, openUserChannel)); + items.Add(new OsuMenuItem("Report", MenuItemType.Destructive, this.ShowPopover)); + } return items.ToArray(); } } + private void report(ChatReportReason reason, string comments) + { + chatManager?.PostMessage($"!report {user.Username} ({reason.GetDescription()}): {comments}"); + } + private void openUserChannel() { chatManager?.OpenPrivateChannel(user); @@ -221,5 +230,10 @@ namespace osu.Game.Overlays.Chat Color4Extensions.FromHex("812a96"), Color4Extensions.FromHex("992861"), }; + + public Popover GetPopover() => new ReportChatPopover(user) + { + Action = report + }; } } diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs new file mode 100644 index 0000000000..cf5e456874 --- /dev/null +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -0,0 +1,106 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; +using osuTK; + +namespace osu.Game.Overlays.Chat +{ + public partial class ReportChatPopover : OsuPopover + { + public Action? Action; + + private readonly APIUser? user; + + private OsuEnumDropdown reasonDropdown = null!; + private OsuTextBox commentsTextBox = null!; + + public ReportChatPopover(APIUser? user) + { + this.user = user; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, AudioManager audio) + { + Child = new ReverseChildIDFillFlowContainer + { + Direction = FillDirection.Vertical, + Width = 500, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new SpriteIcon + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Icon = FontAwesome.Solid.ExclamationTriangle, + Size = new Vector2(36), + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = ReportStrings.UserTitle(user?.Username ?? @"Someone"), + Font = OsuFont.Torus.With(size: 25), + Margin = new MarginPadding { Bottom = 10 } + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = UsersStrings.ReportReason, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = 40, + Child = reasonDropdown = new OsuEnumDropdown + { + RelativeSizeAxes = Axes.X + } + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = UsersStrings.ReportComments, + }, + commentsTextBox = new OsuTextBox + { + RelativeSizeAxes = Axes.X, + PlaceholderText = UsersStrings.ReportPlaceholder, + }, + new RoundedButton + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 200, + BackgroundColour = colours.Red3, + Text = UsersStrings.ReportActionsSend, + Action = () => + { + Action?.Invoke(reasonDropdown.Current.Value, commentsTextBox.Text); + this.HidePopover(); + }, + Margin = new MarginPadding { Bottom = 5, Top = 10 }, + } + } + }; + } + } +} diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index c539cdc5ec..c3a6ed0175 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -122,7 +123,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Width = side_bar_width, }, - new Container + new PopoverContainer { RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopRight, From ffa32307c3ef8c9917a210a31871b9000cf80246 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 21 Dec 2022 01:37:16 +0900 Subject: [PATCH 0044/1400] abstract ReportPopover --- .../Graphics/UserInterfaceV2/ReportPopover.cs | 114 ++++++++++++++++++ osu.Game/Overlays/Chat/ReportChatPopover.cs | 94 +-------------- .../Overlays/Comments/ReportCommentPopover.cs | 98 +-------------- 3 files changed, 119 insertions(+), 187 deletions(-) create mode 100644 osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs diff --git a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs new file mode 100644 index 0000000000..44af108ab1 --- /dev/null +++ b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs @@ -0,0 +1,114 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Resources.Localisation.Web; +using osuTK; + +namespace osu.Game.Graphics.UserInterfaceV2 +{ + public abstract partial class ReportPopover : OsuPopover + where T : struct, Enum + { + public Action? Action; + + private OsuEnumDropdown reasonDropdown = null!; + private OsuTextBox commentsTextBox = null!; + private RoundedButton submitButton = null!; + + public bool CanSubmitEmptyReason = false; + public LocalisableString Header; + + protected ReportPopover(LocalisableString headerString) + { + Header = headerString; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Child = new ReverseChildIDFillFlowContainer + { + Direction = FillDirection.Vertical, + Width = 500, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new SpriteIcon + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Icon = FontAwesome.Solid.ExclamationTriangle, + Size = new Vector2(36), + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = Header, + Font = OsuFont.Torus.With(size: 25), + Margin = new MarginPadding { Bottom = 10 } + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = UsersStrings.ReportReason, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Height = 40, + Child = reasonDropdown = new OsuEnumDropdown + { + RelativeSizeAxes = Axes.X + } + }, + new OsuSpriteText + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Text = UsersStrings.ReportComments, + }, + commentsTextBox = new OsuTextBox + { + RelativeSizeAxes = Axes.X, + PlaceholderText = UsersStrings.ReportPlaceholder, + }, + submitButton = new RoundedButton + { + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 200, + BackgroundColour = colours.Red3, + Text = UsersStrings.ReportActionsSend, + Action = () => + { + Action?.Invoke(reasonDropdown.Current.Value, commentsTextBox.Text); + this.HidePopover(); + }, + Margin = new MarginPadding { Bottom = 5, Top = 10 }, + } + } + }; + + if (!CanSubmitEmptyReason) + { + commentsTextBox.Current.BindValueChanged(e => + { + submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(e.NewValue); + }, true); + } + } + } +} diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index cf5e456874..79c3922795 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -1,106 +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 System; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; -using osuTK; namespace osu.Game.Overlays.Chat { - public partial class ReportChatPopover : OsuPopover + public partial class ReportChatPopover : ReportPopover { - public Action? Action; - - private readonly APIUser? user; - - private OsuEnumDropdown reasonDropdown = null!; - private OsuTextBox commentsTextBox = null!; - public ReportChatPopover(APIUser? user) + : base(ReportStrings.UserTitle(user?.Username ?? @"Someone")) { - this.user = user; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours, AudioManager audio) - { - Child = new ReverseChildIDFillFlowContainer - { - Direction = FillDirection.Vertical, - Width = 500, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(7), - Children = new Drawable[] - { - new SpriteIcon - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Icon = FontAwesome.Solid.ExclamationTriangle, - Size = new Vector2(36), - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = ReportStrings.UserTitle(user?.Username ?? @"Someone"), - Font = OsuFont.Torus.With(size: 25), - Margin = new MarginPadding { Bottom = 10 } - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = UsersStrings.ReportReason, - }, - new Container - { - RelativeSizeAxes = Axes.X, - Height = 40, - Child = reasonDropdown = new OsuEnumDropdown - { - RelativeSizeAxes = Axes.X - } - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = UsersStrings.ReportComments, - }, - commentsTextBox = new OsuTextBox - { - RelativeSizeAxes = Axes.X, - PlaceholderText = UsersStrings.ReportPlaceholder, - }, - new RoundedButton - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Width = 200, - BackgroundColour = colours.Red3, - Text = UsersStrings.ReportActionsSend, - Action = () => - { - Action?.Invoke(reasonDropdown.Current.Value, commentsTextBox.Text); - this.HidePopover(); - }, - Margin = new MarginPadding { Bottom = 5, Top = 10 }, - } - } - }; + CanSubmitEmptyReason = true; } } } diff --git a/osu.Game/Overlays/Comments/ReportCommentPopover.cs b/osu.Game/Overlays/Comments/ReportCommentPopover.cs index f3b2a2f97c..e688dad755 100644 --- a/osu.Game/Overlays/Comments/ReportCommentPopover.cs +++ b/osu.Game/Overlays/Comments/ReportCommentPopover.cs @@ -1,111 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using osu.Framework.Allocation; -using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; -using osuTK; namespace osu.Game.Overlays.Comments { - public partial class ReportCommentPopover : OsuPopover + public partial class ReportCommentPopover : ReportPopover { - public Action? Action; - - private readonly Comment? comment; - - private OsuEnumDropdown reasonDropdown = null!; - private OsuTextBox commentsTextBox = null!; - private RoundedButton submitButton = null!; - public ReportCommentPopover(Comment? comment) + : base(ReportStrings.CommentTitle(comment?.User?.Username ?? comment?.LegacyName ?? @"Someone")) { - this.comment = comment; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Child = new ReverseChildIDFillFlowContainer - { - Direction = FillDirection.Vertical, - Width = 500, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(7), - Children = new Drawable[] - { - new SpriteIcon - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Icon = FontAwesome.Solid.ExclamationTriangle, - Size = new Vector2(36), - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = ReportStrings.CommentTitle(comment?.User?.Username ?? comment?.LegacyName ?? @"Someone"), - Font = OsuFont.Torus.With(size: 25), - Margin = new MarginPadding { Bottom = 10 } - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = UsersStrings.ReportReason, - }, - new Container - { - RelativeSizeAxes = Axes.X, - Height = 40, - Child = reasonDropdown = new OsuEnumDropdown - { - RelativeSizeAxes = Axes.X - } - }, - new OsuSpriteText - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Text = UsersStrings.ReportComments, - }, - commentsTextBox = new OsuTextBox - { - RelativeSizeAxes = Axes.X, - PlaceholderText = UsersStrings.ReportPlaceholder, - }, - submitButton = new RoundedButton - { - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Width = 200, - BackgroundColour = colours.Red3, - Text = UsersStrings.ReportActionsSend, - Action = () => - { - Action?.Invoke(reasonDropdown.Current.Value, commentsTextBox.Text); - this.HidePopover(); - }, - Margin = new MarginPadding { Bottom = 5, Top = 10 }, - } - } - }; - - commentsTextBox.Current.BindValueChanged(e => - { - submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(e.NewValue); - }, true); } } } From 1b2c821346da690e932b4d74fda4ac9307d99bb3 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 21 Dec 2022 15:44:02 +0900 Subject: [PATCH 0045/1400] showpopover directly --- .../Visual/Online/TestSceneChatOverlay.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 44d739a6e3..3a6cbdfb0f 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -12,6 +12,7 @@ using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -544,19 +545,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible); waitForChannel1Visible(); - AddStep("Right click username", () => - { - var username = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(username); - InputManager.Click(MouseButton.Right); - }); - - AddStep("Click report", () => - { - var btn = this.ChildrenOfType().First(x => x.Text == "Report"); - InputManager.MoveMouseTo(btn); - InputManager.Click(MouseButton.Left); - }); + AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); AddStep("Try to report", () => { From bbb22479a8aefd1b040d236dde395c0220ed4bc4 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 25 Dec 2022 21:32:47 +0100 Subject: [PATCH 0046/1400] Add "ModBubbles" for the osu ruleset. --- .../Mods/TestSceneOsuModBubbles.cs | 19 ++ osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 228 ++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 +- osu.Game/Rulesets/Mods/ModFlashlight.cs | 3 + 4 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModBubbles.cs create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModBubbles.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModBubbles.cs new file mode 100644 index 0000000000..e72a1f79f5 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModBubbles.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Osu.Mods; + +namespace osu.Game.Rulesets.Osu.Tests.Mods +{ + public partial class TestSceneOsuModBubbles : OsuModTestScene + { + [Test] + public void TestOsuModBubbles() => CreateModTest(new ModTestData + { + Mod = new OsuModBubbles(), + Autoplay = true, + PassCondition = () => true + }); + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs new file mode 100644 index 0000000000..c51ebde383 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -0,0 +1,228 @@ +// 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.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Performance; +using osu.Framework.Graphics.Pooling; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Pooling; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Scoring; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public partial class OsuModBubbles : ModWithVisibilityAdjustment, IApplicableToDrawableRuleset, IApplicableToScoreProcessor + { + public override string Name => "Bubbles"; + + public override string Acronym => "BB"; + + public override LocalisableString Description => "Dont let their popping distract you!"; + + public override double ScoreMultiplier => 1; + + public override ModType Type => ModType.Fun; + + // Compatibility with these seems potentially feasible in the future, blocked for now because they dont work as one would expect + public override Type[] IncompatibleMods => new[] { typeof(OsuModBarrelRoll), typeof(OsuModMagnetised), typeof(OsuModRepel) }; + + private PlayfieldAdjustmentContainer adjustmentContainer = null!; + private BubbleContainer bubbleContainer = null!; + + private readonly Bindable currentCombo = new BindableInt(); + + private float maxSize; + private float bubbleRadius; + private double bubbleFade; + + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + currentCombo.BindTo(scoreProcessor.Combo); + currentCombo.BindValueChanged(combo => + maxSize = Math.Min(1.75f, (float)(1.25 + 0.005 * combo.NewValue)), true); + } + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + // Multiplying by 2 results in an initial size that is too large, hence 1.85 has been chosen + bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.85f); + bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimeFadeIn * 2; + + // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) + drawableRuleset.Playfield.DisplayJudgements.Value = false; + + adjustmentContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); + + adjustmentContainer.Add(bubbleContainer = new BubbleContainer()); + drawableRuleset.KeyBindingInputManager.Add(adjustmentContainer); + } + + protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); + + protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); + + private void applyBubbleState(DrawableHitObject drawableObject) + { + if (drawableObject is not DrawableOsuHitObject drawableOsuObject || !drawableObject.Judged) return; + + OsuHitObject hitObject = drawableOsuObject.HitObject; + + switch (drawableOsuObject) + { + //Needs to be done explicitly to avoid being handled by DrawableHitCircle below + case DrawableSliderHead: + addBubbleContainer(hitObject.Position); + break; + + //Stack leniency causes placement issues if this isn't handled as such. + case DrawableHitCircle hitCircle: + addBubbleContainer(hitCircle.Position); + break; + + case DrawableSpinnerTick: + case DrawableSlider: + return; + + default: + addBubbleContainer(hitObject.Position); + break; + } + + void addBubbleContainer(Vector2 position) => bubbleContainer.Add(new BubbleLifeTimeEntry + { + LifetimeStart = bubbleContainer.Time.Current, + Colour = drawableOsuObject.AccentColour.Value, + Position = position, + InitialSize = new Vector2(bubbleRadius), + MaxSize = maxSize, + FadeTime = bubbleFade, + IsHit = drawableOsuObject.IsHit + } + ); + } + + #region Pooled Bubble drawable + + //LifetimeEntry flow is necessary to allow for correct rewind behaviour, can probably be made generic later if more mods are made requiring it + //Todo: find solution to bubbles rewinding in "groups" + private sealed partial class BubbleContainer : PooledDrawableWithLifetimeContainer + { + protected override bool RemoveRewoundEntry => true; + + private readonly DrawablePool pool; + + public BubbleContainer() + { + RelativeSizeAxes = Axes.Both; + AddInternal(pool = new DrawablePool(10, 1000)); + } + + protected override BubbleObject GetDrawable(BubbleLifeTimeEntry entry) => pool.Get(d => d.Apply(entry)); + } + + private sealed partial class BubbleObject : PoolableDrawableWithLifetime + { + private readonly BubbleDrawable bubbleDrawable; + + public BubbleObject() + { + InternalChild = bubbleDrawable = new BubbleDrawable(); + } + + protected override void OnApply(BubbleLifeTimeEntry entry) + { + base.OnApply(entry); + if (IsLoaded) + apply(entry); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + apply(Entry); + } + + private void apply(BubbleLifeTimeEntry? entry) + { + if (entry == null) + return; + + ApplyTransformsAt(float.MinValue, true); + ClearTransforms(true); + + Position = entry.Position; + + bubbleDrawable.Animate(entry); + + LifetimeEnd = bubbleDrawable.LatestTransformEndTime; + } + } + + private partial class BubbleDrawable : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load() + { + InternalChild = new Circle + { + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Colour4.Black.Opacity(0.05f), + Type = EdgeEffectType.Shadow, + Radius = 5 + } + }; + } + + public void Animate(BubbleLifeTimeEntry entry) + { + Size = entry.InitialSize; + this + .ScaleTo(entry.MaxSize, entry.FadeTime * 6, Easing.OutSine) + .FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, entry.FadeTime, Easing.OutSine) + .Delay(entry.FadeTime) + .FadeColour(entry.IsHit ? entry.Colour.Darken(.4f) : Colour4.Black, entry.FadeTime * 5, Easing.OutSine) + .Then() + .ScaleTo(entry.MaxSize * 1.5f, entry.FadeTime, Easing.OutSine) + .FadeTo(0, entry.FadeTime, Easing.OutQuint); + } + } + + private class BubbleLifeTimeEntry : LifetimeEntry + { + public Vector2 InitialSize { get; set; } + + public float MaxSize { get; set; } + + public Vector2 Position { get; set; } + + public Colour4 Colour { get; set; } + + // FadeTime is based on the approach rate of the beatmap. + public double FadeTime { get; set; } + + // Whether the corresponding HitObject was hit + public bool IsHit { get; set; } + } + + #endregion + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 79a566e33c..0df1e4dfca 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -202,7 +202,8 @@ namespace osu.Game.Rulesets.Osu new OsuModNoScope(), new MultiMod(new OsuModMagnetised(), new OsuModRepel()), new ModAdaptiveSpeed(), - new OsuModFreezeFrame() + new OsuModFreezeFrame(), + new OsuModBubbles() }; case ModType.System: diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 45fa55c7f2..2c9ef357b5 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -83,6 +83,9 @@ namespace osu.Game.Rulesets.Mods flashlight.Combo.BindTo(Combo); drawableRuleset.KeyBindingInputManager.Add(flashlight); + + // Stop flashlight from being drawn underneath other mods that generate HitObjects. + drawableRuleset.KeyBindingInputManager.ChangeChildDepth(flashlight, -1); } protected abstract Flashlight CreateFlashlight(); From 8a108b143e10bf80162eb0109aad7a68ae9692fc Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 25 Dec 2022 21:33:10 +0100 Subject: [PATCH 0047/1400] Address mod incompatibilities --- osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs | 3 +++ osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 17 +++++++++++------ osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs index 9e71f657ce..2394cf92fc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.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 System; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -10,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModBarrelRoll : ModBarrelRoll, IApplicableToDrawableHitObject { + public override Type[] IncompatibleMods => new[] { typeof(OsuModBubbles) }; + public void ApplyToDrawableHitObject(DrawableHitObject d) { d.OnUpdate += _ => diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index c51ebde383..2e4d574148 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -86,12 +86,12 @@ namespace osu.Game.Rulesets.Osu.Mods { //Needs to be done explicitly to avoid being handled by DrawableHitCircle below case DrawableSliderHead: - addBubbleContainer(hitObject.Position); + addBubbleContainer(hitObject.Position, drawableOsuObject); break; //Stack leniency causes placement issues if this isn't handled as such. case DrawableHitCircle hitCircle: - addBubbleContainer(hitCircle.Position); + addBubbleContainer(hitCircle.Position, drawableOsuObject); break; case DrawableSpinnerTick: @@ -99,19 +99,24 @@ namespace osu.Game.Rulesets.Osu.Mods return; default: - addBubbleContainer(hitObject.Position); + addBubbleContainer(hitObject.Position, drawableOsuObject); break; } + } - void addBubbleContainer(Vector2 position) => bubbleContainer.Add(new BubbleLifeTimeEntry + private void addBubbleContainer(Vector2 position, DrawableHitObject hitObject) + { + bubbleContainer.Add + ( + new BubbleLifeTimeEntry { LifetimeStart = bubbleContainer.Time.Current, - Colour = drawableOsuObject.AccentColour.Value, + Colour = hitObject.AccentColour.Value, Position = position, InitialSize = new Vector2(bubbleRadius), MaxSize = maxSize, FadeTime = bubbleFade, - IsHit = drawableOsuObject.IsHit + IsHit = hitObject.IsHit } ); } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs index 38d90eb121..c8c4cd6a14 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override LocalisableString Description => "No need to chase the circles – your cursor is a magnet!"; public override double ScoreMultiplier => 0.5; - public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModRelax), typeof(OsuModRepel) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModRelax), typeof(OsuModRepel), typeof(OsuModBubbles) }; [SettingSource("Attraction strength", "How strong the pull is.", 0)] public BindableFloat AttractionStrength { get; } = new BindableFloat(0.5f) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs index 31a6b69d6b..28d459cedb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override LocalisableString Description => "Hit objects run away!"; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModMagnetised) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay), typeof(OsuModMagnetised), typeof(OsuModBubbles) }; [SettingSource("Repulsion strength", "How strong the repulsion is.", 0)] public BindableFloat RepulsionStrength { get; } = new BindableFloat(0.5f) From ca84b885dcc6695cb7da3549757f7e6338bc37de Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 11 Jan 2023 17:51:41 +0100 Subject: [PATCH 0048/1400] Add more detail to bubbles --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 58 ++++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 2e4d574148..f5e7e035b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Performance; using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; +using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Pooling; @@ -21,6 +22,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -178,21 +180,38 @@ namespace osu.Game.Rulesets.Osu.Mods } } - private partial class BubbleDrawable : CompositeDrawable + private partial class BubbleDrawable : CompositeDrawable, IHasAccentColour { + public Color4 AccentColour { get; set; } + + private Circle outerCircle = null!; + private Circle innerCircle = null!; + [BackgroundDependencyLoader] private void load() { - InternalChild = new Circle + InternalChildren = new Drawable[] { - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - EdgeEffect = new EdgeEffectParameters + outerCircle = new Circle { - Colour = Colour4.Black.Opacity(0.05f), - Type = EdgeEffectType.Shadow, - Radius = 5 + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + MaskingSmoothness = 2, + BorderThickness = 0, + BorderColour = Colour4.Transparent, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 3, + Colour = Colour4.Black.Opacity(0.05f) + } + }, + innerCircle = new Circle + { + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.5f) } }; } @@ -202,12 +221,25 @@ namespace osu.Game.Rulesets.Osu.Mods Size = entry.InitialSize; this .ScaleTo(entry.MaxSize, entry.FadeTime * 6, Easing.OutSine) - .FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, entry.FadeTime, Easing.OutSine) - .Delay(entry.FadeTime) - .FadeColour(entry.IsHit ? entry.Colour.Darken(.4f) : Colour4.Black, entry.FadeTime * 5, Easing.OutSine) .Then() .ScaleTo(entry.MaxSize * 1.5f, entry.FadeTime, Easing.OutSine) - .FadeTo(0, entry.FadeTime, Easing.OutQuint); + .FadeTo(0, entry.FadeTime, Easing.OutExpo); + + animateCircles(entry); + } + + private void animateCircles(BubbleLifeTimeEntry entry) + { + innerCircle.FadeColour(entry.IsHit ? entry.Colour.Darken(0.2f) : Colour4.Black) + .FadeColour(entry.IsHit ? entry.Colour.Lighten(0.2f) : Colour4.Black, entry.FadeTime * 7); + + innerCircle.FadeTo(0.5f, entry.FadeTime * 7, Easing.InExpo) + .ScaleTo(1.1f, entry.FadeTime * 7, Easing.InSine); + + outerCircle + .FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, entry.FadeTime, Easing.OutSine) + .Delay(entry.FadeTime) + .FadeColour(entry.IsHit ? entry.Colour.Darken(.4f) : Colour4.Black, entry.FadeTime * 5, Easing.OutSine); } } From ff5a12fcb4be833fdeb21b406b2ec9e19f88f8ff Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Mon, 16 Jan 2023 20:39:38 +0300 Subject: [PATCH 0049/1400] Localise login form --- osu.Game/Localisation/LoginPanelStrings.cs | 54 ++++++++++++++++++++++ osu.Game/Overlays/Login/LoginForm.cs | 13 +++--- osu.Game/Overlays/Login/LoginPanel.cs | 7 +-- osu.Game/Overlays/Login/UserAction.cs | 10 ++-- 4 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 osu.Game/Localisation/LoginPanelStrings.cs diff --git a/osu.Game/Localisation/LoginPanelStrings.cs b/osu.Game/Localisation/LoginPanelStrings.cs new file mode 100644 index 0000000000..6dfb48fbdc --- /dev/null +++ b/osu.Game/Localisation/LoginPanelStrings.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class LoginPanelStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.LoginPanel"; + + /// + /// "Do not disturb" + /// + public static LocalisableString DoNotDisturb => new TranslatableString(getKey(@"do_not_disturb"), @"Do not disturb"); + + /// + /// "Appear offline" + /// + public static LocalisableString AppearOffline => new TranslatableString(getKey(@"appear_offline"), @"Appear offline"); + + /// + /// "Sign out" + /// + public static LocalisableString SignOut => new TranslatableString(getKey(@"sign_out"), @"Sign out"); + + /// + /// "Signed in" + /// + public static LocalisableString SignedIn => new TranslatableString(getKey(@"signed_in"), @"Signed in"); + + /// + /// "ACCOUNT" + /// + public static LocalisableString Account => new TranslatableString(getKey(@"account"), @"ACCOUNT"); + + /// + /// "Remember username" + /// + public static LocalisableString RememberUsername => new TranslatableString(getKey(@"remember_username"), @"Remember username"); + + /// + /// "Stay signed in" + /// + public static LocalisableString StaySignedIn => new TranslatableString(getKey(@"stay_signed_in"), @"Stay signed in"); + + /// + /// "Register" + /// + public static LocalisableString Register => new TranslatableString(getKey(@"register"), @"Register"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index af145c418c..9f9b8d9342 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -16,6 +16,7 @@ using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Resources.Localisation.Web; using osuTK; +using osu.Game.Localisation; namespace osu.Game.Overlays.Login { @@ -47,7 +48,7 @@ namespace osu.Game.Overlays.Login RelativeSizeAxes = Axes.X; ErrorTextFlowContainer errorText; - LinkFlowContainer forgottenPaswordLink; + LinkFlowContainer forgottenPasswordLink; Children = new Drawable[] { @@ -71,15 +72,15 @@ namespace osu.Game.Overlays.Login }, new SettingsCheckbox { - LabelText = "Remember username", + LabelText = LoginPanelStrings.RememberUsername, Current = config.GetBindable(OsuSetting.SaveUsername), }, new SettingsCheckbox { - LabelText = "Stay signed in", + LabelText = LoginPanelStrings.StaySignedIn, Current = config.GetBindable(OsuSetting.SavePassword), }, - forgottenPaswordLink = new LinkFlowContainer + forgottenPasswordLink = new LinkFlowContainer { Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, RelativeSizeAxes = Axes.X, @@ -105,7 +106,7 @@ namespace osu.Game.Overlays.Login }, new SettingsButton { - Text = "Register", + Text = LoginPanelStrings.Register, Action = () => { RequestHide?.Invoke(); @@ -114,7 +115,7 @@ namespace osu.Game.Overlays.Login } }; - forgottenPaswordLink.AddLink(LayoutStrings.PopupLoginLoginForgot, $"{api.WebsiteRootUrl}/home/password-reset"); + forgottenPasswordLink.AddLink(LayoutStrings.PopupLoginLoginForgot, $"{api.WebsiteRootUrl}/home/password-reset"); password.OnCommit += (_, _) => performLogin(); diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 44f2f3273a..fb9987bd82 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -6,6 +6,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -81,7 +82,7 @@ namespace osu.Game.Overlays.Login { new OsuSpriteText { - Text = "ACCOUNT", + Text = LoginPanelStrings.Account, Margin = new MarginPadding { Bottom = 5 }, Font = OsuFont.GetFont(weight: FontWeight.Bold), }, @@ -115,7 +116,7 @@ namespace osu.Game.Overlays.Login }, }; - linkFlow.AddLink("cancel", api.Logout, string.Empty); + linkFlow.AddLink(Resources.Localisation.Web.CommonStrings.ButtonsCancel.ToLower(), api.Logout, string.Empty); break; case APIState.Online: @@ -140,7 +141,7 @@ namespace osu.Game.Overlays.Login { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = "Signed in", + Text = LoginPanelStrings.SignedIn, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, diff --git a/osu.Game/Overlays/Login/UserAction.cs b/osu.Game/Overlays/Login/UserAction.cs index 7a18e38109..813968a053 100644 --- a/osu.Game/Overlays/Login/UserAction.cs +++ b/osu.Game/Overlays/Login/UserAction.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; +using osu.Game.Localisation; namespace osu.Game.Overlays.Login { @@ -14,13 +12,13 @@ namespace osu.Game.Overlays.Login [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOnline))] Online, - [Description(@"Do not disturb")] + [LocalisableDescription(typeof(LoginPanelStrings), nameof(LoginPanelStrings.DoNotDisturb))] DoNotDisturb, - [Description(@"Appear offline")] + [LocalisableDescription(typeof(LoginPanelStrings), nameof(LoginPanelStrings.AppearOffline))] AppearOffline, - [Description(@"Sign out")] + [LocalisableDescription(typeof(LoginPanelStrings), nameof(LoginPanelStrings.SignOut))] SignOut, } } From 4c341db33f12a05a1ec6e4abbf60fd4294b0a70d Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Mon, 16 Jan 2023 21:31:01 +0300 Subject: [PATCH 0050/1400] Localise registration window --- .../Localisation/AccountCreationStrings.cs | 77 +++++++++++++++++++ .../Overlays/AccountCreation/ScreenEntry.cs | 19 ++--- .../Overlays/AccountCreation/ScreenWarning.cs | 5 +- .../Overlays/AccountCreation/ScreenWelcome.cs | 9 +-- 4 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 osu.Game/Localisation/AccountCreationStrings.cs diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs new file mode 100644 index 0000000000..4e702ea7cc --- /dev/null +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -0,0 +1,77 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class AccountCreationStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.AccountCreation"; + + /// + /// "New Player Registration" + /// + public static LocalisableString NewPlayerRegistration => new TranslatableString(getKey(@"new_player_registration"), @"New Player Registration"); + + /// + /// "let's get you started" + /// + public static LocalisableString LetsGetYouStarted => new TranslatableString(getKey(@"lets_get_you_started"), @"let's get you started"); + + /// + /// "Let's create an account!" + /// + public static LocalisableString LetsCreateAnAccount => new TranslatableString(getKey(@"lets_create_an_account"), @"Let's create an account!"); + + /// + /// "Help, I can't access my account!" + /// + public static LocalisableString HelpICantAccess => new TranslatableString(getKey(@"help_icant_access"), @"Help, I can't access my account!"); + + /// + /// "I understand. This account isn't for me." + /// + public static LocalisableString AccountIsntForMe => new TranslatableString(getKey(@"account_isnt_for_me"), @"I understand. This account isn't for me."); + + /// + /// "email address" + /// + public static LocalisableString EmailAddress => new TranslatableString(getKey(@"email_address"), @"email address"); + + /// + /// "This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!" + /// + public static LocalisableString ThisWillBeYourPublic => new TranslatableString(getKey(@"this_will_be_your_public"), + @"This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + + /// + /// "Will be used for notifications, account verification and in the case you forget your password. No spam, ever." + /// + public static LocalisableString EmailUsage => + new TranslatableString(getKey(@"email_usage"), @"Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + + /// + /// " Make sure to get it right!" + /// + public static LocalisableString MakeSureToGetIt => new TranslatableString(getKey(@"make_sure_to_get_it"), @" Make sure to get it right!"); + + /// + /// "At least " + /// + public static LocalisableString BeforeCharactersLong => new TranslatableString(getKey(@"before_characters_long"), @"At least "); + + /// + /// "8 characters long" + /// + public static LocalisableString CharactersLong => new TranslatableString(getKey(@"characters_long"), @"8 characters long"); + + /// + /// ". Choose something long but also something you will remember, like a line from your favourite song." + /// + public static LocalisableString AfterCharactersLong => + new TranslatableString(getKey(@"after_characters_long"), @". Choose something long but also something you will remember, like a line from your favourite song."); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 2e20f83e9e..6718b72805 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Overlays.Settings; using osu.Game.Resources.Localisation.Web; @@ -71,7 +72,7 @@ namespace osu.Game.Overlays.AccountCreation Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Font = OsuFont.GetFont(size: 20), - Text = "Let's create an account!", + Text = AccountCreationStrings.LetsCreateAnAccount }, usernameTextBox = new OsuTextBox { @@ -86,7 +87,7 @@ namespace osu.Game.Overlays.AccountCreation }, emailTextBox = new OsuTextBox { - PlaceholderText = "email address", + PlaceholderText = AccountCreationStrings.EmailAddress, RelativeSizeAxes = Axes.X, TabbableContentContainer = this }, @@ -118,7 +119,7 @@ namespace osu.Game.Overlays.AccountCreation AutoSizeAxes = Axes.Y, Child = new SettingsButton { - Text = "Register", + Text = LoginPanelStrings.Register, Margin = new MarginPadding { Vertical = 20 }, Action = performRegistration } @@ -132,14 +133,14 @@ namespace osu.Game.Overlays.AccountCreation textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox }; - usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + usernameDescription.AddText(AccountCreationStrings.ThisWillBeYourPublic); - emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); - emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); + emailAddressDescription.AddText(AccountCreationStrings.EmailUsage); + emailAddressDescription.AddText(AccountCreationStrings.MakeSureToGetIt, cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); - passwordDescription.AddText("At least "); - characterCheckText = passwordDescription.AddText("8 characters long"); - passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); + passwordDescription.AddText(AccountCreationStrings.BeforeCharactersLong); + characterCheckText = passwordDescription.AddText(AccountCreationStrings.CharactersLong); + passwordDescription.AddText(AccountCreationStrings.AfterCharactersLong); passwordTextBox.Current.BindValueChanged(_ => updateCharacterCheckTextColour(), true); characterCheckText.DrawablePartsRecreated += _ => updateCharacterCheckTextColour(); diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index a833a871f9..f5807b49b5 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -17,6 +17,7 @@ using osu.Game.Overlays.Settings; using osu.Game.Screens.Menu; using osuTK; using osuTK.Graphics; +using osu.Game.Localisation; namespace osu.Game.Overlays.AccountCreation { @@ -101,13 +102,13 @@ namespace osu.Game.Overlays.AccountCreation }, new SettingsButton { - Text = "Help, I can't access my account!", + Text = AccountCreationStrings.HelpICantAccess, Margin = new MarginPadding { Top = 50 }, Action = () => game?.OpenUrlExternally(help_centre_url) }, new DangerousSettingsButton { - Text = "I understand. This account isn't for me.", + Text = AccountCreationStrings.AccountIsntForMe, Action = () => this.Push(new ScreenEntry()) }, furtherAssistance = new LinkFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index 4becb225f8..a81b1019fe 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,6 +10,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Settings; using osu.Game.Screens.Menu; using osuTK; +using osu.Game.Localisation; namespace osu.Game.Overlays.AccountCreation { @@ -46,18 +45,18 @@ namespace osu.Game.Overlays.AccountCreation Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), - Text = "New Player Registration", + Text = AccountCreationStrings.NewPlayerRegistration, }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Font = OsuFont.GetFont(size: 12), - Text = "let's get you started", + Text = AccountCreationStrings.LetsGetYouStarted, }, new SettingsButton { - Text = "Let's create an account!", + Text = AccountCreationStrings.LetsCreateAnAccount, Margin = new MarginPadding { Vertical = 120 }, Action = () => this.Push(new ScreenWarning()) } From bb3668c76901f5d2109697748b91627fdcb54878 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Mon, 16 Jan 2023 22:24:03 +0300 Subject: [PATCH 0051/1400] Reuse existing --- osu.Game/Localisation/AccountCreationStrings.cs | 5 ----- osu.Game/Localisation/LoginPanelStrings.cs | 5 ----- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 2 +- osu.Game/Overlays/Login/UserAction.cs | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 4e702ea7cc..0b27944a61 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -34,11 +34,6 @@ namespace osu.Game.Localisation /// public static LocalisableString AccountIsntForMe => new TranslatableString(getKey(@"account_isnt_for_me"), @"I understand. This account isn't for me."); - /// - /// "email address" - /// - public static LocalisableString EmailAddress => new TranslatableString(getKey(@"email_address"), @"email address"); - /// /// "This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!" /// diff --git a/osu.Game/Localisation/LoginPanelStrings.cs b/osu.Game/Localisation/LoginPanelStrings.cs index 6dfb48fbdc..535d86fbc5 100644 --- a/osu.Game/Localisation/LoginPanelStrings.cs +++ b/osu.Game/Localisation/LoginPanelStrings.cs @@ -19,11 +19,6 @@ namespace osu.Game.Localisation /// public static LocalisableString AppearOffline => new TranslatableString(getKey(@"appear_offline"), @"Appear offline"); - /// - /// "Sign out" - /// - public static LocalisableString SignOut => new TranslatableString(getKey(@"sign_out"), @"Sign out"); - /// /// "Signed in" /// diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 6718b72805..fc450c7a91 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.AccountCreation }, emailTextBox = new OsuTextBox { - PlaceholderText = AccountCreationStrings.EmailAddress, + PlaceholderText = ModelValidationStrings.UserAttributesUserEmail.ToLower(), RelativeSizeAxes = Axes.X, TabbableContentContainer = this }, diff --git a/osu.Game/Overlays/Login/UserAction.cs b/osu.Game/Overlays/Login/UserAction.cs index 813968a053..d4d639f2fb 100644 --- a/osu.Game/Overlays/Login/UserAction.cs +++ b/osu.Game/Overlays/Login/UserAction.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Login [LocalisableDescription(typeof(LoginPanelStrings), nameof(LoginPanelStrings.AppearOffline))] AppearOffline, - [LocalisableDescription(typeof(LoginPanelStrings), nameof(LoginPanelStrings.SignOut))] + [LocalisableDescription(typeof(UserVerificationStrings), nameof(UserVerificationStrings.BoxInfoLogoutLink))] SignOut, } } From ad32d99daabe400402e59d4046de6de1e95a1d43 Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Mon, 16 Jan 2023 23:08:29 +0300 Subject: [PATCH 0052/1400] Localise caps lock warning --- osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs | 3 ++- osu.Game/Localisation/CommonStrings.cs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 63c98d7838..9de9eceb07 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -16,6 +16,7 @@ using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Platform; +using osu.Game.Localisation; namespace osu.Game.Graphics.UserInterface { @@ -112,7 +113,7 @@ namespace osu.Game.Graphics.UserInterface private partial class CapsWarning : SpriteIcon, IHasTooltip { - public LocalisableString TooltipText => "caps lock is active"; + public LocalisableString TooltipText => CommonStrings.CapsLockIsActive; public CapsWarning() { diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 10178915a2..a68f08efcc 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -154,6 +154,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Exit => new TranslatableString(getKey(@"exit"), @"Exit"); + /// + /// "caps lock is active" + /// + public static LocalisableString CapsLockIsActive => new TranslatableString(getKey(@"caps_lock_is_active"), @"caps lock is active"); + private static string getKey(string key) => $@"{prefix}:{key}"; } -} +} \ No newline at end of file From df74bccaaa7345e2b016516b799e85dc790a184c Mon Sep 17 00:00:00 2001 From: ansel <79257300125@ya.ru> Date: Tue, 17 Jan 2023 13:31:03 +0300 Subject: [PATCH 0053/1400] Replace 2 strings with one formattable --- osu.Game/Localisation/AccountCreationStrings.cs | 11 +++-------- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 10 +++++++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 0b27944a61..6acfaaa9ac 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -52,21 +52,16 @@ namespace osu.Game.Localisation public static LocalisableString MakeSureToGetIt => new TranslatableString(getKey(@"make_sure_to_get_it"), @" Make sure to get it right!"); /// - /// "At least " + /// "At least {0}. Choose something long but also something you will remember, like a line from your favourite song." /// - public static LocalisableString BeforeCharactersLong => new TranslatableString(getKey(@"before_characters_long"), @"At least "); + public static LocalisableString PasswordRequirements(string arg0) => new TranslatableString(getKey(@"password_requirements"), + @"At least {0}. Choose something long but also something you will remember, like a line from your favourite song.", arg0); /// /// "8 characters long" /// public static LocalisableString CharactersLong => new TranslatableString(getKey(@"characters_long"), @"8 characters long"); - /// - /// ". Choose something long but also something you will remember, like a line from your favourite song." - /// - public static LocalisableString AfterCharactersLong => - new TranslatableString(getKey(@"after_characters_long"), @". Choose something long but also something you will remember, like a line from your favourite song."); - private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index fc450c7a91..192b95b963 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Framework.Platform; using osu.Framework.Screens; @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.AccountCreation private OsuGame game { get; set; } [BackgroundDependencyLoader] - private void load() + private void load(LocalisationManager localisationManager) { InternalChildren = new Drawable[] { @@ -138,9 +139,12 @@ namespace osu.Game.Overlays.AccountCreation emailAddressDescription.AddText(AccountCreationStrings.EmailUsage); emailAddressDescription.AddText(AccountCreationStrings.MakeSureToGetIt, cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); - passwordDescription.AddText(AccountCreationStrings.BeforeCharactersLong); + string[] passwordReq = localisationManager.GetLocalisedBindableString(AccountCreationStrings.PasswordRequirements("{}")).Value.Split("{}"); + if (passwordReq.Length != 2) passwordReq = AccountCreationStrings.PasswordRequirements("{}").ToString().Split("{}"); + + passwordDescription.AddText(passwordReq[0]); characterCheckText = passwordDescription.AddText(AccountCreationStrings.CharactersLong); - passwordDescription.AddText(AccountCreationStrings.AfterCharactersLong); + passwordDescription.AddText(passwordReq[1]); passwordTextBox.Current.BindValueChanged(_ => updateCharacterCheckTextColour(), true); characterCheckText.DrawablePartsRecreated += _ => updateCharacterCheckTextColour(); From 7c81f1e75bb40981a55f16a3544d9521280bf49c Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Fri, 27 Jan 2023 11:21:11 +0100 Subject: [PATCH 0054/1400] Remove unnecessary BDL from bubble drawable Improve animation duration formula --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 85 +++++++++------------ 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index f5e7e035b2..6613d84e0e 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +11,6 @@ using osu.Framework.Graphics.Performance; using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; -using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Pooling; @@ -22,7 +20,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osuTK; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -63,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Mods { // Multiplying by 2 results in an initial size that is too large, hence 1.85 has been chosen bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.85f); - bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimeFadeIn * 2; + bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimePreempt * 2; // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) drawableRuleset.Playfield.DisplayJudgements.Value = false; @@ -125,8 +122,8 @@ namespace osu.Game.Rulesets.Osu.Mods #region Pooled Bubble drawable - //LifetimeEntry flow is necessary to allow for correct rewind behaviour, can probably be made generic later if more mods are made requiring it - //Todo: find solution to bubbles rewinding in "groups" + // LifetimeEntry flow is necessary to allow for correct rewind behaviour, can probably be made generic later if more mods are made requiring it + // Todo: find solution to bubbles rewinding in "groups" private sealed partial class BubbleContainer : PooledDrawableWithLifetimeContainer { protected override bool RemoveRewoundEntry => true; @@ -166,8 +163,7 @@ namespace osu.Game.Rulesets.Osu.Mods private void apply(BubbleLifeTimeEntry? entry) { - if (entry == null) - return; + if (entry == null) return; ApplyTransformsAt(float.MinValue, true); ClearTransforms(true); @@ -180,38 +176,36 @@ namespace osu.Game.Rulesets.Osu.Mods } } - private partial class BubbleDrawable : CompositeDrawable, IHasAccentColour + private partial class BubbleDrawable : CircularContainer { - public Color4 AccentColour { get; set; } + private readonly Circle innerCircle; + private readonly Box colourBox; - private Circle outerCircle = null!; - private Circle innerCircle = null!; - - [BackgroundDependencyLoader] - private void load() + public BubbleDrawable() { - InternalChildren = new Drawable[] + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + Masking = true; + MaskingSmoothness = 2; + BorderThickness = 0; + BorderColour = Colour4.Transparent; + EdgeEffect = new EdgeEffectParameters { - outerCircle = new Circle - { - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - MaskingSmoothness = 2, - BorderThickness = 0, - BorderColour = Colour4.Transparent, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Radius = 3, - Colour = Colour4.Black.Opacity(0.05f) - } - }, + Type = EdgeEffectType.Shadow, + Radius = 3, + Colour = Colour4.Black.Opacity(0.05f) + }; + + Children = new Drawable[] + { + colourBox = new Box { RelativeSizeAxes = Axes.Both, }, innerCircle = new Circle { + Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.5f) + Size = new Vector2(0.5f), } }; } @@ -219,27 +213,24 @@ namespace osu.Game.Rulesets.Osu.Mods public void Animate(BubbleLifeTimeEntry entry) { Size = entry.InitialSize; - this - .ScaleTo(entry.MaxSize, entry.FadeTime * 6, Easing.OutSine) + + this.ScaleTo(entry.MaxSize, getAnimationTime() * 0.8f, Easing.OutSine) .Then() - .ScaleTo(entry.MaxSize * 1.5f, entry.FadeTime, Easing.OutSine) - .FadeTo(0, entry.FadeTime, Easing.OutExpo); + .ScaleTo(entry.MaxSize * 1.5f, getAnimationTime() * 0.2f, Easing.OutSine) + .FadeTo(0, getAnimationTime() * 0.2f, Easing.OutExpo); - animateCircles(entry); - } + colourBox.FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, getAnimationTime() * 0.1f, Easing.OutSine) + .Then() + .FadeColour(entry.IsHit ? entry.Colour.Darken(0.4f) : Colour4.Black, getAnimationTime() * 0.9f, Easing.OutSine); - private void animateCircles(BubbleLifeTimeEntry entry) - { innerCircle.FadeColour(entry.IsHit ? entry.Colour.Darken(0.2f) : Colour4.Black) - .FadeColour(entry.IsHit ? entry.Colour.Lighten(0.2f) : Colour4.Black, entry.FadeTime * 7); + .FadeColour(entry.IsHit ? entry.Colour.Lighten(0.2f) : Colour4.Black, getAnimationTime()); - innerCircle.FadeTo(0.5f, entry.FadeTime * 7, Easing.InExpo) - .ScaleTo(1.1f, entry.FadeTime * 7, Easing.InSine); + innerCircle.FadeTo(0.5f, getAnimationTime(), Easing.InExpo) + .ScaleTo(2.2f, getAnimationTime(), Easing.InSine); - outerCircle - .FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, entry.FadeTime, Easing.OutSine) - .Delay(entry.FadeTime) - .FadeColour(entry.IsHit ? entry.Colour.Darken(.4f) : Colour4.Black, entry.FadeTime * 5, Easing.OutSine); + // The absolute length of the bubble's animation, can be used in fractions for animations of partial length + double getAnimationTime() => 2000 + 450 / (450 / entry.FadeTime); } } From c3090dea5f7bea51e2662cd82fc292d65c56d7ca Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 28 Jan 2023 00:30:30 +0100 Subject: [PATCH 0055/1400] Simplify animations --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 28 +++++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 6613d84e0e..479741b5b9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -214,23 +214,29 @@ namespace osu.Game.Rulesets.Osu.Mods { Size = entry.InitialSize; - this.ScaleTo(entry.MaxSize, getAnimationTime() * 0.8f, Easing.OutSine) + //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. + var colourDarker = entry.Colour.Darken(0.1f); + + this.ScaleTo(entry.MaxSize, getAnimationDuration() * 0.8f, Easing.OutSine) .Then() - .ScaleTo(entry.MaxSize * 1.5f, getAnimationTime() * 0.2f, Easing.OutSine) - .FadeTo(0, getAnimationTime() * 0.2f, Easing.OutExpo); + .ScaleTo(entry.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutSine) + .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutExpo); - colourBox.FadeColour(entry.IsHit ? entry.Colour : Colour4.Black, getAnimationTime() * 0.1f, Easing.OutSine) - .Then() - .FadeColour(entry.IsHit ? entry.Colour.Darken(0.4f) : Colour4.Black, getAnimationTime() * 0.9f, Easing.OutSine); + innerCircle.ScaleTo(2f, getAnimationDuration() * 0.8f, Easing.OutCubic); - innerCircle.FadeColour(entry.IsHit ? entry.Colour.Darken(0.2f) : Colour4.Black) - .FadeColour(entry.IsHit ? entry.Colour.Lighten(0.2f) : Colour4.Black, getAnimationTime()); + if (!entry.IsHit) + { + colourBox.Colour = Colour4.Black; + innerCircle.Colour = Colour4.Black; - innerCircle.FadeTo(0.5f, getAnimationTime(), Easing.InExpo) - .ScaleTo(2.2f, getAnimationTime(), Easing.InSine); + return; + } + + colourBox.FadeColour(colourDarker, getAnimationDuration() * 0.2f, Easing.OutQuint); + innerCircle.FadeColour(colourDarker); // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationTime() => 2000 + 450 / (450 / entry.FadeTime); + double getAnimationDuration() => 1700 + Math.Pow(entry.FadeTime, 1.15f); } } From 66da4c0288fd63d87fa7b4ea3547da39796e74e7 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 28 Jan 2023 17:38:24 +0100 Subject: [PATCH 0056/1400] Add colouration to the sliders to better match the vibrancy of the mod --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 27 +++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 479741b5b9..0101427f7a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -16,6 +16,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -77,6 +78,12 @@ namespace osu.Game.Rulesets.Osu.Mods private void applyBubbleState(DrawableHitObject drawableObject) { + if (drawableObject is DrawableSlider slider) + { + slider.Body.OnSkinChanged += () => applySliderState(slider); + applySliderState(slider); + } + if (drawableObject is not DrawableOsuHitObject drawableOsuObject || !drawableObject.Judged) return; OsuHitObject hitObject = drawableOsuObject.HitObject; @@ -93,9 +100,9 @@ namespace osu.Game.Rulesets.Osu.Mods addBubbleContainer(hitCircle.Position, drawableOsuObject); break; - case DrawableSpinnerTick: case DrawableSlider: - return; + case DrawableSpinnerTick: + break; default: addBubbleContainer(hitObject.Position, drawableOsuObject); @@ -103,6 +110,9 @@ namespace osu.Game.Rulesets.Osu.Mods } } + private void applySliderState(DrawableSlider slider) => + ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; + private void addBubbleContainer(Vector2 position, DrawableHitObject hitObject) { bubbleContainer.Add @@ -217,12 +227,12 @@ namespace osu.Game.Rulesets.Osu.Mods //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. var colourDarker = entry.Colour.Darken(0.1f); - this.ScaleTo(entry.MaxSize, getAnimationDuration() * 0.8f, Easing.OutSine) + this.ScaleTo(entry.MaxSize, getAnimationDuration() * 0.8f) .Then() - .ScaleTo(entry.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutSine) - .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutExpo); + .ScaleTo(entry.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutQuint) + .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutQuint); - innerCircle.ScaleTo(2f, getAnimationDuration() * 0.8f, Easing.OutCubic); + innerCircle.ScaleTo(2f, getAnimationDuration() * 0.8f, Easing.OutQuint); if (!entry.IsHit) { @@ -232,11 +242,12 @@ namespace osu.Game.Rulesets.Osu.Mods return; } - colourBox.FadeColour(colourDarker, getAnimationDuration() * 0.2f, Easing.OutQuint); + colourBox.FadeColour(colourDarker, getAnimationDuration() * 0.2f, Easing.OutQuint + ); innerCircle.FadeColour(colourDarker); // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationDuration() => 1700 + Math.Pow(entry.FadeTime, 1.15f); + double getAnimationDuration() => 1700 + Math.Pow(entry.FadeTime, 1.07f); } } From 3bdf83bf44e63000d2a4c23c7467a1aa24b87724 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sat, 28 Jan 2023 22:44:57 +0100 Subject: [PATCH 0057/1400] Redo the drawable structure of bubbledrawable to run and look better --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 50 ++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 0101427f7a..2c90bfa399 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -5,6 +5,7 @@ using System; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Performance; @@ -93,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Mods //Needs to be done explicitly to avoid being handled by DrawableHitCircle below case DrawableSliderHead: addBubbleContainer(hitObject.Position, drawableOsuObject); - break; + return; //Stack leniency causes placement issues if this isn't handled as such. case DrawableHitCircle hitCircle: @@ -188,7 +189,6 @@ namespace osu.Game.Rulesets.Osu.Mods private partial class BubbleDrawable : CircularContainer { - private readonly Circle innerCircle; private readonly Box colourBox; public BubbleDrawable() @@ -196,55 +196,55 @@ namespace osu.Game.Rulesets.Osu.Mods Anchor = Anchor.Centre; Origin = Anchor.Centre; - Masking = true; MaskingSmoothness = 2; BorderThickness = 0; - BorderColour = Colour4.Transparent; + BorderColour = Colour4.White; + Masking = true; EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, Radius = 3, Colour = Colour4.Black.Opacity(0.05f) }; - - Children = new Drawable[] - { - colourBox = new Box { RelativeSizeAxes = Axes.Both, }, - innerCircle = new Circle - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.5f), - } - }; + Child = colourBox = new Box { RelativeSizeAxes = Axes.Both, }; } public void Animate(BubbleLifeTimeEntry entry) { Size = entry.InitialSize; + BorderThickness = Width / 3.5f; //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. - var colourDarker = entry.Colour.Darken(0.1f); + ColourInfo colourDarker = entry.Colour.Darken(0.1f); + // Main bubble scaling based on combo this.ScaleTo(entry.MaxSize, getAnimationDuration() * 0.8f) .Then() + // Pop at the end of the bubbles life time .ScaleTo(entry.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutQuint) - .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutQuint); - - innerCircle.ScaleTo(2f, getAnimationDuration() * 0.8f, Easing.OutQuint); + .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutCirc); if (!entry.IsHit) { - colourBox.Colour = Colour4.Black; - innerCircle.Colour = Colour4.Black; + Colour = Colour4.Black; + BorderColour = Colour4.Black; return; } - colourBox.FadeColour(colourDarker, getAnimationDuration() * 0.2f, Easing.OutQuint - ); - innerCircle.FadeColour(colourDarker); + colourBox.FadeColour(colourDarker); + + this.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration() * 0.3f, Easing.OutQuint); + + // Ripple effect utilises the border to reduce drawable count + this.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration() * 0.3f, Easing.OutQuint) + + // Avoids transparency overlap issues during the bubble "pop" + .Then().Schedule(() => + { + BorderThickness = 0; + BorderColour = Colour4.Transparent; + }); // The absolute length of the bubble's animation, can be used in fractions for animations of partial length double getAnimationDuration() => 1700 + Math.Pow(entry.FadeTime, 1.07f); From f58534f60c76e4b0f9874eb91be336a49cb62035 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 5 Feb 2023 16:35:11 +0100 Subject: [PATCH 0058/1400] Extended the length of replay at the end of map --- osu.Game/Screens/Play/Player.cs | 88 +++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bf7f38cdd3..fda6bdaa8f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -613,6 +613,8 @@ namespace osu.Game.Screens.Play // if an exit has been requested, cancel any pending completion (the user has shown intention to exit). resultsDisplayDelegate?.Cancel(); + beginScoreImport(); + // The actual exit is performed if // - the pause / fail dialog was not requested // - the pause / fail dialog was requested but is already displayed (user showing intention to exit). @@ -735,14 +737,9 @@ namespace osu.Game.Screens.Play // is no chance that a user could return to the (already completed) Player instance from a child screen. ValidForResume = false; - // Ensure we are not writing to the replay any more, as we are about to consume and store the score. - DrawableRuleset.SetRecordTarget(null); - if (!Configuration.ShowResults) return; - prepareScoreForDisplayTask ??= Task.Run(prepareAndImportScore); - bool storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; if (storyboardHasOutro) @@ -756,6 +753,56 @@ namespace osu.Game.Screens.Play progressToResults(true); } + /// + /// Queue the results screen for display. + /// + /// + /// A final display will only occur once all work is completed in . This means that even after calling this method, the results screen will never be shown until ScoreProcessor.HasCompleted becomes . + /// + /// Whether a minimum delay () should be added before the screen is displayed. + private void progressToResults(bool withDelay) + { + resultsDisplayDelegate?.Cancel(); + + double delay = withDelay ? RESULTS_DISPLAY_DELAY : 0; + + resultsDisplayDelegate = new ScheduledDelegate(() => + { + if (prepareScoreForDisplayTask == null) + { + beginScoreImport(); + return; + } + + if (!prepareScoreForDisplayTask.IsCompleted) + // If the asynchronous preparation has not completed, keep repeating this delegate. + return; + + resultsDisplayDelegate?.Cancel(); + + if (!this.IsCurrentScreen()) + // This player instance may already be in the process of exiting. + return; + + this.Push(CreateResults(prepareScoreForDisplayTask.GetResultSafely())); + }, Time.Current + delay, 50); + + Scheduler.Add(resultsDisplayDelegate); + } + + private void beginScoreImport() + { + // We do not want to import the score in cases where we don't show results + bool canShowResults = Configuration.ShowResults && ScoreProcessor.HasCompleted.Value && GameplayState.HasPassed; + if (!canShowResults) + return; + + // Ensure we are not writing to the replay any more, as we are about to consume and store the score. + DrawableRuleset.SetRecordTarget(null); + + prepareScoreForDisplayTask ??= Task.Run(prepareAndImportScore); + } + /// /// Asynchronously run score preparation operations (database import, online submission etc.). /// @@ -785,37 +832,6 @@ namespace osu.Game.Screens.Play return scoreCopy.ScoreInfo; } - /// - /// Queue the results screen for display. - /// - /// - /// A final display will only occur once all work is completed in . This means that even after calling this method, the results screen will never be shown until ScoreProcessor.HasCompleted becomes . - /// - /// Whether a minimum delay () should be added before the screen is displayed. - private void progressToResults(bool withDelay) - { - resultsDisplayDelegate?.Cancel(); - - double delay = withDelay ? RESULTS_DISPLAY_DELAY : 0; - - resultsDisplayDelegate = new ScheduledDelegate(() => - { - if (prepareScoreForDisplayTask?.IsCompleted != true) - // If the asynchronous preparation has not completed, keep repeating this delegate. - return; - - resultsDisplayDelegate?.Cancel(); - - if (!this.IsCurrentScreen()) - // This player instance may already be in the process of exiting. - return; - - this.Push(CreateResults(prepareScoreForDisplayTask.GetResultSafely())); - }, Time.Current + delay, 50); - - Scheduler.Add(resultsDisplayDelegate); - } - protected override bool OnScroll(ScrollEvent e) { // During pause, allow global volume adjust regardless of settings. From 45981125860b331d5f5dbaa59966e6d354f2fd4c Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 5 Feb 2023 21:46:38 +0300 Subject: [PATCH 0059/1400] Add OriginalBeatmapHash to ScoreInfo. Update db schema_version, migration --- osu.Game/Beatmaps/BeatmapManager.cs | 8 ++++++++ osu.Game/Database/RealmAccess.cs | 15 +++++++++++++++ osu.Game/Scoring/ScoreInfo.cs | 2 ++ 3 files changed, 25 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index ad56bbbc3a..e972f067ca 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; @@ -25,6 +26,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; +using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; @@ -454,6 +456,12 @@ namespace osu.Game.Beatmaps if (transferCollections) beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); + //Unlinking all scores from this beatmap + r.All().Where(s => s.BeatmapInfoID == beatmapInfo.ID).ForEach(s => s.BeatmapInfo = new BeatmapInfo()); + + //Linking all the previos scores + r.All().Where(s => s.OriginalBeatmapHash == beatmapInfo.Hash).ForEach(s => s.BeatmapInfo = beatmapInfo); + ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); } diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 177c671bca..422ceb8af3 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -70,6 +70,7 @@ namespace osu.Game.Database /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo. /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. + /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. /// private const int schema_version = 25; @@ -865,6 +866,20 @@ namespace osu.Game.Database case 25: // Remove the default skins so they can be added back by SkinManager with updated naming. migration.NewRealm.RemoveRange(migration.NewRealm.All().Where(s => s.Protected)); + break; + case 26: + // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should + // See: https://github.com/ppy/osu/issues/22062 + string ScoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + + var oldScoreInfos = migration.OldRealm.DynamicApi.All(ScoreInfoName); + var newScoreInfos = migration.NewRealm.All(); + + for (int i = 0; i < newScoreInfos.Count(); i++) + { + newScoreInfos.ElementAt(i).OriginalBeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; + } + break; } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 1009474d89..2c029bbe68 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -66,6 +66,8 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; + public string OriginalBeatmapHash { get; set; } = string.Empty; + public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { Ruleset = ruleset ?? new RulesetInfo(); From d23e787bc1f341ae41c3fa5a21467d0c9f320973 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 5 Feb 2023 21:55:50 +0300 Subject: [PATCH 0060/1400] Update `schema_version` --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 422ceb8af3..6f85b3f1be 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -72,7 +72,7 @@ namespace osu.Game.Database /// 25 2022-09-18 Remove skins to add with new naming. /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. /// - private const int schema_version = 25; + private const int schema_version = 26; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. From 4f23e096d76e9ab33140b77472dd4fa6247d9b0c Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 6 Feb 2023 07:59:37 +0100 Subject: [PATCH 0061/1400] Improved readability --- osu.Game/Screens/Play/Player.cs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fda6bdaa8f..443108cf34 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -613,6 +613,7 @@ namespace osu.Game.Screens.Play // if an exit has been requested, cancel any pending completion (the user has shown intention to exit). resultsDisplayDelegate?.Cancel(); + // import current score if possible. beginScoreImport(); // The actual exit is performed if @@ -770,7 +771,11 @@ namespace osu.Game.Screens.Play { if (prepareScoreForDisplayTask == null) { - beginScoreImport(); + // Try importing score since the task hasn't been invoked yet. + if (!beginScoreImport()) + // If the task hasn't started, the score will never be imported. + resultsDisplayDelegate?.Cancel(); + return; } @@ -790,17 +795,25 @@ namespace osu.Game.Screens.Play Scheduler.Add(resultsDisplayDelegate); } - private void beginScoreImport() + /// + /// Ends replay recording and runs only when results can be shown + /// + /// + /// Whether the task has been invoked + /// + private bool beginScoreImport() { - // We do not want to import the score in cases where we don't show results - bool canShowResults = Configuration.ShowResults && ScoreProcessor.HasCompleted.Value && GameplayState.HasPassed; - if (!canShowResults) - return; - // Ensure we are not writing to the replay any more, as we are about to consume and store the score. DrawableRuleset.SetRecordTarget(null); + // We do not want to import the score in cases where we don't show results + bool canShowResults = Configuration.ShowResults && ScoreProcessor.HasCompleted.Value && GameplayState.HasPassed; + if (!canShowResults) + return false; + prepareScoreForDisplayTask ??= Task.Run(prepareAndImportScore); + + return true; } /// From abcb564a74efeb3bb9e43ee1686f402297d416b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Feb 2023 17:32:17 +0900 Subject: [PATCH 0062/1400] Code quality pass of `OsuModBubbles` --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 24 ++++++--------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 2c90bfa399..3606434042 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -29,15 +29,15 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Name => "Bubbles"; - public override string Acronym => "BB"; + public override string Acronym => "BU"; - public override LocalisableString Description => "Dont let their popping distract you!"; + public override LocalisableString Description => "Don't let their popping distract you!"; public override double ScoreMultiplier => 1; public override ModType Type => ModType.Fun; - // Compatibility with these seems potentially feasible in the future, blocked for now because they dont work as one would expect + // Compatibility with these seems potentially feasible in the future, blocked for now because they don't work as one would expect public override Type[] IncompatibleMods => new[] { typeof(OsuModBarrelRoll), typeof(OsuModMagnetised), typeof(OsuModRepel) }; private PlayfieldAdjustmentContainer adjustmentContainer = null!; @@ -87,26 +87,14 @@ namespace osu.Game.Rulesets.Osu.Mods if (drawableObject is not DrawableOsuHitObject drawableOsuObject || !drawableObject.Judged) return; - OsuHitObject hitObject = drawableOsuObject.HitObject; - switch (drawableOsuObject) { - //Needs to be done explicitly to avoid being handled by DrawableHitCircle below - case DrawableSliderHead: - addBubbleContainer(hitObject.Position, drawableOsuObject); - return; - - //Stack leniency causes placement issues if this isn't handled as such. - case DrawableHitCircle hitCircle: - addBubbleContainer(hitCircle.Position, drawableOsuObject); - break; - case DrawableSlider: case DrawableSpinnerTick: break; default: - addBubbleContainer(hitObject.Position, drawableOsuObject); + addBubbleForObject(drawableOsuObject); break; } } @@ -114,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Mods private void applySliderState(DrawableSlider slider) => ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; - private void addBubbleContainer(Vector2 position, DrawableHitObject hitObject) + private void addBubbleForObject(DrawableOsuHitObject hitObject) { bubbleContainer.Add ( @@ -122,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Mods { LifetimeStart = bubbleContainer.Time.Current, Colour = hitObject.AccentColour.Value, - Position = position, + Position = hitObject.HitObject.Position, InitialSize = new Vector2(bubbleRadius), MaxSize = maxSize, FadeTime = bubbleFade, From 43f7665c9eabe7105bb1a7c1c2ace3784214d28f Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 6 Feb 2023 09:49:42 +0100 Subject: [PATCH 0063/1400] Improved readability again --- osu.Game/Screens/Play/Player.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 443108cf34..2f81b7154a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -614,7 +614,7 @@ namespace osu.Game.Screens.Play resultsDisplayDelegate?.Cancel(); // import current score if possible. - beginScoreImport(); + attemptScoreImport(); // The actual exit is performed if // - the pause / fail dialog was not requested @@ -772,8 +772,8 @@ namespace osu.Game.Screens.Play if (prepareScoreForDisplayTask == null) { // Try importing score since the task hasn't been invoked yet. - if (!beginScoreImport()) - // If the task hasn't started, the score will never be imported. + if (!attemptScoreImport()) + // If attempt failed, trying again is unnecessary resultsDisplayDelegate?.Cancel(); return; @@ -796,12 +796,12 @@ namespace osu.Game.Screens.Play } /// - /// Ends replay recording and runs only when results can be shown + /// Attempts to run /// /// - /// Whether the task has been invoked + /// Whether the attempt was successful /// - private bool beginScoreImport() + private bool attemptScoreImport() { // Ensure we are not writing to the replay any more, as we are about to consume and store the score. DrawableRuleset.SetRecordTarget(null); From b00848e742d48ef08849d5115690909109c88de9 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 6 Feb 2023 13:58:41 +0300 Subject: [PATCH 0064/1400] Fix realm error. Apply `OriginalBeatmapHash` on import --- osu.Game/Beatmaps/BeatmapManager.cs | 6 ------ osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e972f067ca..b46859cc59 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -456,12 +456,6 @@ namespace osu.Game.Beatmaps if (transferCollections) beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); - //Unlinking all scores from this beatmap - r.All().Where(s => s.BeatmapInfoID == beatmapInfo.ID).ForEach(s => s.BeatmapInfo = new BeatmapInfo()); - - //Linking all the previos scores - r.All().Where(s => s.OriginalBeatmapHash == beatmapInfo.Hash).ForEach(s => s.BeatmapInfo = beatmapInfo); - ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 6f0b0c62f8..4bd068ca0f 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -123,6 +123,7 @@ namespace osu.Game.Scoring.Legacy // before returning for database import, we must restore the database-sourced BeatmapInfo. // if not, the clone operation in GetPlayableBeatmap will cause a dereference and subsequent database exception. score.ScoreInfo.BeatmapInfo = workingBeatmap.BeatmapInfo; + score.ScoreInfo.OriginalBeatmapHash = workingBeatmap.BeatmapInfo.Hash; return score; } From 2c7386db39d894cfa8ef335e7c58659399ed2e19 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 6 Feb 2023 15:14:14 +0300 Subject: [PATCH 0065/1400] FIx score appearing on `BeatmapLeaderboard` and `TopLocalRank` --- osu.Game/Screens/Play/Player.cs | 1 + osu.Game/Screens/Select/Carousel/TopLocalRank.cs | 1 + osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0d208e6d9b..7bd020db93 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -248,6 +248,7 @@ namespace osu.Game.Screens.Play // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; + Score.ScoreInfo.OriginalBeatmapHash = Beatmap.Value.BeatmapInfo.Hash; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; Score.ScoreInfo.Mods = gameplayMods; diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index f1b773c831..3df72f7d3b 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -65,6 +65,7 @@ namespace osu.Game.Screens.Select.Carousel r.All() .Filter($"{nameof(ScoreInfo.User)}.{nameof(RealmUser.OnlineID)} == $0" + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $1" + + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + $" && {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $2" + $" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 5c720c8491..3e90d2465b 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -191,6 +191,7 @@ namespace osu.Game.Screens.Select.Leaderboards scoreSubscription = realm.RegisterForNotifications(r => r.All().Filter($"{nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $0" + + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1" + $" AND {nameof(ScoreInfo.DeletePending)} == false" , beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); From f0d4b9f0ca339c79c74fba39f1d9a97de37f5f6e Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 6 Feb 2023 17:00:47 +0100 Subject: [PATCH 0066/1400] Add inline comment for colour border override --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 3606434042..41430bb323 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -99,6 +99,7 @@ namespace osu.Game.Rulesets.Osu.Mods } } + // Makes the slider border coloured on all skins private void applySliderState(DrawableSlider slider) => ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; From cb26601cb4be90a62d898d230a14ac9cb667ecc3 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 02:29:28 +0300 Subject: [PATCH 0067/1400] Fix test's score generation --- osu.Game.Tests/Resources/TestResources.cs | 1 + .../Visual/SongSelect/TestSceneBeatmapLeaderboard.cs | 10 ++++++++++ .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 1 + 3 files changed, 12 insertions(+) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index adf28afc8e..f65d427649 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -176,6 +176,7 @@ namespace osu.Game.Tests.Resources CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }, BeatmapInfo = beatmap, + OriginalBeatmapHash = beatmap.Hash, Ruleset = beatmap.Ruleset, Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() }, TotalScore = 2845370, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index ef0ad6c25c..7a578230d9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -210,6 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Ruleset = new OsuRuleset().RulesetInfo, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, User = new APIUser { Id = 6602580, @@ -226,6 +227,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-30), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -243,6 +245,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-70), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -261,6 +264,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMinutes(-40), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -279,6 +283,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -297,6 +302,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-25), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -315,6 +321,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-50), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -333,6 +340,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-72), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -351,6 +359,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMonths(-3), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -369,6 +378,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddYears(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 7635c61867..14193b1ac8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -94,6 +94,7 @@ namespace osu.Game.Tests.Visual.UserInterface { OnlineID = i, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Accuracy = RNG.NextDouble(), TotalScore = RNG.Next(1, 1000000), MaxCombo = RNG.Next(1, 1000), From 723f13af259da2e022a5c25b61d84b67c8ad75a9 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 02:43:27 +0300 Subject: [PATCH 0068/1400] Add summary for `OriginalBeatmapHash` --- osu.Game/Scoring/ScoreInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2c029bbe68..7ad2d9203a 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -66,6 +66,9 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; + /// + /// Hash of the beatmap where it scored + /// public string OriginalBeatmapHash { get; set; } = string.Empty; public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) From 1470ea0a311bec07ba3ba6525025939e51322a68 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 03:07:53 +0300 Subject: [PATCH 0069/1400] Remove unnecessary using directives --- osu.Game/Beatmaps/BeatmapManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b46859cc59..ad56bbbc3a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,7 +13,6 @@ using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; @@ -26,7 +25,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; -using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; From a1ee3df453f46a271d7ba7450f791340119cc539 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 03:16:25 +0300 Subject: [PATCH 0070/1400] Improve local variable naming --- osu.Game/Database/RealmAccess.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 6f85b3f1be..1ef904fbc3 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -867,12 +867,13 @@ namespace osu.Game.Database // Remove the default skins so they can be added back by SkinManager with updated naming. migration.NewRealm.RemoveRange(migration.NewRealm.All().Where(s => s.Protected)); break; + case 26: // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should // See: https://github.com/ppy/osu/issues/22062 - string ScoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); - var oldScoreInfos = migration.OldRealm.DynamicApi.All(ScoreInfoName); + var oldScoreInfos = migration.OldRealm.DynamicApi.All(scoreInfoName); var newScoreInfos = migration.NewRealm.All(); for (int i = 0; i < newScoreInfos.Count(); i++) From 957c9e7e276037c9c0db101f5e77cbaf3ceda5da Mon Sep 17 00:00:00 2001 From: Cootz <50776304+Cootz@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:23:39 +0300 Subject: [PATCH 0071/1400] Update osu.Game/Scoring/ScoreInfo.cs Co-authored-by: Dean Herbert --- osu.Game/Scoring/ScoreInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 7ad2d9203a..2ea40df44d 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,9 +67,9 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// Hash of the beatmap where it scored + /// The beatmap's at the point in time when the score was set. /// - public string OriginalBeatmapHash { get; set; } = string.Empty; + public string BeatmapHash { get; set; } = string.Empty; public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { From 7e127dafe21a89f5059f59de5cff7904f34e9783 Mon Sep 17 00:00:00 2001 From: PC Date: Tue, 7 Feb 2023 11:52:47 +0300 Subject: [PATCH 0072/1400] Update reference --- osu.Game.Tests/Resources/TestResources.cs | 2 +- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 20 +++++++++---------- .../TestSceneDeleteLocalScore.cs | 2 +- osu.Game/Database/RealmAccess.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 2 +- osu.Game/Scoring/ScoreInfo.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- .../Screens/Select/Carousel/TopLocalRank.cs | 2 +- .../Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index f65d427649..a2d81c0a75 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -176,7 +176,7 @@ namespace osu.Game.Tests.Resources CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }, BeatmapInfo = beatmap, - OriginalBeatmapHash = beatmap.Hash, + BeatmapHash = beatmap.Hash, Ruleset = beatmap.Ruleset, Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() }, TotalScore = 2845370, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 7a578230d9..c4bca79480 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Ruleset = new OsuRuleset().RulesetInfo, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, User = new APIUser { Id = 6602580, @@ -227,7 +227,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-30), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -245,7 +245,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-70), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -264,7 +264,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMinutes(-40), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -283,7 +283,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -302,7 +302,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-25), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -321,7 +321,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-50), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -340,7 +340,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-72), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -359,7 +359,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMonths(-3), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -378,7 +378,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddYears(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 14193b1ac8..529874b71e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.UserInterface { OnlineID = i, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Accuracy = RNG.NextDouble(), TotalScore = RNG.Next(1, 1000000), MaxCombo = RNG.Next(1, 1000), diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1ef904fbc3..b151fc6474 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -70,7 +70,7 @@ namespace osu.Game.Database /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo. /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. - /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. + /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. /// private const int schema_version = 26; @@ -878,7 +878,7 @@ namespace osu.Game.Database for (int i = 0; i < newScoreInfos.Count(); i++) { - newScoreInfos.ElementAt(i).OriginalBeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; + newScoreInfos.ElementAt(i).BeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; } break; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 4bd068ca0f..9b145ad56e 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -123,7 +123,7 @@ namespace osu.Game.Scoring.Legacy // before returning for database import, we must restore the database-sourced BeatmapInfo. // if not, the clone operation in GetPlayableBeatmap will cause a dereference and subsequent database exception. score.ScoreInfo.BeatmapInfo = workingBeatmap.BeatmapInfo; - score.ScoreInfo.OriginalBeatmapHash = workingBeatmap.BeatmapInfo.Hash; + score.ScoreInfo.BeatmapHash = workingBeatmap.BeatmapInfo.Hash; return score; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2ea40df44d..62adcb9f94 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// The beatmap's at the point in time when the score was set. + /// The at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7bd020db93..a3d8d3237c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Play // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; - Score.ScoreInfo.OriginalBeatmapHash = Beatmap.Value.BeatmapInfo.Hash; + Score.ScoreInfo.BeatmapHash = Beatmap.Value.BeatmapInfo.Hash; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; Score.ScoreInfo.Mods = gameplayMods; diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index 3df72f7d3b..a57a8b0f27 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Select.Carousel r.All() .Filter($"{nameof(ScoreInfo.User)}.{nameof(RealmUser.OnlineID)} == $0" + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $1" - + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.BeatmapHash)}" + $" && {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $2" + $" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 3e90d2465b..2b40b9faf8 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -191,7 +191,7 @@ namespace osu.Game.Screens.Select.Leaderboards scoreSubscription = realm.RegisterForNotifications(r => r.All().Filter($"{nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $0" - + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.BeatmapHash)}" + $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1" + $" AND {nameof(ScoreInfo.DeletePending)} == false" , beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); From 338d96534a2ad7b27d82eeeafb2c778fb67d0b67 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:01:54 +0300 Subject: [PATCH 0073/1400] Add leaderboard test on beatmap update --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index c4bca79480..13a24cd490 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -96,6 +96,37 @@ namespace osu.Game.Tests.Visual.SongSelect checkCount(0); } + [Test] + public void TestLocalScoresDisplayOnBeatmapEdit() + { + BeatmapInfo beatmapInfo = null!; + + AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local); + + AddStep(@"Set beatmap", () => + { + beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); + beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + + leaderboard.BeatmapInfo = beatmapInfo; + }); + + clearScores(); + checkCount(0); + + loadMoreScores(() => beatmapInfo); + checkCount(10); + + beatmapEdit(() => beatmapInfo); + checkCount(0); + + loadMoreScores(() => beatmapInfo); + checkCount(10); + + clearScores(); + checkCount(0); + } + [Test] public void TestGlobalScoresDisplay() { @@ -123,6 +154,21 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } + private void beatmapEdit(Func beatmapInfo) + { + AddStep(@"Update beatmap via BeatmapManager", () => + { + BeatmapInfo info = beatmapInfo(); + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(info).Beatmap; + + beatmap.Difficulty.ApproachRate = 11; + beatmap.Difficulty.DrainRate = 11; + beatmap.Difficulty.OverallDifficulty = 11; + + beatmapManager.Save(info, beatmap); + }); + } + private void showPersonalBestWithNullPosition() { leaderboard.SetScores(leaderboard.Scores, new ScoreInfo From 391af2791b875a9928bba1d92dbcbae2128c0dd0 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:23:42 +0300 Subject: [PATCH 0074/1400] Fix CSharpWarnings::CS1574,CS1584,CS1581,CS1580 --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 62adcb9f94..8c912ef32a 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// The at the point in time when the score was set. + /// The .Hash at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty; From 6bf56aff73e07b7cd92241b251ae0ea0d9787b99 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:40:20 +0300 Subject: [PATCH 0075/1400] Add warning for `ScoreInfo` --- osu.Game/Scoring/ScoreInfo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 8c912ef32a..c57e06bee5 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -22,6 +22,13 @@ using Realms; namespace osu.Game.Scoring { + + /// + /// Store information about the score + /// + /// + /// If you work on inporting/adding score please ensure you provide both BeatmapInfo and BeatmapHash + /// [ExcludeFromDynamicCompile] [MapTo("Score")] public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IScoreInfo From ab7c9a200bdcc7804927ca68b9c59da58d22d49f Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:42:06 +0300 Subject: [PATCH 0076/1400] Fix a typo --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index c57e06bee5..85452ede17 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -27,7 +27,7 @@ namespace osu.Game.Scoring /// Store information about the score /// /// - /// If you work on inporting/adding score please ensure you provide both BeatmapInfo and BeatmapHash + /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash /// [ExcludeFromDynamicCompile] [MapTo("Score")] From 4ba915268c5e0a34824d2a03cb501a12574707a4 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:46:47 +0300 Subject: [PATCH 0077/1400] Change a comment into `RealmAccess` --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index b151fc6474..861a74e163 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -869,7 +869,7 @@ namespace osu.Game.Database break; case 26: - // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should + // Add ScoreInfo.BeatmapHash property to ensure the score corresponds to the version of beatmap it should // See: https://github.com/ppy/osu/issues/22062 string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); From 086b3eb542348048da062fde8234239e8d7d3ef6 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:50:52 +0300 Subject: [PATCH 0078/1400] Fix minor formating issues --- osu.Game/Scoring/ScoreInfo.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 85452ede17..d2ec4ebd5f 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -22,10 +22,9 @@ using Realms; namespace osu.Game.Scoring { - /// /// Store information about the score - /// + /// /// /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash /// From 5c113ddb030445c5099fdd2334d6b2608f5851ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 14:20:58 +0900 Subject: [PATCH 0079/1400] Reword xmldoc to read better --- osu.Game/Scoring/ScoreInfo.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d2ec4ebd5f..6213c65c75 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -23,11 +23,8 @@ using Realms; namespace osu.Game.Scoring { /// - /// Store information about the score + /// A realm model containing metadata for a single score. /// - /// - /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash - /// [ExcludeFromDynamicCompile] [MapTo("Score")] public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IScoreInfo @@ -35,8 +32,19 @@ namespace osu.Game.Scoring [PrimaryKey] public Guid ID { get; set; } + /// + /// The this score was made against. + /// + /// + /// When setting this, make sure to also set to allow relational consistency when a beatmap is potentially changed. + /// public BeatmapInfo BeatmapInfo { get; set; } = null!; + /// + /// The at the point in time when the score was set. + /// + public string BeatmapHash { get; set; } = string.Empty; + public RulesetInfo Ruleset { get; set; } = null!; public IList Files { get; } = null!; @@ -72,11 +80,6 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; - /// - /// The .Hash at the point in time when the score was set. - /// - public string BeatmapHash { get; set; } = string.Empty; - public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { Ruleset = ruleset ?? new RulesetInfo(); From c50ea89bc99f3dc142e85ecec3bf2504d3fd5f32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 14:24:06 +0900 Subject: [PATCH 0080/1400] Simplify migration to not rely on old/dynamic schema --- osu.Game/Database/RealmAccess.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 861a74e163..831e328439 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -869,17 +869,11 @@ namespace osu.Game.Database break; case 26: - // Add ScoreInfo.BeatmapHash property to ensure the score corresponds to the version of beatmap it should - // See: https://github.com/ppy/osu/issues/22062 - string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + // Add ScoreInfo.BeatmapHash property to ensure scores correspond to the correct version of beatmap. + var scores = migration.NewRealm.All(); - var oldScoreInfos = migration.OldRealm.DynamicApi.All(scoreInfoName); - var newScoreInfos = migration.NewRealm.All(); - - for (int i = 0; i < newScoreInfos.Count(); i++) - { - newScoreInfos.ElementAt(i).BeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; - } + foreach (var score in scores) + score.BeatmapHash = score.BeatmapInfo.Hash; break; } From c7eec371f52dd403a0bfaeea6f645d4a56dd3857 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:22:17 +0900 Subject: [PATCH 0081/1400] Clean up tests somewhat --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 13a24cd490..83bb58804d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -86,10 +86,10 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(20); clearScores(); @@ -114,13 +114,23 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); - beatmapEdit(() => beatmapInfo); + AddStep(@"Save beatmap with changes", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + + beatmap.Difficulty.ApproachRate = 11; + beatmap.Difficulty.DrainRate = 11; + beatmap.Difficulty.OverallDifficulty = 11; + + beatmapManager.Save(beatmapInfo, beatmap); + }); + checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); clearScores(); @@ -154,21 +164,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } - private void beatmapEdit(Func beatmapInfo) - { - AddStep(@"Update beatmap via BeatmapManager", () => - { - BeatmapInfo info = beatmapInfo(); - IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(info).Beatmap; - - beatmap.Difficulty.ApproachRate = 11; - beatmap.Difficulty.DrainRate = 11; - beatmap.Difficulty.OverallDifficulty = 11; - - beatmapManager.Save(info, beatmap); - }); - } - private void showPersonalBestWithNullPosition() { leaderboard.SetScores(leaderboard.Scores, new ScoreInfo @@ -208,9 +203,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - private void loadMoreScores(Func beatmapInfo) + private void importMoreScores(Func beatmapInfo) { - AddStep(@"Load new scores via manager", () => + AddStep(@"Import new scores", () => { foreach (var score in generateSampleScores(beatmapInfo())) scoreManager.Import(score); @@ -223,7 +218,7 @@ namespace osu.Game.Tests.Visual.SongSelect } private void checkCount(int expected) => - AddUntilStep("Correct count displayed", () => leaderboard.ChildrenOfType().Count() == expected); + AddUntilStep($"{expected} scores displayed", () => leaderboard.ChildrenOfType().Count(), () => Is.EqualTo(expected)); private static ScoreInfo[] generateSampleScores(BeatmapInfo beatmapInfo) { From d4d985ba0f0378d3c93a71b17e5cfcb793a7b41b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:34:46 +0900 Subject: [PATCH 0082/1400] Improve test to also check that reverting hash restores old scores --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 83bb58804d..01397563fd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -100,10 +100,11 @@ namespace osu.Game.Tests.Visual.SongSelect public void TestLocalScoresDisplayOnBeatmapEdit() { BeatmapInfo beatmapInfo = null!; + string originalHash = string.Empty; AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local); - AddStep(@"Set beatmap", () => + AddStep(@"Import beatmap", () => { beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); @@ -114,23 +115,39 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); + AddStep(@"Perform initial save to guarantee stable hash", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + beatmapManager.Save(beatmapInfo, beatmap); + + originalHash = beatmapInfo.Hash; + }); + importMoreScores(() => beatmapInfo); checkCount(10); - AddStep(@"Save beatmap with changes", () => + AddStep(@"Save with changes", () => { IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; - - beatmap.Difficulty.ApproachRate = 11; - beatmap.Difficulty.DrainRate = 11; - beatmap.Difficulty.OverallDifficulty = 11; - + beatmap.Difficulty.ApproachRate = 12; beatmapManager.Save(beatmapInfo, beatmap); }); + AddAssert("Hash changed", () => beatmapInfo.Hash, () => Is.Not.EqualTo(originalHash)); checkCount(0); importMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); + checkCount(20); + + AddStep(@"Revert changes", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + beatmap.Difficulty.ApproachRate = 8; + beatmapManager.Save(beatmapInfo, beatmap); + }); + + AddAssert("Hash restored", () => beatmapInfo.Hash, () => Is.EqualTo(originalHash)); checkCount(10); clearScores(); From 38031fdf2327cb50705cd14fa55c4cb1cb058a9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:38:07 +0900 Subject: [PATCH 0083/1400] Add test coverage of stores stored in database as well --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 01397563fd..c234cc8a9c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -84,16 +84,16 @@ namespace osu.Game.Tests.Visual.SongSelect }); clearScores(); - checkCount(0); + checkDisplayedCount(0); importMoreScores(() => beatmapInfo); - checkCount(10); + checkDisplayedCount(10); importMoreScores(() => beatmapInfo); - checkCount(20); + checkDisplayedCount(20); clearScores(); - checkCount(0); + checkDisplayedCount(0); } [Test] @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); clearScores(); - checkCount(0); + checkDisplayedCount(0); AddStep(@"Perform initial save to guarantee stable hash", () => { @@ -124,7 +124,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); importMoreScores(() => beatmapInfo); - checkCount(10); + + checkDisplayedCount(10); + checkStoredCount(10); AddStep(@"Save with changes", () => { @@ -134,11 +136,13 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("Hash changed", () => beatmapInfo.Hash, () => Is.Not.EqualTo(originalHash)); - checkCount(0); + checkDisplayedCount(0); + checkStoredCount(10); importMoreScores(() => beatmapInfo); importMoreScores(() => beatmapInfo); - checkCount(20); + checkDisplayedCount(20); + checkStoredCount(30); AddStep(@"Revert changes", () => { @@ -148,10 +152,12 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("Hash restored", () => beatmapInfo.Hash, () => Is.EqualTo(originalHash)); - checkCount(10); + checkDisplayedCount(10); + checkStoredCount(30); clearScores(); - checkCount(0); + checkDisplayedCount(0); + checkStoredCount(0); } [Test] @@ -234,9 +240,12 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Clear all scores", () => scoreManager.Delete()); } - private void checkCount(int expected) => + private void checkDisplayedCount(int expected) => AddUntilStep($"{expected} scores displayed", () => leaderboard.ChildrenOfType().Count(), () => Is.EqualTo(expected)); + private void checkStoredCount(int expected) => + AddUntilStep($"Total scores stored is {expected}", () => Realm.Run(r => r.All().Count(s => !s.DeletePending)), () => Is.EqualTo(expected)); + private static ScoreInfo[] generateSampleScores(BeatmapInfo beatmapInfo) { return new[] From 4fdba880b1efc2dcb49a2f3c64585f2e896a64ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:39:18 +0900 Subject: [PATCH 0084/1400] Fix xmldoc reference fail at CI --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 6213c65c75..02c7acf350 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -41,7 +41,7 @@ namespace osu.Game.Scoring public BeatmapInfo BeatmapInfo { get; set; } = null!; /// - /// The at the point in time when the score was set. + /// The at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty; From 5e0c4aa904f28435bb2ffad3967f2f4fe2b08802 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 8 Feb 2023 11:12:14 +0100 Subject: [PATCH 0085/1400] Refactor pooling for bubbles, tweak the animations a tad, add some clarifying comments --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 231 ++++++++++---------- 1 file changed, 114 insertions(+), 117 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 41430bb323..8cf9c619d7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -8,13 +8,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Performance; using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Skinning.Default; @@ -41,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => new[] { typeof(OsuModBarrelRoll), typeof(OsuModMagnetised), typeof(OsuModRepel) }; private PlayfieldAdjustmentContainer adjustmentContainer = null!; - private BubbleContainer bubbleContainer = null!; + private Container bubbleContainer = null!; private readonly Bindable currentCombo = new BindableInt(); @@ -49,6 +47,10 @@ namespace osu.Game.Rulesets.Osu.Mods private float bubbleRadius; private double bubbleFade; + private readonly DrawablePool bubblePool = new DrawablePool(100); + + private DrawableOsuHitObject lastJudgedHitobject = null!; + public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -56,6 +58,63 @@ namespace osu.Game.Rulesets.Osu.Mods currentCombo.BindTo(scoreProcessor.Combo); currentCombo.BindValueChanged(combo => maxSize = Math.Min(1.75f, (float)(1.25 + 0.005 * combo.NewValue)), true); + + scoreProcessor.NewJudgement += result => + { + if (result.HitObject is not OsuHitObject osuHitObject) return; + + DrawableOsuHitObject drawableOsuHitObject = lastJudgedHitobject; + + switch (result.HitObject) + { + case Slider: + case SpinnerTick: + break; + + default: + addBubble(); + break; + } + + void addBubble() + { + BubbleDrawable bubble = bubblePool.Get(); + bubble.Info = new BubbleInfo + { + InitialSize = new Vector2(bubbleRadius), + MaxSize = maxSize, + Position = getPosition(), + FadeTime = bubbleFade, + Colour = drawableOsuHitObject.AccentColour.Value, + IsHit = drawableOsuHitObject.IsHit, + }; + bubbleContainer.Add(bubble); + } + + Vector2 getPosition() + { + switch (drawableOsuHitObject) + { + // SliderHeads are derived from HitCircles, + // so we must handle them before to avoid them using the wrong positioning logic + case DrawableSliderHead: + return osuHitObject.Position; + + // Using hitobject position will cause issues with HitCircle placement due to stack leniency. + case DrawableHitCircle: + return drawableOsuHitObject.Position; + + default: + return osuHitObject.Position; + } + } + }; + + scoreProcessor.JudgementReverted += _ => + { + bubbleContainer.LastOrDefault()?.FinishTransforms(); + bubbleContainer.LastOrDefault()?.Expire(); + }; } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) @@ -69,178 +128,116 @@ namespace osu.Game.Rulesets.Osu.Mods adjustmentContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); - adjustmentContainer.Add(bubbleContainer = new BubbleContainer()); + adjustmentContainer.Add(bubbleContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }); drawableRuleset.KeyBindingInputManager.Add(adjustmentContainer); } protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); - protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); private void applyBubbleState(DrawableHitObject drawableObject) { + DrawableOsuHitObject osuHitObject = (DrawableOsuHitObject)drawableObject; + if (drawableObject is DrawableSlider slider) { slider.Body.OnSkinChanged += () => applySliderState(slider); applySliderState(slider); } - if (drawableObject is not DrawableOsuHitObject drawableOsuObject || !drawableObject.Judged) return; + if (osuHitObject == lastJudgedHitobject || !osuHitObject.Judged) return; - switch (drawableOsuObject) + switch (osuHitObject) { case DrawableSlider: case DrawableSpinnerTick: break; default: - addBubbleForObject(drawableOsuObject); + lastJudgedHitobject = osuHitObject; break; } } - // Makes the slider border coloured on all skins + // Makes the slider border coloured on all skins (for aesthetics) private void applySliderState(DrawableSlider slider) => ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; - private void addBubbleForObject(DrawableOsuHitObject hitObject) - { - bubbleContainer.Add - ( - new BubbleLifeTimeEntry - { - LifetimeStart = bubbleContainer.Time.Current, - Colour = hitObject.AccentColour.Value, - Position = hitObject.HitObject.Position, - InitialSize = new Vector2(bubbleRadius), - MaxSize = maxSize, - FadeTime = bubbleFade, - IsHit = hitObject.IsHit - } - ); - } - #region Pooled Bubble drawable - // LifetimeEntry flow is necessary to allow for correct rewind behaviour, can probably be made generic later if more mods are made requiring it - // Todo: find solution to bubbles rewinding in "groups" - private sealed partial class BubbleContainer : PooledDrawableWithLifetimeContainer - { - protected override bool RemoveRewoundEntry => true; - - private readonly DrawablePool pool; - - public BubbleContainer() - { - RelativeSizeAxes = Axes.Both; - AddInternal(pool = new DrawablePool(10, 1000)); - } - - protected override BubbleObject GetDrawable(BubbleLifeTimeEntry entry) => pool.Get(d => d.Apply(entry)); - } - - private sealed partial class BubbleObject : PoolableDrawableWithLifetime - { - private readonly BubbleDrawable bubbleDrawable; - - public BubbleObject() - { - InternalChild = bubbleDrawable = new BubbleDrawable(); - } - - protected override void OnApply(BubbleLifeTimeEntry entry) - { - base.OnApply(entry); - if (IsLoaded) - apply(entry); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - apply(Entry); - } - - private void apply(BubbleLifeTimeEntry? entry) - { - if (entry == null) return; - - ApplyTransformsAt(float.MinValue, true); - ClearTransforms(true); - - Position = entry.Position; - - bubbleDrawable.Animate(entry); - - LifetimeEnd = bubbleDrawable.LatestTransformEndTime; - } - } - - private partial class BubbleDrawable : CircularContainer + private partial class BubbleDrawable : PoolableDrawable { private readonly Box colourBox; + private readonly CircularContainer content; + + public BubbleInfo Info { get; set; } public BubbleDrawable() { - Anchor = Anchor.Centre; Origin = Anchor.Centre; - - MaskingSmoothness = 2; - BorderThickness = 0; - BorderColour = Colour4.White; - Masking = true; - EdgeEffect = new EdgeEffectParameters + InternalChild = content = new CircularContainer { - Type = EdgeEffectType.Shadow, - Radius = 3, - Colour = Colour4.Black.Opacity(0.05f) + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + MaskingSmoothness = 2, + BorderThickness = 0, + BorderColour = Colour4.White, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Radius = 3, + Colour = Colour4.Black.Opacity(0.05f), + }, + Child = colourBox = new Box { RelativeSizeAxes = Axes.Both, } }; - Child = colourBox = new Box { RelativeSizeAxes = Axes.Both, }; } - public void Animate(BubbleLifeTimeEntry entry) + protected override void PrepareForUse() { - Size = entry.InitialSize; - BorderThickness = Width / 3.5f; + Alpha = 1; + Colour = Colour4.White; + Scale = new Vector2(1); + Position = Info.Position; + Size = Info.InitialSize; + content.BorderThickness = Info.InitialSize.X / 3.5f; + content.BorderColour = Colour4.White; //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. - ColourInfo colourDarker = entry.Colour.Darken(0.1f); + ColourInfo colourDarker = Info.Colour.Darken(0.1f); // Main bubble scaling based on combo - this.ScaleTo(entry.MaxSize, getAnimationDuration() * 0.8f) + this.ScaleTo(Info.MaxSize, getAnimationDuration() * 0.8f) .Then() // Pop at the end of the bubbles life time - .ScaleTo(entry.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutQuint) - .FadeTo(0, getAnimationDuration() * 0.2f, Easing.OutCirc); + .ScaleTo(Info.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutQuint) + .FadeOutFromOne(getAnimationDuration() * 0.2f, Easing.OutCirc).Expire(); - if (!entry.IsHit) + if (Info.IsHit) { - Colour = Colour4.Black; - BorderColour = Colour4.Black; + colourBox.FadeColour(colourDarker); + + content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration() * 0.3f, Easing.OutQuint); + // Ripple effect utilises the border to reduce drawable count + content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration() * 0.3f, Easing.OutQuint) + // Avoids transparency overlap issues during the bubble "pop" + .Then().Schedule(() => content.BorderThickness = 0); return; } - colourBox.FadeColour(colourDarker); - - this.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration() * 0.3f, Easing.OutQuint); - - // Ripple effect utilises the border to reduce drawable count - this.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration() * 0.3f, Easing.OutQuint) - - // Avoids transparency overlap issues during the bubble "pop" - .Then().Schedule(() => - { - BorderThickness = 0; - BorderColour = Colour4.Transparent; - }); + Colour = Colour4.Black; // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationDuration() => 1700 + Math.Pow(entry.FadeTime, 1.07f); + double getAnimationDuration() => 1700 + Math.Pow(Info.FadeTime, 1.07f); } } - private class BubbleLifeTimeEntry : LifetimeEntry + private struct BubbleInfo { public Vector2 InitialSize { get; set; } From 6ff6e06a69256987d7a409a154c021df9988df30 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 12 Feb 2023 11:37:07 +0100 Subject: [PATCH 0086/1400] Simplify bubble container structure, modify some comments --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 8cf9c619d7..3e3fce5c27 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -38,8 +38,7 @@ namespace osu.Game.Rulesets.Osu.Mods // Compatibility with these seems potentially feasible in the future, blocked for now because they don't work as one would expect public override Type[] IncompatibleMods => new[] { typeof(OsuModBarrelRoll), typeof(OsuModMagnetised), typeof(OsuModRepel) }; - private PlayfieldAdjustmentContainer adjustmentContainer = null!; - private Container bubbleContainer = null!; + private PlayfieldAdjustmentContainer bubbleContainer = null!; private readonly Bindable currentCombo = new BindableInt(); @@ -119,20 +118,17 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - // Multiplying by 2 results in an initial size that is too large, hence 1.85 has been chosen - bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.85f); + // Multiplying by 2 results in an initial size that is too large, hence 1.90 has been chosen + // Also avoids the HitObject bleeding around the edges of the bubble drawable at minimum size + bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.90f); bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimePreempt * 2; // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) drawableRuleset.Playfield.DisplayJudgements.Value = false; - adjustmentContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); + bubbleContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); - adjustmentContainer.Add(bubbleContainer = new Container - { - RelativeSizeAxes = Axes.Both, - }); - drawableRuleset.KeyBindingInputManager.Add(adjustmentContainer); + drawableRuleset.KeyBindingInputManager.Add(bubbleContainer); } protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); From 74a58fb674945a5ec82f20ca2bffff91b6de776c Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 01:24:27 +0000 Subject: [PATCH 0087/1400] refactor: separate things in KeyCounter To implement different different sources of input for KeyCounter, it is now possible to create a Trigger class (to inherit) instead of inheriting KeyCounter. This eases the creation of more input sources (like for tests) while allowing to implement different UI variants. That way, if another variant of the key counter needs to implemented (for whathever reason), this can be done by only inheriting KeyCounter and changing how things are arranged visually. --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 9 +- osu.Game/Screens/Play/DefaultKeyCounter.cs | 105 +++++++++++++ osu.Game/Screens/Play/KeyCounter.cs | 157 +++++++------------- osu.Game/Screens/Play/KeyCounterAction.cs | 10 +- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 11 +- osu.Game/Screens/Play/KeyCounterMouse.cs | 11 +- 6 files changed, 177 insertions(+), 126 deletions(-) create mode 100644 osu.Game/Screens/Play/DefaultKeyCounter.cs diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index a5e442b7de..0fa1f0b332 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.UI .Select(b => b.GetAction()) .Distinct() .OrderBy(action => action) - .Select(action => new KeyCounterAction(action))); + .Select(action => keyCounter.CreateKeyCounter(new KeyCounterAction(action)))); } private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler @@ -176,11 +176,14 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(KeyBindingPressEvent e) => Target.Children.OfType>().Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); + public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.CounterTrigger is KeyCounterAction) + .Select(c => (KeyCounterAction)c.CounterTrigger) + .Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); public void OnReleased(KeyBindingReleaseEvent e) { - foreach (var c in Target.Children.OfType>()) + foreach (var c + in Target.Children.Where(c => c.CounterTrigger is KeyCounterAction).Select(c => (KeyCounterAction)c.CounterTrigger)) c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/DefaultKeyCounter.cs new file mode 100644 index 0000000000..dcb425ae1d --- /dev/null +++ b/osu.Game/Screens/Play/DefaultKeyCounter.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + public partial class DefaultKeyCounter : KeyCounter + { + private Sprite buttonSprite = null!; + private Sprite glowSprite = null!; + private Container textLayer = null!; + private SpriteText countSpriteText = null!; + + //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor + public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; + public Color4 KeyUpTextColor { get; set; } = Color4.White; + public double FadeTime { get; set; } + + public DefaultKeyCounter(Trigger trigger) + : base(trigger) + { + } + + [BackgroundDependencyLoader(true)] + private void load(TextureStore textures) + { + Children = new Drawable[] + { + buttonSprite = new Sprite + { + Texture = textures.Get(@"KeyCounter/key-up"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + glowSprite = new Sprite + { + Texture = textures.Get(@"KeyCounter/key-glow"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Alpha = 0 + }, + textLayer = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = Name, + Font = OsuFont.Numeric.With(size: 12), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(0, -0.25f), + Colour = KeyUpTextColor + }, + countSpriteText = new OsuSpriteText + { + Text = CountPresses.ToString(@"#,0"), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = new Vector2(0, 0.25f), + Colour = KeyUpTextColor + } + } + } + }; + // Set this manually because an element with Alpha=0 won't take it size to AutoSizeContainer, + // so the size can be changing between buttonSprite and glowSprite. + Height = buttonSprite.DrawHeight; + Width = buttonSprite.DrawWidth; + + IsLit.BindValueChanged(e => updateGlowSprite(e.NewValue), true); + PressesCount.BindValueChanged(e => countSpriteText.Text = e.NewValue.ToString(@"#,0"), true); + } + + private void updateGlowSprite(bool show) + { + if (show) + { + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); + } + else + { + double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; + glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); + } + } + } +} diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 4405542b3b..a612edbace 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,57 +1,37 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osuTK; -using osuTK.Graphics; +using osu.Framework.Input.Events; namespace osu.Game.Screens.Play { public abstract partial class KeyCounter : Container { - private Sprite buttonSprite; - private Sprite glowSprite; - private Container textLayer; - private SpriteText countSpriteText; + public readonly Trigger CounterTrigger; - public bool IsCounting { get; set; } = true; - private int countPresses; + protected Bindable IsCountingBindable = new BindableBool(true); + + protected Bindable PressesCount = new BindableInt + { + MinValue = 0 + }; + + public bool IsCounting + { + get => IsCountingBindable.Value; + set => IsCountingBindable.Value = value; + } public int CountPresses { - get => countPresses; - private set - { - if (countPresses != value) - { - countPresses = value; - countSpriteText.Text = value.ToString(@"#,0"); - } - } + get => PressesCount.Value; + private set => PressesCount.Value = value; } - private bool isLit; - - public bool IsLit - { - get => isLit; - protected set - { - if (isLit != value) - { - isLit = value; - updateGlowSprite(value); - } - } - } + protected Bindable IsLit = new BindableBool(); public void Increment() { @@ -69,82 +49,51 @@ namespace osu.Game.Screens.Play CountPresses--; } - //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor - public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; - public Color4 KeyUpTextColor { get; set; } = Color4.White; - public double FadeTime { get; set; } - - protected KeyCounter(string name) + protected override void LoadComplete() { - Name = name; + Add(CounterTrigger); + base.LoadComplete(); } - [BackgroundDependencyLoader(true)] - private void load(TextureStore textures) + protected override bool Handle(UIEvent e) => CounterTrigger.TriggerEvent(e); + + protected KeyCounter(Trigger trigger) { - Children = new Drawable[] - { - buttonSprite = new Sprite - { - Texture = textures.Get(@"KeyCounter/key-up"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - glowSprite = new Sprite - { - Texture = textures.Get(@"KeyCounter/key-glow"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Alpha = 0 - }, - textLayer = new Container - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = Name, - Font = OsuFont.Numeric.With(size: 12), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(0, -0.25f), - Colour = KeyUpTextColor - }, - countSpriteText = new OsuSpriteText - { - Text = CountPresses.ToString(@"#,0"), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(0, 0.25f), - Colour = KeyUpTextColor - } - } - } - }; - // Set this manually because an element with Alpha=0 won't take it size to AutoSizeContainer, - // so the size can be changing between buttonSprite and glowSprite. - Height = buttonSprite.DrawHeight; - Width = buttonSprite.DrawWidth; + CounterTrigger = trigger; + trigger.Target = this; + Name = trigger.Name; } - private void updateGlowSprite(bool show) + public abstract partial class Trigger : Component { - if (show) + private KeyCounter? target; + + public KeyCounter Target { - double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); - glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); - textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); + set => target = value; } - else + + protected Trigger(string name) { - double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; - glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); - textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); + Name = name; + } + + protected void Lit(bool increment = true) + { + if (target == null) return; + + target.IsLit.Value = true; + if (increment) + target.Increment(); + } + + protected void Unlit(bool preserve = true) + { + if (target == null) return; + + target.IsLit.Value = false; + if (!preserve) + target.Decrement(); } } } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 900d9bcd0e..058dbb1480 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public partial class KeyCounterAction : KeyCounter + public partial class KeyCounterAction : KeyCounter.Trigger where T : struct { public T Action { get; } @@ -23,9 +23,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return false; - IsLit = true; - if (forwards) - Increment(); + Lit(forwards); return false; } @@ -34,9 +32,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return; - IsLit = false; - if (!forwards) - Decrement(); + Unlit(forwards); } } } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index c5c8b7eeae..4306efd360 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public partial class KeyCounterKeyboard : KeyCounter + public partial class KeyCounterKeyboard : KeyCounter.Trigger { public Key Key { get; } @@ -21,17 +21,16 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { if (e.Key == Key) - { - IsLit = true; - Increment(); - } + Lit(); return base.OnKeyDown(e); } protected override void OnKeyUp(KeyUpEvent e) { - if (e.Key == Key) IsLit = false; + if (e.Key == Key) + Unlit(); + base.OnKeyUp(e); } } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index cf9c7c029f..00fca47ba2 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public partial class KeyCounterMouse : KeyCounter + public partial class KeyCounterMouse : KeyCounter.Trigger { public MouseButton Button { get; } @@ -39,17 +39,16 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == Button) - { - IsLit = true; - Increment(); - } + Lit(); return base.OnMouseDown(e); } protected override void OnMouseUp(MouseUpEvent e) { - if (e.Button == Button) IsLit = false; + if (e.Button == Button) + Unlit(); + base.OnMouseUp(e); } } From 11d0e185b8188d0986f4520131a14ba95ab2322f Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 01:33:09 +0000 Subject: [PATCH 0088/1400] refactor: separate impl of KeyCounterDisplay This allows for different layouts of display. Idk, maybe someone would want to mix both variants? (don't do this please). This commit is mostly prep for further changes. --- .../TestSceneOsuTouchInput.cs | 16 ++-- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../Visual/Gameplay/TestSceneKeyCounter.cs | 18 ++-- .../TestSceneSkinEditorMultipleSkins.cs | 2 +- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- .../Screens/Play/DefaultKeyCounterDisplay.cs | 91 +++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 2 +- osu.Game/Screens/Play/KeyCounterDisplay.cs | 76 ++-------------- 8 files changed, 121 insertions(+), 88 deletions(-) create mode 100644 osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 72bcec6045..cd30d8df83 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -34,9 +34,9 @@ namespace osu.Game.Rulesets.Osu.Tests [Resolved] private OsuConfigManager config { get; set; } = null!; - private TestActionKeyCounter leftKeyCounter = null!; + private DefaultKeyCounter leftKeyCounter = null!; - private TestActionKeyCounter rightKeyCounter = null!; + private DefaultKeyCounter rightKeyCounter = null!; private OsuInputManager osuInputManager = null!; @@ -59,14 +59,14 @@ namespace osu.Game.Rulesets.Osu.Tests Origin = Anchor.Centre, Children = new Drawable[] { - leftKeyCounter = new TestActionKeyCounter(OsuAction.LeftButton) + leftKeyCounter = new DefaultKeyCounter(new TestActionKeyCounter(OsuAction.LeftButton)) { Anchor = Anchor.Centre, Origin = Anchor.CentreRight, Depth = float.MinValue, X = -100, }, - rightKeyCounter = new TestActionKeyCounter(OsuAction.RightButton) + rightKeyCounter = new DefaultKeyCounter(new TestActionKeyCounter(OsuAction.RightButton)) { Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, @@ -579,7 +579,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkNotPressed(OsuAction action) => AddAssert($"Not pressing {action}", () => !osuInputManager.PressedActions.Contains(action)); private void checkPressed(OsuAction action) => AddAssert($"Is pressing {action}", () => osuInputManager.PressedActions.Contains(action)); - public partial class TestActionKeyCounter : KeyCounter, IKeyBindingHandler + public partial class TestActionKeyCounter : KeyCounter.Trigger, IKeyBindingHandler { public OsuAction Action { get; } @@ -593,8 +593,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (e.Action == Action) { - IsLit = true; - Increment(); + Lit(); } return false; @@ -602,7 +601,8 @@ namespace osu.Game.Rulesets.Osu.Tests public void OnReleased(KeyBindingReleaseEvent e) { - if (e.Action == Action) IsLit = false; + if (e.Action == Action) + Unlit(); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 5e1412d79b..4055ef9d3a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); scoreProcessor.Combo.Value = 1; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 890ac21b40..60ebce4f52 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -17,28 +17,28 @@ namespace osu.Game.Tests.Visual.Gameplay { public TestSceneKeyCounter() { - KeyCounterKeyboard testCounter; + DefaultKeyCounter testCounter; - KeyCounterDisplay kc = new KeyCounterDisplay + KeyCounterDisplay kc = new DefaultKeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Children = new KeyCounter[] + Children = new[] { - testCounter = new KeyCounterKeyboard(Key.X), - new KeyCounterKeyboard(Key.X), - new KeyCounterMouse(MouseButton.Left), - new KeyCounterMouse(MouseButton.Right), + testCounter = new DefaultKeyCounter(new KeyCounterKeyboard(Key.X)), + new DefaultKeyCounter(new KeyCounterKeyboard(Key.X)), + new DefaultKeyCounter(new KeyCounterMouse(MouseButton.Left)), + new DefaultKeyCounter(new KeyCounterMouse(MouseButton.Right)), }, }; AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); - kc.Add(new KeyCounterKeyboard(key)); + kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboard(key))); }); - Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; + Key testKey = ((KeyCounterKeyboard)kc.Children.First().CounterTrigger).Key; void addPressKeyStep() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index d5b6ac38cb..56cf56efd9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); scoreProcessor.Combo.Value = 1; return new Container diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 1f2329af4a..f713bca081 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space)); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); action?.Invoke(hudOverlay); diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs new file mode 100644 index 0000000000..d643070e06 --- /dev/null +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -0,0 +1,91 @@ +// 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; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + public partial class DefaultKeyCounterDisplay : KeyCounterDisplay + { + private const int duration = 100; + private const double key_fade_time = 80; + + protected override Container Content => KeyFlow; + + public new IReadOnlyList Children + { + get => (IReadOnlyList)base.Children; + set => base.Children = value; + } + + public DefaultKeyCounterDisplay() + { + InternalChild = KeyFlow = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Alpha = 0, + }; + } + + protected override void Update() + { + base.Update(); + + // Don't use autosize as it will shrink to zero when KeyFlow is hidden. + // In turn this can cause the display to be masked off screen and never become visible again. + Size = KeyFlow.Size; + } + + public override void Add(KeyCounter key) + { + base.Add(key); + if (key is not DefaultKeyCounter defaultKey) + throw new ArgumentException($"{key.GetType()} is not a supported {nameof(KeyCounter)}.", nameof(key)); + + defaultKey.FadeTime = key_fade_time; + defaultKey.KeyDownTextColor = KeyDownTextColor; + defaultKey.KeyUpTextColor = KeyUpTextColor; + } + + protected override void UpdateVisibility() => + // Isolate changing visibility of the key counters from fading this component. + KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); + + private Color4 keyDownTextColor = Color4.DarkGray; + + public Color4 KeyDownTextColor + { + get => keyDownTextColor; + set + { + if (value != keyDownTextColor) + { + keyDownTextColor = value; + foreach (var child in Children) + child.KeyDownTextColor = value; + } + } + } + + private Color4 keyUpTextColor = Color4.White; + + public Color4 KeyUpTextColor + { + get => keyUpTextColor; + set + { + if (value != keyUpTextColor) + { + keyUpTextColor = value; + foreach (var child in Children) + child.KeyUpTextColor = value; + } + } + } + } +} diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 4d1f0b96b6..a09da14132 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -327,7 +327,7 @@ namespace osu.Game.Screens.Play ShowHealth = { BindTarget = ShowHealthBar } }; - protected KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay + protected KeyCounterDisplay CreateKeyCounter() => new DefaultKeyCounterDisplay { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index bb50d4a539..b06d1adfa0 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -12,18 +12,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Game.Configuration; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play { - public partial class KeyCounterDisplay : Container + public abstract partial class KeyCounterDisplay : Container { - private const int duration = 100; - private const double key_fade_time = 80; + protected readonly Bindable ConfigVisibility = new Bindable(); - private readonly Bindable configVisibility = new Bindable(); - - protected readonly FillFlowContainer KeyFlow; + protected FillFlowContainer KeyFlow; protected override Container Content => KeyFlow; @@ -33,48 +29,26 @@ namespace osu.Game.Screens.Play /// public readonly Bindable AlwaysVisible = new Bindable(true); - public KeyCounterDisplay() - { - InternalChild = KeyFlow = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Alpha = 0, - }; - } - - protected override void Update() - { - base.Update(); - - // Don't use autosize as it will shrink to zero when KeyFlow is hidden. - // In turn this can cause the display to be masked off screen and never become visible again. - Size = KeyFlow.Size; - } - public override void Add(KeyCounter key) { ArgumentNullException.ThrowIfNull(key); base.Add(key); key.IsCounting = IsCounting; - key.FadeTime = key_fade_time; - key.KeyDownTextColor = KeyDownTextColor; - key.KeyUpTextColor = KeyUpTextColor; } [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - config.BindWith(OsuSetting.KeyOverlay, configVisibility); + config.BindWith(OsuSetting.KeyOverlay, ConfigVisibility); } protected override void LoadComplete() { base.LoadComplete(); - AlwaysVisible.BindValueChanged(_ => updateVisibility()); - configVisibility.BindValueChanged(_ => updateVisibility(), true); + AlwaysVisible.BindValueChanged(_ => UpdateVisibility()); + ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true); } private bool isCounting = true; @@ -92,41 +66,7 @@ namespace osu.Game.Screens.Play } } - private Color4 keyDownTextColor = Color4.DarkGray; - - public Color4 KeyDownTextColor - { - get => keyDownTextColor; - set - { - if (value != keyDownTextColor) - { - keyDownTextColor = value; - foreach (var child in Children) - child.KeyDownTextColor = value; - } - } - } - - private Color4 keyUpTextColor = Color4.White; - - public Color4 KeyUpTextColor - { - get => keyUpTextColor; - set - { - if (value != keyUpTextColor) - { - keyUpTextColor = value; - foreach (var child in Children) - child.KeyUpTextColor = value; - } - } - } - - private void updateVisibility() => - // Isolate changing visibility of the key counters from fading this component. - KeyFlow.FadeTo(AlwaysVisible.Value || configVisibility.Value ? 1 : 0, duration); + protected abstract void UpdateVisibility(); public override bool HandleNonPositionalInput => receptor == null; public override bool HandlePositionalInput => receptor == null; @@ -141,6 +81,8 @@ namespace osu.Game.Screens.Play this.receptor = receptor; } + public virtual KeyCounter CreateKeyCounter(KeyCounter.Trigger trigger) => new DefaultKeyCounter(trigger); + public partial class Receptor : Drawable { protected readonly KeyCounterDisplay Target; From aa2e0028ab3c20cb4e0afe412e12670e3b14f96f Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 10:59:10 +0000 Subject: [PATCH 0089/1400] refactor: hide trigger presence from content --- osu.Game/Screens/Play/KeyCounter.cs | 32 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index a612edbace..b111305b22 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -14,6 +14,10 @@ namespace osu.Game.Screens.Play protected Bindable IsCountingBindable = new BindableBool(true); + private readonly Container content; + + protected override Container Content => content; + protected Bindable PressesCount = new BindableInt { MinValue = 0 @@ -31,6 +35,21 @@ namespace osu.Game.Screens.Play private set => PressesCount.Value = value; } + protected KeyCounter(Trigger trigger) + { + InternalChildren = new Drawable[] + { + content = new Container + { + RelativeSizeAxes = Axes.Both + }, + CounterTrigger = trigger, + }; + + CounterTrigger.Target = this; + Name = trigger.Name; + } + protected Bindable IsLit = new BindableBool(); public void Increment() @@ -49,21 +68,8 @@ namespace osu.Game.Screens.Play CountPresses--; } - protected override void LoadComplete() - { - Add(CounterTrigger); - base.LoadComplete(); - } - protected override bool Handle(UIEvent e) => CounterTrigger.TriggerEvent(e); - protected KeyCounter(Trigger trigger) - { - CounterTrigger = trigger; - trigger.Target = this; - Name = trigger.Name; - } - public abstract partial class Trigger : Component { private KeyCounter? target; From 7aaaf7fca2d598998d7c407a3b259db985484b06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2023 16:55:35 +0900 Subject: [PATCH 0090/1400] Combine and attempt to simplify the score import / preparation process further --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 3 + osu.Game/Screens/Play/Player.cs | 82 ++++++++++----------- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index a5e442b7de..7bf0482673 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -39,6 +39,9 @@ namespace osu.Game.Rulesets.UI { set { + if (value == recorder) + return; + if (value != null && recorder != null) throw new InvalidOperationException("Cannot attach more than one recorder"); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0825f36a0a..bc453d2151 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -276,7 +276,7 @@ namespace osu.Game.Screens.Play }, FailOverlay = new FailOverlay { - SaveReplay = prepareAndImportScore, + SaveReplay = async () => await prepareAndImportScoreAsync(true).ConfigureAwait(false), OnRetry = () => Restart(), OnQuit = () => PerformExit(true), }, @@ -614,7 +614,7 @@ namespace osu.Game.Screens.Play resultsDisplayDelegate?.Cancel(); // import current score if possible. - attemptScoreImport(); + prepareAndImportScoreAsync(); // The actual exit is performed if // - the pause / fail dialog was not requested @@ -772,10 +772,7 @@ namespace osu.Game.Screens.Play if (prepareScoreForDisplayTask == null) { // Try importing score since the task hasn't been invoked yet. - if (!attemptScoreImport()) - // If attempt failed, trying again is unnecessary - resultsDisplayDelegate?.Cancel(); - + prepareAndImportScoreAsync(); return; } @@ -785,6 +782,12 @@ namespace osu.Game.Screens.Play resultsDisplayDelegate?.Cancel(); + if (prepareScoreForDisplayTask.GetResultSafely() == null) + { + // If score import did not occur, we do not want to show the results screen. + return; + } + if (!this.IsCurrentScreen()) // This player instance may already be in the process of exiting. return; @@ -796,53 +799,48 @@ namespace osu.Game.Screens.Play } /// - /// Attempts to run + /// Asynchronously run score preparation operations (database import, online submission etc.). /// - /// - /// Whether the attempt was successful - /// - private bool attemptScoreImport() + /// Whether the score should be imported even if non-passing (or the current configuration doesn't allow for it). + /// The final score. + [ItemCanBeNull] + private Task prepareAndImportScoreAsync(bool forceImport = false) { // Ensure we are not writing to the replay any more, as we are about to consume and store the score. DrawableRuleset.SetRecordTarget(null); + if (prepareScoreForDisplayTask != null) + return prepareScoreForDisplayTask; + // We do not want to import the score in cases where we don't show results bool canShowResults = Configuration.ShowResults && ScoreProcessor.HasCompleted.Value && GameplayState.HasPassed; - if (!canShowResults) - return false; + if (!canShowResults && !forceImport) + return Task.FromResult(null); - prepareScoreForDisplayTask ??= Task.Run(prepareAndImportScore); - - return true; - } - - /// - /// Asynchronously run score preparation operations (database import, online submission etc.). - /// - /// The final score. - private async Task prepareAndImportScore() - { - var scoreCopy = Score.DeepClone(); - - try + return prepareScoreForDisplayTask = Task.Run(async () => { - await PrepareScoreForResultsAsync(scoreCopy).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.Error(ex, @"Score preparation failed!"); - } + var scoreCopy = Score.DeepClone(); - try - { - await ImportScore(scoreCopy).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.Error(ex, @"Score import failed!"); - } + try + { + await PrepareScoreForResultsAsync(scoreCopy).ConfigureAwait(false); + } + catch (Exception ex) + { + Logger.Error(ex, @"Score preparation failed!"); + } - return scoreCopy.ScoreInfo; + try + { + await ImportScore(scoreCopy).ConfigureAwait(false); + } + catch (Exception ex) + { + Logger.Error(ex, @"Score import failed!"); + } + + return scoreCopy.ScoreInfo; + }); } protected override bool OnScroll(ScrollEvent e) From d100a4a4915b3c67c48cf790822e93da90dc02be Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 14 Feb 2023 10:12:37 +0100 Subject: [PATCH 0091/1400] Make `lastJudgedHitObject` nullable, and fix typo in name. --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 23 ++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 3e3fce5c27..40c235911c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -2,8 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -48,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly DrawablePool bubblePool = new DrawablePool(100); - private DrawableOsuHitObject lastJudgedHitobject = null!; + private DrawableOsuHitObject? lastJudgedHitObject; public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; @@ -60,9 +62,11 @@ namespace osu.Game.Rulesets.Osu.Mods scoreProcessor.NewJudgement += result => { - if (result.HitObject is not OsuHitObject osuHitObject) return; + if (result.HitObject is not OsuHitObject osuHitObject || lastJudgedHitObject.IsNull()) return; - DrawableOsuHitObject drawableOsuHitObject = lastJudgedHitobject; + Debug.Assert(result.HitObject == lastJudgedHitObject.HitObject); + + DrawableOsuHitObject drawableOsuHitObject = lastJudgedHitObject; switch (result.HitObject) { @@ -144,18 +148,9 @@ namespace osu.Game.Rulesets.Osu.Mods applySliderState(slider); } - if (osuHitObject == lastJudgedHitobject || !osuHitObject.Judged) return; + if (osuHitObject == lastJudgedHitObject || !osuHitObject.Judged) return; - switch (osuHitObject) - { - case DrawableSlider: - case DrawableSpinnerTick: - break; - - default: - lastJudgedHitobject = osuHitObject; - break; - } + lastJudgedHitObject = osuHitObject; } // Makes the slider border coloured on all skins (for aesthetics) From 2d49b5f9d66150598260451250c11736bdad87bc Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 14 Feb 2023 14:03:48 +0100 Subject: [PATCH 0092/1400] Move bubbles to ruleset overlays container --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 40c235911c..732626b177 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Mods bubbleContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); - drawableRuleset.KeyBindingInputManager.Add(bubbleContainer); + drawableRuleset.Overlays.Add(bubbleContainer); } protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); From 92c61c73396939363b3c6bd7ffffb083e3c74116 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 14 Feb 2023 16:31:34 +0100 Subject: [PATCH 0093/1400] move logic for bubble invoking to `ApplyToDrawableHitobject()`` method --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 85 +++++++++------------ 1 file changed, 34 insertions(+), 51 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 732626b177..4a8c11e7ff 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -2,10 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -25,7 +23,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public partial class OsuModBubbles : ModWithVisibilityAdjustment, IApplicableToDrawableRuleset, IApplicableToScoreProcessor + public partial class OsuModBubbles : Mod, IApplicableToDrawableRuleset, IApplicableToDrawableHitObject, IApplicableToScoreProcessor { public override string Name => "Bubbles"; @@ -50,8 +48,6 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly DrawablePool bubblePool = new DrawablePool(100); - private DrawableOsuHitObject? lastJudgedHitObject; - public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -60,15 +56,41 @@ namespace osu.Game.Rulesets.Osu.Mods currentCombo.BindValueChanged(combo => maxSize = Math.Min(1.75f, (float)(1.25 + 0.005 * combo.NewValue)), true); - scoreProcessor.NewJudgement += result => + scoreProcessor.JudgementReverted += _ => { - if (result.HitObject is not OsuHitObject osuHitObject || lastJudgedHitObject.IsNull()) return; + bubbleContainer.LastOrDefault()?.ClearTransforms(); + bubbleContainer.LastOrDefault()?.Expire(); + }; + } - Debug.Assert(result.HitObject == lastJudgedHitObject.HitObject); + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + // Multiplying by 2 results in an initial size that is too large, hence 1.90 has been chosen + // Also avoids the HitObject bleeding around the edges of the bubble drawable at minimum size + bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.90f); + bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimePreempt * 2; - DrawableOsuHitObject drawableOsuHitObject = lastJudgedHitObject; + // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) + drawableRuleset.Playfield.DisplayJudgements.Value = false; - switch (result.HitObject) + bubbleContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); + + drawableRuleset.Overlays.Add(bubbleContainer); + } + + public void ApplyToDrawableHitObject(DrawableHitObject drawableObject) + { + if (drawableObject is DrawableSlider slider) + { + applySliderState(slider); + slider.Body.OnSkinChanged += () => applySliderState(slider); + } + + drawableObject.OnNewResult += (drawable, _) => + { + if (drawable is not DrawableOsuHitObject drawableOsuHitObject) return; + + switch (drawableOsuHitObject.HitObject) { case Slider: case SpinnerTick: @@ -101,56 +123,17 @@ namespace osu.Game.Rulesets.Osu.Mods // SliderHeads are derived from HitCircles, // so we must handle them before to avoid them using the wrong positioning logic case DrawableSliderHead: - return osuHitObject.Position; + return drawableOsuHitObject.HitObject.Position; // Using hitobject position will cause issues with HitCircle placement due to stack leniency. case DrawableHitCircle: return drawableOsuHitObject.Position; default: - return osuHitObject.Position; + return drawableOsuHitObject.HitObject.Position; } } }; - - scoreProcessor.JudgementReverted += _ => - { - bubbleContainer.LastOrDefault()?.FinishTransforms(); - bubbleContainer.LastOrDefault()?.Expire(); - }; - } - - public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) - { - // Multiplying by 2 results in an initial size that is too large, hence 1.90 has been chosen - // Also avoids the HitObject bleeding around the edges of the bubble drawable at minimum size - bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.90f); - bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimePreempt * 2; - - // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) - drawableRuleset.Playfield.DisplayJudgements.Value = false; - - bubbleContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); - - drawableRuleset.Overlays.Add(bubbleContainer); - } - - protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); - protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyBubbleState(hitObject); - - private void applyBubbleState(DrawableHitObject drawableObject) - { - DrawableOsuHitObject osuHitObject = (DrawableOsuHitObject)drawableObject; - - if (drawableObject is DrawableSlider slider) - { - slider.Body.OnSkinChanged += () => applySliderState(slider); - applySliderState(slider); - } - - if (osuHitObject == lastJudgedHitObject || !osuHitObject.Judged) return; - - lastJudgedHitObject = osuHitObject; } // Makes the slider border coloured on all skins (for aesthetics) From 5db624159b1230e7ca522e9ab6cdec8194e8a0fa Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Tue, 14 Feb 2023 18:06:43 +0100 Subject: [PATCH 0094/1400] Change bubble rewind removal to be in `ApplyToDrawableHitObject` method. --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 4a8c11e7ff..f521dfb1f8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -55,12 +55,6 @@ namespace osu.Game.Rulesets.Osu.Mods currentCombo.BindTo(scoreProcessor.Combo); currentCombo.BindValueChanged(combo => maxSize = Math.Min(1.75f, (float)(1.25 + 0.005 * combo.NewValue)), true); - - scoreProcessor.JudgementReverted += _ => - { - bubbleContainer.LastOrDefault()?.ClearTransforms(); - bubbleContainer.LastOrDefault()?.Expire(); - }; } public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) @@ -134,6 +128,16 @@ namespace osu.Game.Rulesets.Osu.Mods } } }; + + drawableObject.OnRevertResult += (drawable, _) => + { + if (drawable.HitObject is SpinnerTick or Slider) return; + + BubbleDrawable? lastBubble = bubbleContainer.OfType().LastOrDefault(); + + lastBubble?.ClearTransforms(); + lastBubble?.Expire(); + }; } // Makes the slider border coloured on all skins (for aesthetics) From 82292d61621e49a158c576879ae56f47a9e52a84 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 15 Feb 2023 09:30:12 +0100 Subject: [PATCH 0095/1400] Make colouring for bubble more intuitive and remove unnecessary alpha assignment --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index f521dfb1f8..2a4208065d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -177,8 +177,7 @@ namespace osu.Game.Rulesets.Osu.Mods protected override void PrepareForUse() { - Alpha = 1; - Colour = Colour4.White; + Colour = Info.IsHit ? Colour4.White : Colour4.Black; Scale = new Vector2(1); Position = Info.Position; Size = Info.InitialSize; @@ -204,12 +203,8 @@ namespace osu.Game.Rulesets.Osu.Mods content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration() * 0.3f, Easing.OutQuint) // Avoids transparency overlap issues during the bubble "pop" .Then().Schedule(() => content.BorderThickness = 0); - - return; } - Colour = Colour4.Black; - // The absolute length of the bubble's animation, can be used in fractions for animations of partial length double getAnimationDuration() => 1700 + Math.Pow(Info.FadeTime, 1.07f); } From e9a7d90273c57dbd7dfb30ff32b9ca21dc9b6d39 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 15 Feb 2023 09:33:18 +0100 Subject: [PATCH 0096/1400] make transform duration for bubble a method instead of a variable --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 2a4208065d..a88bf6b813 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -187,26 +187,26 @@ namespace osu.Game.Rulesets.Osu.Mods //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. ColourInfo colourDarker = Info.Colour.Darken(0.1f); + // The absolute length of the bubble's animation, can be used in fractions for animations of partial length + double getAnimationDuration = 1700 + Math.Pow(Info.FadeTime, 1.07f); + // Main bubble scaling based on combo - this.ScaleTo(Info.MaxSize, getAnimationDuration() * 0.8f) + this.ScaleTo(Info.MaxSize, getAnimationDuration * 0.8f) .Then() // Pop at the end of the bubbles life time - .ScaleTo(Info.MaxSize * 1.5f, getAnimationDuration() * 0.2f, Easing.OutQuint) - .FadeOutFromOne(getAnimationDuration() * 0.2f, Easing.OutCirc).Expire(); + .ScaleTo(Info.MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) + .FadeOutFromOne(getAnimationDuration * 0.2f, Easing.OutCirc).Expire(); if (Info.IsHit) { colourBox.FadeColour(colourDarker); - content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration() * 0.3f, Easing.OutQuint); + content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration * 0.3f, Easing.OutQuint); // Ripple effect utilises the border to reduce drawable count - content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration() * 0.3f, Easing.OutQuint) + content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) // Avoids transparency overlap issues during the bubble "pop" .Then().Schedule(() => content.BorderThickness = 0); } - - // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationDuration() => 1700 + Math.Pow(Info.FadeTime, 1.07f); } } From 1d1c794ccfde23743574d8579da648cf42f4e4d4 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 15 Feb 2023 09:37:47 +0100 Subject: [PATCH 0097/1400] Invert pointless nested `if` statement --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index a88bf6b813..d75c82dc85 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -197,16 +197,15 @@ namespace osu.Game.Rulesets.Osu.Mods .ScaleTo(Info.MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) .FadeOutFromOne(getAnimationDuration * 0.2f, Easing.OutCirc).Expire(); - if (Info.IsHit) - { - colourBox.FadeColour(colourDarker); + if (!Info.IsHit) return; - content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration * 0.3f, Easing.OutQuint); - // Ripple effect utilises the border to reduce drawable count - content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) - // Avoids transparency overlap issues during the bubble "pop" - .Then().Schedule(() => content.BorderThickness = 0); - } + colourBox.FadeColour(colourDarker); + + content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration * 0.3f, Easing.OutQuint); + // Ripple effect utilises the border to reduce drawable count + content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) + // Avoids transparency overlap issues during the bubble "pop" + .Then().Schedule(() => content.BorderThickness = 0); } } From 297963b461cfdfd6083784ab0c4561c43c1d4a93 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 15 Feb 2023 10:00:46 +0100 Subject: [PATCH 0098/1400] Remove BubbleInfo struct and consume `DrawableOsuHitObject`s directly --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 102 +++++++++----------- 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index d75c82dc85..981932c580 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -2,8 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -98,35 +101,14 @@ namespace osu.Game.Rulesets.Osu.Mods void addBubble() { BubbleDrawable bubble = bubblePool.Get(); - bubble.Info = new BubbleInfo - { - InitialSize = new Vector2(bubbleRadius), - MaxSize = maxSize, - Position = getPosition(), - FadeTime = bubbleFade, - Colour = drawableOsuHitObject.AccentColour.Value, - IsHit = drawableOsuHitObject.IsHit, - }; + + bubble.DrawableOsuHitObject = drawableOsuHitObject; + bubble.InitialSize = new Vector2(bubbleRadius); + bubble.FadeTime = bubbleFade; + bubble.MaxSize = maxSize; + bubbleContainer.Add(bubble); } - - Vector2 getPosition() - { - switch (drawableOsuHitObject) - { - // SliderHeads are derived from HitCircles, - // so we must handle them before to avoid them using the wrong positioning logic - case DrawableSliderHead: - return drawableOsuHitObject.HitObject.Position; - - // Using hitobject position will cause issues with HitCircle placement due to stack leniency. - case DrawableHitCircle: - return drawableOsuHitObject.Position; - - default: - return drawableOsuHitObject.HitObject.Position; - } - } }; drawableObject.OnRevertResult += (drawable, _) => @@ -148,11 +130,15 @@ namespace osu.Game.Rulesets.Osu.Mods private partial class BubbleDrawable : PoolableDrawable { + public DrawableOsuHitObject? DrawableOsuHitObject { get; set; } + + public Vector2 InitialSize { get; set; } + public double FadeTime { get; set; } + public float MaxSize { get; set; } + private readonly Box colourBox; private readonly CircularContainer content; - public BubbleInfo Info { get; set; } - public BubbleDrawable() { Origin = Anchor.Centre; @@ -177,27 +163,30 @@ namespace osu.Game.Rulesets.Osu.Mods protected override void PrepareForUse() { - Colour = Info.IsHit ? Colour4.White : Colour4.Black; + Debug.Assert(DrawableOsuHitObject.IsNotNull()); + + Colour = DrawableOsuHitObject.IsHit ? Colour4.White : Colour4.Black; + Alpha = 1; Scale = new Vector2(1); - Position = Info.Position; - Size = Info.InitialSize; - content.BorderThickness = Info.InitialSize.X / 3.5f; + Position = getPosition(); + Size = InitialSize; + content.BorderThickness = InitialSize.X / 3.5f; content.BorderColour = Colour4.White; //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. - ColourInfo colourDarker = Info.Colour.Darken(0.1f); + ColourInfo colourDarker = DrawableOsuHitObject.AccentColour.Value.Darken(0.1f); // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationDuration = 1700 + Math.Pow(Info.FadeTime, 1.07f); + double getAnimationDuration = 1700 + Math.Pow(FadeTime, 1.07f); // Main bubble scaling based on combo - this.ScaleTo(Info.MaxSize, getAnimationDuration * 0.8f) + this.ScaleTo(MaxSize, getAnimationDuration * 0.8f) .Then() // Pop at the end of the bubbles life time - .ScaleTo(Info.MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) - .FadeOutFromOne(getAnimationDuration * 0.2f, Easing.OutCirc).Expire(); + .ScaleTo(MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) + .FadeOut(getAnimationDuration * 0.2f, Easing.OutCirc).Expire(); - if (!Info.IsHit) return; + if (!DrawableOsuHitObject.IsHit) return; colourBox.FadeColour(colourDarker); @@ -206,26 +195,27 @@ namespace osu.Game.Rulesets.Osu.Mods content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) // Avoids transparency overlap issues during the bubble "pop" .Then().Schedule(() => content.BorderThickness = 0); + + Vector2 getPosition() + { + switch (DrawableOsuHitObject) + { + // SliderHeads are derived from HitCircles, + // so we must handle them before to avoid them using the wrong positioning logic + case DrawableSliderHead: + return DrawableOsuHitObject.HitObject.Position; + + // Using hitobject position will cause issues with HitCircle placement due to stack leniency. + case DrawableHitCircle: + return DrawableOsuHitObject.Position; + + default: + return DrawableOsuHitObject.HitObject.Position; + } + } } } - private struct BubbleInfo - { - public Vector2 InitialSize { get; set; } - - public float MaxSize { get; set; } - - public Vector2 Position { get; set; } - - public Colour4 Colour { get; set; } - - // FadeTime is based on the approach rate of the beatmap. - public double FadeTime { get; set; } - - // Whether the corresponding HitObject was hit - public bool IsHit { get; set; } - } - #endregion } } From 8fc35b159f87a10a087c79c469d981ff9750bc95 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Wed, 15 Feb 2023 10:04:50 +0100 Subject: [PATCH 0099/1400] Remove dysfunctional slider colouring --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 981932c580..4edf726f26 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -18,7 +18,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Scoring; @@ -77,12 +76,6 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObject(DrawableHitObject drawableObject) { - if (drawableObject is DrawableSlider slider) - { - applySliderState(slider); - slider.Body.OnSkinChanged += () => applySliderState(slider); - } - drawableObject.OnNewResult += (drawable, _) => { if (drawable is not DrawableOsuHitObject drawableOsuHitObject) return; @@ -122,10 +115,6 @@ namespace osu.Game.Rulesets.Osu.Mods }; } - // Makes the slider border coloured on all skins (for aesthetics) - private void applySliderState(DrawableSlider slider) => - ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; - #region Pooled Bubble drawable private partial class BubbleDrawable : PoolableDrawable From 1f586c129c1b27fee148db26846e69eb6febc1d8 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 15 Feb 2023 22:15:44 +0300 Subject: [PATCH 0100/1400] fix applied --- osu.Game/Database/LegacyExporter.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 09d6913dd9..c56c17222d 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.IO; using osu.Framework.Platform; @@ -18,6 +19,14 @@ namespace osu.Game.Database public abstract class LegacyExporter where TModel : class, IHasNamedFiles { + /// + /// Max length of filename (including extension) + /// + /// + /// This constant is smaller 256 because adds additional "_" to the end of the path + /// + private const int max_path = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) + /// /// The file extension for exports (including the leading '.'). /// @@ -33,7 +42,16 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } - protected virtual string GetFilename(TModel item) => item.GetDisplayString(); + protected virtual string GetFilename(TModel item) + { + string fileName = item.GetDisplayString(); + + int fileNameLength = fileName.Length - FileExtension.Length; + if (fileNameLength > max_path) + fileName = fileName.Remove(max_path - FileExtension.Length); //Truncating the name to fit the path limit + + return fileName; + } /// /// Exports an item to a legacy (.zip based) package. From 387a6f1330b3e22360565dd07a4a7048eae3e4d8 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 15 Feb 2023 22:43:43 +0300 Subject: [PATCH 0101/1400] Move logic to `Export` method --- osu.Game/Database/LegacyExporter.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index cd0b50c109..483c3cbd5c 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -43,16 +43,7 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } - protected virtual string GetFilename(TModel item) - { - string fileName = item.GetDisplayString(); - - int fileNameLength = fileName.Length - FileExtension.Length; - if (fileNameLength > max_path) - fileName = fileName.Remove(max_path - FileExtension.Length); //Truncating the name to fit the path limit - - return fileName; - } + protected virtual string GetFilename(TModel item) => item.GetDisplayString(); /// /// Exports an item to a legacy (.zip based) package. @@ -68,6 +59,15 @@ namespace osu.Game.Database .Concat(exportStorage.GetDirectories(string.Empty)); string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); + + if (filename.Length > max_path) + { + string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); + + filenameWithoutExtension = filenameWithoutExtension.Remove(max_path - FileExtension.Length); //Truncating the name to fit the path limit + filename = $"{filenameWithoutExtension}{FileExtension}"; + } + using (var stream = exportStorage.CreateFileSafely(filename)) ExportModelTo(item, stream); From 157bba78305b3474fecc5a529b95c954b994e9e9 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 21:59:17 +0000 Subject: [PATCH 0102/1400] refactor: rename `Trigger` class to `InputTrigger` --- .../TestSceneOsuTouchInput.cs | 2 +- .../Visual/Gameplay/TestSceneKeyCounter.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 6 +++--- osu.Game/Screens/Play/DefaultKeyCounter.cs | 2 +- osu.Game/Screens/Play/KeyCounter.cs | 14 +++++++------- osu.Game/Screens/Play/KeyCounterAction.cs | 2 +- osu.Game/Screens/Play/KeyCounterDisplay.cs | 2 +- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 2 +- osu.Game/Screens/Play/KeyCounterMouse.cs | 2 +- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index cd30d8df83..1a273153bd 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -579,7 +579,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkNotPressed(OsuAction action) => AddAssert($"Not pressing {action}", () => !osuInputManager.PressedActions.Contains(action)); private void checkPressed(OsuAction action) => AddAssert($"Is pressing {action}", () => osuInputManager.PressedActions.Contains(action)); - public partial class TestActionKeyCounter : KeyCounter.Trigger, IKeyBindingHandler + public partial class TestActionKeyCounter : KeyCounter.InputTrigger, IKeyBindingHandler { public OsuAction Action { get; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 60ebce4f52..f652a62489 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboard(key))); }); - Key testKey = ((KeyCounterKeyboard)kc.Children.First().CounterTrigger).Key; + Key testKey = ((KeyCounterKeyboard)kc.Children.First().Trigger).Key; void addPressKeyStep() { diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 0fa1f0b332..22dc6567eb 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -176,14 +176,14 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.CounterTrigger is KeyCounterAction) - .Select(c => (KeyCounterAction)c.CounterTrigger) + public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.Trigger is KeyCounterAction) + .Select(c => (KeyCounterAction)c.Trigger) .Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); public void OnReleased(KeyBindingReleaseEvent e) { foreach (var c - in Target.Children.Where(c => c.CounterTrigger is KeyCounterAction).Select(c => (KeyCounterAction)c.CounterTrigger)) + in Target.Children.Where(c => c.Trigger is KeyCounterAction).Select(c => (KeyCounterAction)c.Trigger)) c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/DefaultKeyCounter.cs index dcb425ae1d..93dc4abcb5 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounter.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounter.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play public Color4 KeyUpTextColor { get; set; } = Color4.White; public double FadeTime { get; set; } - public DefaultKeyCounter(Trigger trigger) + public DefaultKeyCounter(InputTrigger trigger) : base(trigger) { } diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index b111305b22..a1950a49f4 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -10,7 +10,7 @@ namespace osu.Game.Screens.Play { public abstract partial class KeyCounter : Container { - public readonly Trigger CounterTrigger; + public readonly InputTrigger Trigger; protected Bindable IsCountingBindable = new BindableBool(true); @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Play private set => PressesCount.Value = value; } - protected KeyCounter(Trigger trigger) + protected KeyCounter(InputTrigger trigger) { InternalChildren = new Drawable[] { @@ -43,10 +43,10 @@ namespace osu.Game.Screens.Play { RelativeSizeAxes = Axes.Both }, - CounterTrigger = trigger, + Trigger = trigger, }; - CounterTrigger.Target = this; + Trigger.Target = this; Name = trigger.Name; } @@ -68,9 +68,9 @@ namespace osu.Game.Screens.Play CountPresses--; } - protected override bool Handle(UIEvent e) => CounterTrigger.TriggerEvent(e); + protected override bool Handle(UIEvent e) => Trigger.TriggerEvent(e); - public abstract partial class Trigger : Component + public abstract partial class InputTrigger : Component { private KeyCounter? target; @@ -79,7 +79,7 @@ namespace osu.Game.Screens.Play set => target = value; } - protected Trigger(string name) + protected InputTrigger(string name) { Name = name; } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 058dbb1480..4926970960 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public partial class KeyCounterAction : KeyCounter.Trigger + public partial class KeyCounterAction : KeyCounter.InputTrigger where T : struct { public T Action { get; } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index b06d1adfa0..fc6fa12f10 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Play this.receptor = receptor; } - public virtual KeyCounter CreateKeyCounter(KeyCounter.Trigger trigger) => new DefaultKeyCounter(trigger); + public virtual KeyCounter CreateKeyCounter(KeyCounter.InputTrigger trigger) => new DefaultKeyCounter(trigger); public partial class Receptor : Drawable { diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 4306efd360..6ae1a2c5bc 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public partial class KeyCounterKeyboard : KeyCounter.Trigger + public partial class KeyCounterKeyboard : KeyCounter.InputTrigger { public Key Key { get; } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 00fca47ba2..40674cdbcd 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public partial class KeyCounterMouse : KeyCounter.Trigger + public partial class KeyCounterMouse : KeyCounter.InputTrigger { public MouseButton Button { get; } From df0633858cb9aa0734a95e5f67fc284313571485 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 23:20:23 +0000 Subject: [PATCH 0103/1400] fix(KeyCounter): don't override Handle This caused the Keyboard inputs to register twice, which is not what we want. --- osu.Game/Screens/Play/KeyCounter.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index a1950a49f4..cd306dfb9b 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -4,7 +4,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Events; namespace osu.Game.Screens.Play { @@ -68,8 +67,6 @@ namespace osu.Game.Screens.Play CountPresses--; } - protected override bool Handle(UIEvent e) => Trigger.TriggerEvent(e); - public abstract partial class InputTrigger : Component { private KeyCounter? target; From a644fae3649f29eacf612b2bd920fc4ad0a8ec48 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 23:22:50 +0000 Subject: [PATCH 0104/1400] style(KeyCounter): rename `(Un)lit` methods to `(Un)light` --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 4 ++-- osu.Game/Screens/Play/KeyCounter.cs | 4 ++-- osu.Game/Screens/Play/KeyCounterAction.cs | 4 ++-- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 6 ++++-- osu.Game/Screens/Play/KeyCounterMouse.cs | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 1a273153bd..6068cf50b6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -593,7 +593,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (e.Action == Action) { - Lit(); + Light(); } return false; @@ -602,7 +602,7 @@ namespace osu.Game.Rulesets.Osu.Tests public void OnReleased(KeyBindingReleaseEvent e) { if (e.Action == Action) - Unlit(); + Unlight(); } } diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index cd306dfb9b..4a7203870c 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Play Name = name; } - protected void Lit(bool increment = true) + protected void Light(bool increment = true) { if (target == null) return; @@ -90,7 +90,7 @@ namespace osu.Game.Screens.Play target.Increment(); } - protected void Unlit(bool preserve = true) + protected void Unlight(bool preserve = true) { if (target == null) return; diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 4926970960..65a0bc2ca7 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return false; - Lit(forwards); + Light(forwards); return false; } @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return; - Unlit(forwards); + Unlight(forwards); } } } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 6ae1a2c5bc..ef1f207556 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -21,7 +21,9 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { if (e.Key == Key) - Lit(); + { + Light(); + } return base.OnKeyDown(e); } @@ -29,7 +31,7 @@ namespace osu.Game.Screens.Play protected override void OnKeyUp(KeyUpEvent e) { if (e.Key == Key) - Unlit(); + Unlight(); base.OnKeyUp(e); } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 40674cdbcd..cf0e0a394f 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == Button) - Lit(); + Light(); return base.OnMouseDown(e); } @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Play protected override void OnMouseUp(MouseUpEvent e) { if (e.Button == Button) - Unlit(); + Unlight(); base.OnMouseUp(e); } From 076eb81b212caaa61546ad3d3d0605b5e072eb46 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 13 Feb 2023 23:49:57 +0000 Subject: [PATCH 0105/1400] refactor: rename trigger classes Makes it better to understand their purpose --- .../TestSceneOsuTouchInput.cs | 8 ++++---- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../Visual/Gameplay/TestSceneKeyCounter.cs | 12 ++++++------ .../Gameplay/TestSceneSkinEditorMultipleSkins.cs | 2 +- .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 8 ++++---- ...eyCounterAction.cs => KeyCounterActionTrigger.cs} | 4 ++-- ...unterKeyboard.cs => KeyCounterKeyboardTrigger.cs} | 4 ++-- ...{KeyCounterMouse.cs => KeyCounterMouseTrigger.cs} | 4 ++-- 9 files changed, 23 insertions(+), 23 deletions(-) rename osu.Game/Screens/Play/{KeyCounterAction.cs => KeyCounterActionTrigger.cs} (86%) rename osu.Game/Screens/Play/{KeyCounterKeyboard.cs => KeyCounterKeyboardTrigger.cs} (85%) rename osu.Game/Screens/Play/{KeyCounterMouse.cs => KeyCounterMouseTrigger.cs} (90%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 6068cf50b6..950e034d8f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -59,14 +59,14 @@ namespace osu.Game.Rulesets.Osu.Tests Origin = Anchor.Centre, Children = new Drawable[] { - leftKeyCounter = new DefaultKeyCounter(new TestActionKeyCounter(OsuAction.LeftButton)) + leftKeyCounter = new DefaultKeyCounter(new TestActionKeyCounterTrigger(OsuAction.LeftButton)) { Anchor = Anchor.Centre, Origin = Anchor.CentreRight, Depth = float.MinValue, X = -100, }, - rightKeyCounter = new DefaultKeyCounter(new TestActionKeyCounter(OsuAction.RightButton)) + rightKeyCounter = new DefaultKeyCounter(new TestActionKeyCounterTrigger(OsuAction.RightButton)) { Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, @@ -579,11 +579,11 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkNotPressed(OsuAction action) => AddAssert($"Not pressing {action}", () => !osuInputManager.PressedActions.Contains(action)); private void checkPressed(OsuAction action) => AddAssert($"Is pressing {action}", () => osuInputManager.PressedActions.Contains(action)); - public partial class TestActionKeyCounter : KeyCounter.InputTrigger, IKeyBindingHandler + public partial class TestActionKeyCounterTrigger : KeyCounter.InputTrigger, IKeyBindingHandler { public OsuAction Action { get; } - public TestActionKeyCounter(OsuAction action) + public TestActionKeyCounterTrigger(OsuAction action) : base(action.ToString()) { Action = action; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 4055ef9d3a..af79650d29 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); scoreProcessor.Combo.Value = 1; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index f652a62489..975a5c9465 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -25,20 +25,20 @@ namespace osu.Game.Tests.Visual.Gameplay Anchor = Anchor.Centre, Children = new[] { - testCounter = new DefaultKeyCounter(new KeyCounterKeyboard(Key.X)), - new DefaultKeyCounter(new KeyCounterKeyboard(Key.X)), - new DefaultKeyCounter(new KeyCounterMouse(MouseButton.Left)), - new DefaultKeyCounter(new KeyCounterMouse(MouseButton.Right)), + testCounter = new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Left)), + new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Right)), }, }; AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); - kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboard(key))); + kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboardTrigger(key))); }); - Key testKey = ((KeyCounterKeyboard)kc.Children.First().Trigger).Key; + Key testKey = ((KeyCounterKeyboardTrigger)kc.Children.First().Trigger).Key; void addPressKeyStep() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 56cf56efd9..432ff2fc7e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); scoreProcessor.Combo.Value = 1; return new Container diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index f713bca081..24de29fa03 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboard(Key.Space))); + hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); action?.Invoke(hudOverlay); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 22dc6567eb..6a38fa4824 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.UI .Select(b => b.GetAction()) .Distinct() .OrderBy(action => action) - .Select(action => keyCounter.CreateKeyCounter(new KeyCounterAction(action)))); + .Select(action => keyCounter.CreateKeyCounter(new KeyCounterActionTrigger(action)))); } private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler @@ -176,14 +176,14 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.Trigger is KeyCounterAction) - .Select(c => (KeyCounterAction)c.Trigger) + public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.Trigger is KeyCounterActionTrigger) + .Select(c => (KeyCounterActionTrigger)c.Trigger) .Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); public void OnReleased(KeyBindingReleaseEvent e) { foreach (var c - in Target.Children.Where(c => c.Trigger is KeyCounterAction).Select(c => (KeyCounterAction)c.Trigger)) + in Target.Children.Where(c => c.Trigger is KeyCounterActionTrigger).Select(c => (KeyCounterActionTrigger)c.Trigger)) c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs similarity index 86% rename from osu.Game/Screens/Play/KeyCounterAction.cs rename to osu.Game/Screens/Play/KeyCounterActionTrigger.cs index 65a0bc2ca7..51b82ac5e5 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs @@ -7,12 +7,12 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public partial class KeyCounterAction : KeyCounter.InputTrigger + public partial class KeyCounterActionTrigger : KeyCounter.InputTrigger where T : struct { public T Action { get; } - public KeyCounterAction(T action) + public KeyCounterActionTrigger(T action) : base($"B{(int)(object)action + 1}") { Action = action; diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs similarity index 85% rename from osu.Game/Screens/Play/KeyCounterKeyboard.cs rename to osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs index ef1f207556..fee716abf4 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs @@ -8,11 +8,11 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public partial class KeyCounterKeyboard : KeyCounter.InputTrigger + public partial class KeyCounterKeyboardTrigger : KeyCounter.InputTrigger { public Key Key { get; } - public KeyCounterKeyboard(Key key) + public KeyCounterKeyboardTrigger(Key key) : base(key.ToString()) { Key = key; diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs similarity index 90% rename from osu.Game/Screens/Play/KeyCounterMouse.cs rename to osu.Game/Screens/Play/KeyCounterMouseTrigger.cs index cf0e0a394f..a693db9b19 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs @@ -9,11 +9,11 @@ using osuTK; namespace osu.Game.Screens.Play { - public partial class KeyCounterMouse : KeyCounter.InputTrigger + public partial class KeyCounterMouseTrigger : KeyCounter.InputTrigger { public MouseButton Button { get; } - public KeyCounterMouse(MouseButton button) + public KeyCounterMouseTrigger(MouseButton button) : base(getStringRepresentation(button)) { Button = button; From b0a2e69f951910907559d16fc2392a4d9867cd99 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 15 Feb 2023 22:06:10 +0000 Subject: [PATCH 0106/1400] style: nullable pass on `KeyCounterDisplay` --- osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs | 11 +++++------ osu.Game/Screens/Play/KeyCounterDisplay.cs | 6 ++---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs index d643070e06..332474a517 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -24,12 +24,11 @@ namespace osu.Game.Screens.Play public DefaultKeyCounterDisplay() { - InternalChild = KeyFlow = new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Alpha = 0, - }; + KeyFlow.Direction = FillDirection.Horizontal; + KeyFlow.AutoSizeAxes = Axes.Both; + KeyFlow.Alpha = 0; + + InternalChild = KeyFlow; } protected override void Update() diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index fc6fa12f10..f5af67caea 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.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. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -19,7 +17,7 @@ namespace osu.Game.Screens.Play { protected readonly Bindable ConfigVisibility = new Bindable(); - protected FillFlowContainer KeyFlow; + protected FillFlowContainer KeyFlow = new FillFlowContainer(); protected override Container Content => KeyFlow; @@ -71,7 +69,7 @@ namespace osu.Game.Screens.Play public override bool HandleNonPositionalInput => receptor == null; public override bool HandlePositionalInput => receptor == null; - private Receptor receptor; + private Receptor? receptor; public void SetReceptor(Receptor receptor) { From e9dcc257b48ae26302c598df7d433e09007a40ba Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 15 Feb 2023 22:06:35 +0000 Subject: [PATCH 0107/1400] reafactor: simplify type checking --- osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs | 6 +++--- osu.Game/Screens/Play/KeyCounterDisplay.cs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs index 332474a517..b69ecfd7ae 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -43,14 +42,15 @@ namespace osu.Game.Screens.Play public override void Add(KeyCounter key) { base.Add(key); - if (key is not DefaultKeyCounter defaultKey) - throw new ArgumentException($"{key.GetType()} is not a supported {nameof(KeyCounter)}.", nameof(key)); + DefaultKeyCounter defaultKey = (DefaultKeyCounter)key; defaultKey.FadeTime = key_fade_time; defaultKey.KeyDownTextColor = KeyDownTextColor; defaultKey.KeyUpTextColor = KeyUpTextColor; } + protected override bool CheckType(KeyCounter key) => key is DefaultKeyCounter; + protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index f5af67caea..ed47af11a3 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -29,12 +29,15 @@ namespace osu.Game.Screens.Play public override void Add(KeyCounter key) { - ArgumentNullException.ThrowIfNull(key); + if (!CheckType(key)) + throw new ArgumentException($"{key.GetType()} is not a supported {nameof(KeyCounter)}.", nameof(key)); base.Add(key); key.IsCounting = IsCounting; } + protected virtual bool CheckType(KeyCounter key) => true; + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 74e7cc205601bc4edb9d88e12afb8c63f8e967d2 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 15 Feb 2023 22:18:02 +0000 Subject: [PATCH 0108/1400] feat: implement new design of key counter --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 39 +++++++--- osu.Game/Screens/Play/ArgonKeyCounter.cs | 76 +++++++++++++++++++ .../Screens/Play/ArgonKeyCounterDisplay.cs | 42 ++++++++++ 3 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 osu.Game/Screens/Play/ArgonKeyCounter.cs create mode 100644 osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 975a5c9465..41add82245 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; using osu.Game.Screens.Play; +using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -18,24 +19,44 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneKeyCounter() { DefaultKeyCounter testCounter; + KeyCounterDisplay kc; + KeyCounterDisplay argonKc; - KeyCounterDisplay kc = new DefaultKeyCounterDisplay + Children = new Drawable[] { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Children = new[] + kc = new DefaultKeyCounterDisplay { - testCounter = new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), - new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), - new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Left)), - new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Right)), + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Position = new Vector2(0, -50), + Children = new[] + { + testCounter = new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Left)), + new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Right)), + }, }, + argonKc = new ArgonKeyCounterDisplay + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Position = new Vector2(0, 50), + Children = new[] + { + new ArgonKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new ArgonKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), + new ArgonKeyCounter(new KeyCounterMouseTrigger(MouseButton.Left)), + new ArgonKeyCounter(new KeyCounterMouseTrigger(MouseButton.Right)), + }, + } }; AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboardTrigger(key))); + argonKc.Add(argonKc.CreateKeyCounter(new KeyCounterKeyboardTrigger(key))); }); Key testKey = ((KeyCounterKeyboardTrigger)kc.Children.First().Trigger).Key; @@ -52,8 +73,6 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Disable counting", () => testCounter.IsCounting = false); addPressKeyStep(); AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses == 2); - - Add(kc); } } } diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs new file mode 100644 index 0000000000..a275a7e017 --- /dev/null +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -0,0 +1,76 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osuTK; + +namespace osu.Game.Screens.Play +{ + public partial class ArgonKeyCounter : KeyCounter + { + private Circle inputIndicator = null!; + private OsuSpriteText countText = null!; + + // These values were taken from Figma + private const float line_height = 3; + private const float name_font_size = 10; + private const float count_font_size = 14; + + // Make things look bigger without using Scale + private const float scale_factor = 1.5f; + + public ArgonKeyCounter(InputTrigger trigger) + : base(trigger) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + inputIndicator = new Circle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = line_height * scale_factor, + Alpha = 0.5f + }, + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(0, -13) * scale_factor, + Font = OsuFont.Torus.With(size: name_font_size * scale_factor, weight: FontWeight.Bold), + Colour = colours.Blue0, + Text = Name + }, + countText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.Torus.With(size: count_font_size * scale_factor, weight: FontWeight.Bold), + Text = "0" + }, + }; + + // Values from Figma didn't match visually + // So these were just eyeballed + Height = 30 * scale_factor; + Width = 35 * scale_factor; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + IsLit.BindValueChanged(e => inputIndicator.Alpha = e.NewValue ? 1 : 0.5f, true); + PressesCount.BindValueChanged(e => countText.Text = e.NewValue.ToString(@"#,0"), true); + } + } +} diff --git a/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs b/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs new file mode 100644 index 0000000000..da34a64a4c --- /dev/null +++ b/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs @@ -0,0 +1,42 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; + +namespace osu.Game.Screens.Play +{ + public partial class ArgonKeyCounterDisplay : KeyCounterDisplay + { + private const int duration = 100; + + public new IReadOnlyList Children + { + get => (IReadOnlyList)base.Children; + set => base.Children = value; + } + + [BackgroundDependencyLoader] + private void load() + { + KeyFlow.Direction = FillDirection.Horizontal; + KeyFlow.AutoSizeAxes = Axes.Both; + KeyFlow.Spacing = new Vector2(2); + + InternalChildren = new[] + { + KeyFlow + }; + } + + protected override bool CheckType(KeyCounter key) => key is ArgonKeyCounter; + + protected override void UpdateVisibility() + => KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); + + public override KeyCounter CreateKeyCounter(KeyCounter.InputTrigger trigger) => new ArgonKeyCounter(trigger); + } +} From d5bc8e2941fc0a6d948fda24546cc976b12165fa Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Thu, 16 Feb 2023 11:12:30 +0100 Subject: [PATCH 0109/1400] Code cleanup pass: Make bubble transform logic more sane. Extract bubble `getPosition()` method. Address poorly named variables. --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 47 +++++++++++---------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 4edf726f26..0fc27c8f1d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Mods private readonly Bindable currentCombo = new BindableInt(); private float maxSize; - private float bubbleRadius; + private float bubbleSize; private double bubbleFade; private readonly DrawablePool bubblePool = new DrawablePool(100); @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Mods { // Multiplying by 2 results in an initial size that is too large, hence 1.90 has been chosen // Also avoids the HitObject bleeding around the edges of the bubble drawable at minimum size - bubbleRadius = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.90f); + bubbleSize = (float)(drawableRuleset.Beatmap.HitObjects.OfType().First().Radius * 1.90f); bubbleFade = drawableRuleset.Beatmap.HitObjects.OfType().First().TimePreempt * 2; // We want to hide the judgements since they are obscured by the BubbleDrawable (due to layering) @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Mods BubbleDrawable bubble = bubblePool.Get(); bubble.DrawableOsuHitObject = drawableOsuHitObject; - bubble.InitialSize = new Vector2(bubbleRadius); + bubble.InitialSize = new Vector2(bubbleSize); bubble.FadeTime = bubbleFade; bubble.MaxSize = maxSize; @@ -122,9 +122,11 @@ namespace osu.Game.Rulesets.Osu.Mods public DrawableOsuHitObject? DrawableOsuHitObject { get; set; } public Vector2 InitialSize { get; set; } - public double FadeTime { get; set; } + public float MaxSize { get; set; } + public double FadeTime { get; set; } + private readonly Box colourBox; private readonly CircularContainer content; @@ -155,12 +157,9 @@ namespace osu.Game.Rulesets.Osu.Mods Debug.Assert(DrawableOsuHitObject.IsNotNull()); Colour = DrawableOsuHitObject.IsHit ? Colour4.White : Colour4.Black; - Alpha = 1; Scale = new Vector2(1); - Position = getPosition(); + Position = getPosition(DrawableOsuHitObject); Size = InitialSize; - content.BorderThickness = InitialSize.X / 3.5f; - content.BorderColour = Colour4.White; //We want to fade to a darker colour to avoid colours such as white hiding the "ripple" effect. ColourInfo colourDarker = DrawableOsuHitObject.AccentColour.Value.Darken(0.1f); @@ -169,7 +168,8 @@ namespace osu.Game.Rulesets.Osu.Mods double getAnimationDuration = 1700 + Math.Pow(FadeTime, 1.07f); // Main bubble scaling based on combo - this.ScaleTo(MaxSize, getAnimationDuration * 0.8f) + this.FadeTo(1) + .ScaleTo(MaxSize, getAnimationDuration * 0.8f) .Then() // Pop at the end of the bubbles life time .ScaleTo(MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) @@ -177,6 +177,9 @@ namespace osu.Game.Rulesets.Osu.Mods if (!DrawableOsuHitObject.IsHit) return; + content.BorderThickness = InitialSize.X / 3.5f; + content.BorderColour = Colour4.White; + colourBox.FadeColour(colourDarker); content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration * 0.3f, Easing.OutQuint); @@ -184,23 +187,23 @@ namespace osu.Game.Rulesets.Osu.Mods content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) // Avoids transparency overlap issues during the bubble "pop" .Then().Schedule(() => content.BorderThickness = 0); + } - Vector2 getPosition() + private Vector2 getPosition(DrawableOsuHitObject drawableOsuHitObject) + { + switch (drawableOsuHitObject) { - switch (DrawableOsuHitObject) - { - // SliderHeads are derived from HitCircles, - // so we must handle them before to avoid them using the wrong positioning logic - case DrawableSliderHead: - return DrawableOsuHitObject.HitObject.Position; + // SliderHeads are derived from HitCircles, + // so we must handle them before to avoid them using the wrong positioning logic + case DrawableSliderHead: + return drawableOsuHitObject.HitObject.Position; - // Using hitobject position will cause issues with HitCircle placement due to stack leniency. - case DrawableHitCircle: - return DrawableOsuHitObject.Position; + // Using hitobject position will cause issues with HitCircle placement due to stack leniency. + case DrawableHitCircle: + return drawableOsuHitObject.Position; - default: - return DrawableOsuHitObject.HitObject.Position; - } + default: + return drawableOsuHitObject.HitObject.Position; } } } From f1da213beaaaba85b82c785def1c43f6cb1f62ec Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 16 Feb 2023 16:26:57 +0300 Subject: [PATCH 0110/1400] Add tests --- osu.Game.Tests/Database/LegacyExporterTest.cs | 85 +++++++++++++++++++ osu.Game/Database/LegacyExporter.cs | 6 +- 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tests/Database/LegacyExporterTest.cs diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs new file mode 100644 index 0000000000..5f07e6c917 --- /dev/null +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -0,0 +1,85 @@ +// 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 System.Diagnostics; +using System.IO; +using System.Text; +using NUnit.Framework; +using osu.Framework.Platform; +using osu.Framework.Testing; +using osu.Game.Database; + +namespace osu.Game.Tests.Database +{ + public class LegacyExporterTest + { + private TestLegacyExporter? legacyExporter; + private TemporaryNativeStorage? storage; + + [SetUp] + public void SetupLegacyExporter() + { + storage = new TemporaryNativeStorage("export-storage"); + legacyExporter = new TestLegacyExporter(storage); + } + + [Test] + public void ExportFileWithNormalName() + { + var exportStorage = storage?.GetStorageForDirectory(@"exports"); + + string filename = "normal file name"; + var item = new TestPathInfo(filename); + + Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); + Assert.DoesNotThrow(() => legacyExporter?.Export(item)); + Assert.That(exportStorage?.Exists($"{filename}{legacyExporter?.GetExtension()}"), Is.True); + } + + [Test] + public void ExportFileWithSuperLongName() + { + var exportStorage = storage?.GetStorageForDirectory(@"exports"); + + string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + + int capacity = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); + string expectedName = fullname.Remove(capacity); + + var item = new TestPathInfo(fullname); + + Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); + Assert.DoesNotThrow(() => legacyExporter?.Export(item)); + Assert.That(exportStorage?.Exists($"{expectedName}{legacyExporter?.GetExtension()}"), Is.True); + } + + [TearDown] + public void CleanupAfterTest() + { + storage?.Dispose(); + } + + private class TestPathInfo : IHasNamedFiles + { + public string FileName { get; set; } = string.Empty; + + public TestPathInfo(string fileName) => FileName = fileName; + + public IEnumerable Files { get; set; } = new List(); + + public override string ToString() => FileName; + } + + private class TestLegacyExporter : LegacyExporter + { + public TestLegacyExporter(Storage storage) : base(storage) { } + + public static int GetMaxPath() => MAX_PATH; + + public string GetExtension() => FileExtension; + + protected override string FileExtension => ".ots"; + } + } +} diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 483c3cbd5c..9041f58368 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Database /// /// This constant is smaller 256 because adds additional "_" to the end of the path /// - private const int max_path = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) + protected const int MAX_PATH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) /// /// The file extension for exports (including the leading '.'). @@ -60,11 +60,11 @@ namespace osu.Game.Database string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - if (filename.Length > max_path) + if (filename.Length > MAX_PATH) { string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - filenameWithoutExtension = filenameWithoutExtension.Remove(max_path - FileExtension.Length); //Truncating the name to fit the path limit + filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_PATH - FileExtension.Length); //Truncating the name to fit the path limit filename = $"{filenameWithoutExtension}{FileExtension}"; } From 6819a45a1bdba3fdd2b28a6d7983b73116ddbded Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 16 Feb 2023 16:42:07 +0300 Subject: [PATCH 0111/1400] Improve code slightly --- osu.Game.Tests/Database/LegacyExporterTest.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 5f07e6c917..c464eb5c28 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -2,9 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; using NUnit.Framework; using osu.Framework.Platform; using osu.Framework.Testing; @@ -29,7 +26,7 @@ namespace osu.Game.Tests.Database { var exportStorage = storage?.GetStorageForDirectory(@"exports"); - string filename = "normal file name"; + const string filename = "normal file name"; var item = new TestPathInfo(filename); Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); @@ -42,7 +39,7 @@ namespace osu.Game.Tests.Database { var exportStorage = storage?.GetStorageForDirectory(@"exports"); - string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; int capacity = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); string expectedName = fullname.Remove(capacity); @@ -62,7 +59,7 @@ namespace osu.Game.Tests.Database private class TestPathInfo : IHasNamedFiles { - public string FileName { get; set; } = string.Empty; + public string FileName { get; set; } public TestPathInfo(string fileName) => FileName = fileName; @@ -73,7 +70,10 @@ namespace osu.Game.Tests.Database private class TestLegacyExporter : LegacyExporter { - public TestLegacyExporter(Storage storage) : base(storage) { } + public TestLegacyExporter(Storage storage) + : base(storage) + { + } public static int GetMaxPath() => MAX_PATH; From 6340730427908b839aaa3d00c82497818cec93e1 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 16 Feb 2023 21:59:39 +0000 Subject: [PATCH 0112/1400] refactor(KeyCounter): remove circularity --- .../TestSceneOsuTouchInput.cs | 2 +- osu.Game/Screens/Play/KeyCounter.cs | 52 +++++++++++-------- .../Screens/Play/KeyCounterActionTrigger.cs | 2 +- .../Screens/Play/KeyCounterKeyboardTrigger.cs | 2 +- .../Screens/Play/KeyCounterMouseTrigger.cs | 2 +- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 950e034d8f..c73025ebb9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -593,7 +593,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (e.Action == Action) { - Light(); + LightUp(); } return false; diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 4a7203870c..3748792383 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.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 System; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -45,7 +46,9 @@ namespace osu.Game.Screens.Play Trigger = trigger, }; - Trigger.Target = this; + Trigger.OnLightUp += LightUp; + Trigger.OnUnlight += Unlight; + Name = trigger.Name; } @@ -67,37 +70,40 @@ namespace osu.Game.Screens.Play CountPresses--; } + protected virtual void LightUp(bool increment = true) + { + IsLit.Value = true; + if (increment) + Increment(); + } + + protected virtual void Unlight(bool preserve = true) + { + IsLit.Value = false; + if (!preserve) + Decrement(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + Trigger.OnLightUp -= LightUp; + Trigger.OnUnlight -= Unlight; + } + public abstract partial class InputTrigger : Component { - private KeyCounter? target; - - public KeyCounter Target - { - set => target = value; - } + public event Action? OnLightUp; + public event Action? OnUnlight; protected InputTrigger(string name) { Name = name; } - protected void Light(bool increment = true) - { - if (target == null) return; + protected void LightUp(bool increment = true) => OnLightUp?.Invoke(increment); - target.IsLit.Value = true; - if (increment) - target.Increment(); - } - - protected void Unlight(bool preserve = true) - { - if (target == null) return; - - target.IsLit.Value = false; - if (!preserve) - target.Decrement(); - } + protected void Unlight(bool preserve = true) => OnUnlight?.Invoke(preserve); } } } diff --git a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs index 51b82ac5e5..c6acb3f95f 100644 --- a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return false; - Light(forwards); + LightUp(forwards); return false; } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs index fee716abf4..18eb6b7612 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Play { if (e.Key == Key) { - Light(); + LightUp(); } return base.OnKeyDown(e); diff --git a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs index a693db9b19..1446494b5b 100644 --- a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == Button) - Light(); + LightUp(); return base.OnMouseDown(e); } From ddd6c1a1c671c24f33479eceff34f7acf05b5cc7 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 16 Feb 2023 22:20:34 +0000 Subject: [PATCH 0113/1400] refactor(KeyCounter): address bindables issues `IsCounting` is back being an auto-property. `countPresses` is now encapsulated and being exposed as an `IBindable` via `CountPresses` --- .../Visual/Gameplay/TestSceneAutoplay.cs | 4 ++-- .../Gameplay/TestSceneGameplayRewinding.cs | 4 ++-- .../Visual/Gameplay/TestSceneKeyCounter.cs | 6 +++--- .../Visual/Gameplay/TestSceneReplay.cs | 2 +- .../TestSceneChangeAndUseGameplayBindings.cs | 4 ++-- osu.Game/Screens/Play/DefaultKeyCounter.cs | 4 ++-- osu.Game/Screens/Play/KeyCounter.cs | 20 +++++-------------- 7 files changed, 17 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 5442b3bfef..4b6e1f089f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -35,14 +35,14 @@ namespace osu.Game.Tests.Visual.Gameplay var referenceBeatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2)); + AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 2)); seekTo(referenceBeatmap.Breaks[0].StartTime); AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting); AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType().Single().AccuracyDisplay.Current.Value == 1); AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000)); - AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses.Value == 0)); seekTo(referenceBeatmap.HitObjects[^1].GetEndTime()); AddUntilStep("results displayed", () => getResultsScreen()?.IsLoaded == true); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 1dffeed01b..9f485cd7bf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -31,11 +31,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); - AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Select(kc => kc.CountPresses).Sum() == 15); + AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Select(kc => kc.CountPresses.Value).Sum() == 15); AddStep("clear results", () => Player.Results.Clear()); addSeekStep(0); AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged)); - AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses.Value == 0)); AddAssert("no results triggered", () => Player.Results.Count == 0); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 975a5c9465..9eeee800d9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -46,12 +46,12 @@ namespace osu.Game.Tests.Visual.Gameplay } addPressKeyStep(); - AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1); addPressKeyStep(); - AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2); AddStep("Disable counting", () => testCounter.IsCounting = false); addPressKeyStep(); - AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses == 2); + AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2); Add(kc); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index c476aae202..542686f0cd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 0)); AddAssert("cannot fail", () => !((ScoreAccessibleReplayPlayer)Player).AllowFail); } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index d937b9e6d7..59a0f9cea8 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -69,10 +69,10 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for gameplay", () => player?.IsBreakTime.Value == false); AddStep("press 'z'", () => InputManager.Key(Key.Z)); - AddAssert("key counter didn't increase", () => keyCounter.CountPresses == 0); + AddAssert("key counter didn't increase", () => keyCounter.CountPresses.Value == 0); AddStep("press 's'", () => InputManager.Key(Key.S)); - AddAssert("key counter did increase", () => keyCounter.CountPresses == 1); + AddAssert("key counter did increase", () => keyCounter.CountPresses.Value == 1); } private KeyBindingsSubsection osuBindingSubsection => keyBindingPanel diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/DefaultKeyCounter.cs index 93dc4abcb5..52d54b9d4a 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounter.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounter.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.Play }, countSpriteText = new OsuSpriteText { - Text = CountPresses.ToString(@"#,0"), + Text = CountPresses.Value.ToString(@"#,0"), Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Play Width = buttonSprite.DrawWidth; IsLit.BindValueChanged(e => updateGlowSprite(e.NewValue), true); - PressesCount.BindValueChanged(e => countSpriteText.Text = e.NewValue.ToString(@"#,0"), true); + CountPresses.BindValueChanged(e => countSpriteText.Text = e.NewValue.ToString(@"#,0"), true); } private void updateGlowSprite(bool show) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 3748792383..23afa97597 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -12,28 +12,18 @@ namespace osu.Game.Screens.Play { public readonly InputTrigger Trigger; - protected Bindable IsCountingBindable = new BindableBool(true); - private readonly Container content; protected override Container Content => content; - protected Bindable PressesCount = new BindableInt + private readonly Bindable countPresses = new BindableInt { MinValue = 0 }; - public bool IsCounting - { - get => IsCountingBindable.Value; - set => IsCountingBindable.Value = value; - } + public bool IsCounting { get; set; } = true; - public int CountPresses - { - get => PressesCount.Value; - private set => PressesCount.Value = value; - } + public IBindable CountPresses => countPresses; protected KeyCounter(InputTrigger trigger) { @@ -59,7 +49,7 @@ namespace osu.Game.Screens.Play if (!IsCounting) return; - CountPresses++; + countPresses.Value++; } public void Decrement() @@ -67,7 +57,7 @@ namespace osu.Game.Screens.Play if (!IsCounting) return; - CountPresses--; + countPresses.Value--; } protected virtual void LightUp(bool increment = true) From 6cb00cd42f22b7324df66a2863a0fe333875d2f8 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 01:44:45 +0300 Subject: [PATCH 0114/1400] Add more test cases --- osu.Game.Tests/Database/LegacyExporterTest.cs | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index c464eb5c28..c67ec75e92 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Database } [Test] - public void ExportFileWithNormalName() + public void ExportFileWithNormalNameTest() { var exportStorage = storage?.GetStorageForDirectory(@"exports"); @@ -30,23 +30,65 @@ namespace osu.Game.Tests.Database var item = new TestPathInfo(filename); Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); - Assert.DoesNotThrow(() => legacyExporter?.Export(item)); - Assert.That(exportStorage?.Exists($"{filename}{legacyExporter?.GetExtension()}"), Is.True); + exportItemWithLongNameAndAssert(item, exportStorage, filename); } [Test] - public void ExportFileWithSuperLongName() + public void ExportFileWithNormalNameMultipleTimesTest() + { + var exportStorage = storage?.GetStorageForDirectory(@"exports"); + + const string filename = "normal file name"; + var item = new TestPathInfo(filename); + + Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); + + //Export multiple times + string expectedFileName; + for (int i = 0; i < 10; i++) + { + expectedFileName = i == 0 ? filename : $"{filename} ({i})"; + exportItemWithLongNameAndAssert(item, exportStorage, expectedFileName); + } + } + + [Test] + public void ExportFileWithSuperLongNameTest() { var exportStorage = storage?.GetStorageForDirectory(@"exports"); const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; - int capacity = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); - string expectedName = fullname.Remove(capacity); + int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); + string expectedName = fullname.Remove(expectedLength); var item = new TestPathInfo(fullname); Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); + exportItemWithLongNameAndAssert(item, exportStorage, expectedName); + } + + [Test] + public void ExportFileWithSuperLongNameMultipleTimesTest() + { + var exportStorage = storage?.GetStorageForDirectory(@"exports"); + + const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + + int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); + string expectedName = fullname.Remove(expectedLength); + + var item = new TestPathInfo(fullname); + + Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); + + //Export multiple times + for (int i = 0; i < 10; i++) + exportItemWithLongNameAndAssert(item, exportStorage, expectedName); + } + + private void exportItemWithLongNameAndAssert(IHasNamedFiles item, Storage? exportStorage, string expectedName) + { Assert.DoesNotThrow(() => legacyExporter?.Export(item)); Assert.That(exportStorage?.Exists($"{expectedName}{legacyExporter?.GetExtension()}"), Is.True); } From 1d8b348e4c72d29d44ce0f56d9d6e71f98000187 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 01:46:15 +0300 Subject: [PATCH 0115/1400] Improve naming --- osu.Game.Tests/Database/LegacyExporterTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index c67ec75e92..97b32b0c51 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Database var item = new TestPathInfo(filename); Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); - exportItemWithLongNameAndAssert(item, exportStorage, filename); + exportItemAndAssert(item, exportStorage, filename); } [Test] @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Database for (int i = 0; i < 10; i++) { expectedFileName = i == 0 ? filename : $"{filename} ({i})"; - exportItemWithLongNameAndAssert(item, exportStorage, expectedFileName); + exportItemAndAssert(item, exportStorage, expectedFileName); } } @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Database var item = new TestPathInfo(fullname); Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); - exportItemWithLongNameAndAssert(item, exportStorage, expectedName); + exportItemAndAssert(item, exportStorage, expectedName); } [Test] @@ -84,10 +84,10 @@ namespace osu.Game.Tests.Database //Export multiple times for (int i = 0; i < 10; i++) - exportItemWithLongNameAndAssert(item, exportStorage, expectedName); + exportItemAndAssert(item, exportStorage, expectedName); } - private void exportItemWithLongNameAndAssert(IHasNamedFiles item, Storage? exportStorage, string expectedName) + private void exportItemAndAssert(IHasNamedFiles item, Storage? exportStorage, string expectedName) { Assert.DoesNotThrow(() => legacyExporter?.Export(item)); Assert.That(exportStorage?.Exists($"{expectedName}{legacyExporter?.GetExtension()}"), Is.True); From f4038a49a17f8670f3b3ed8613e12d197d4e96b6 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 01:50:24 +0300 Subject: [PATCH 0116/1400] Fix inspectCode issues --- osu.Game.Tests/Database/LegacyExporterTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 97b32b0c51..d67cb8abf1 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -44,10 +44,9 @@ namespace osu.Game.Tests.Database Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); //Export multiple times - string expectedFileName; for (int i = 0; i < 10; i++) { - expectedFileName = i == 0 ? filename : $"{filename} ({i})"; + string expectedFileName = i == 0 ? filename : $"{filename} ({i})"; exportItemAndAssert(item, exportStorage, expectedFileName); } } From c61fac578ca53fa4dba22ac7ec85aa0cc335c762 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 16 Feb 2023 23:15:03 +0000 Subject: [PATCH 0117/1400] style(KeyCounter): rename methods and arguments As for the second suggestion in https://github.com/ppy/osu/pull/22654#discussion_r1109047998, I went with the first one as only one Trigger actually uses this argument for rewinding. --- .../TestSceneOsuTouchInput.cs | 4 ++-- osu.Game/Screens/Play/KeyCounter.cs | 20 +++++++++---------- .../Screens/Play/KeyCounterActionTrigger.cs | 4 ++-- .../Screens/Play/KeyCounterKeyboardTrigger.cs | 4 ++-- .../Screens/Play/KeyCounterMouseTrigger.cs | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index c73025ebb9..8a933c6b24 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -593,7 +593,7 @@ namespace osu.Game.Rulesets.Osu.Tests { if (e.Action == Action) { - LightUp(); + Activate(); } return false; @@ -602,7 +602,7 @@ namespace osu.Game.Rulesets.Osu.Tests public void OnReleased(KeyBindingReleaseEvent e) { if (e.Action == Action) - Unlight(); + Deactivate(); } } diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 23afa97597..a276c9d59e 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -36,8 +36,8 @@ namespace osu.Game.Screens.Play Trigger = trigger, }; - Trigger.OnLightUp += LightUp; - Trigger.OnUnlight += Unlight; + Trigger.OnActivate += Activate; + Trigger.OnDeactivate += Deactivate; Name = trigger.Name; } @@ -60,14 +60,14 @@ namespace osu.Game.Screens.Play countPresses.Value--; } - protected virtual void LightUp(bool increment = true) + protected virtual void Activate(bool increment = true) { IsLit.Value = true; if (increment) Increment(); } - protected virtual void Unlight(bool preserve = true) + protected virtual void Deactivate(bool preserve = true) { IsLit.Value = false; if (!preserve) @@ -77,23 +77,23 @@ namespace osu.Game.Screens.Play protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - Trigger.OnLightUp -= LightUp; - Trigger.OnUnlight -= Unlight; + Trigger.OnActivate -= Activate; + Trigger.OnDeactivate -= Deactivate; } public abstract partial class InputTrigger : Component { - public event Action? OnLightUp; - public event Action? OnUnlight; + public event Action? OnActivate; + public event Action? OnDeactivate; protected InputTrigger(string name) { Name = name; } - protected void LightUp(bool increment = true) => OnLightUp?.Invoke(increment); + protected void Activate(bool forwardPlayback = true) => OnActivate?.Invoke(forwardPlayback); - protected void Unlight(bool preserve = true) => OnUnlight?.Invoke(preserve); + protected void Deactivate(bool forwardPlayback = true) => OnDeactivate?.Invoke(forwardPlayback); } } } diff --git a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs index c6acb3f95f..8bb9bdc886 100644 --- a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return false; - LightUp(forwards); + Activate(forwards); return false; } @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play if (!EqualityComparer.Default.Equals(action, Action)) return; - Unlight(forwards); + Deactivate(forwards); } } } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs index 18eb6b7612..56c5ab0083 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Play { if (e.Key == Key) { - LightUp(); + Activate(); } return base.OnKeyDown(e); @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Play protected override void OnKeyUp(KeyUpEvent e) { if (e.Key == Key) - Unlight(); + Deactivate(); base.OnKeyUp(e); } diff --git a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs index 1446494b5b..66890073a8 100644 --- a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { if (e.Button == Button) - LightUp(); + Activate(); return base.OnMouseDown(e); } @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Play protected override void OnMouseUp(MouseUpEvent e) { if (e.Button == Button) - Unlight(); + Deactivate(); base.OnMouseUp(e); } From e3ca751027af079ac74e73ad7e88d59c8dc82d24 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 16 Feb 2023 23:17:47 +0000 Subject: [PATCH 0118/1400] refactor: make `FillFlowContainer` read-only --- osu.Game/Screens/Play/KeyCounterDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index ed47af11a3..0f2f8e43c9 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play { protected readonly Bindable ConfigVisibility = new Bindable(); - protected FillFlowContainer KeyFlow = new FillFlowContainer(); + protected readonly FillFlowContainer KeyFlow = new FillFlowContainer(); protected override Container Content => KeyFlow; From 6193aeed120f2bc85768a47efafa21b95695119e Mon Sep 17 00:00:00 2001 From: tsrk Date: Fri, 17 Feb 2023 00:13:45 +0000 Subject: [PATCH 0119/1400] fix(TestSceneOsuTouchInput): missing Value call --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 8a933c6b24..4cb017cc56 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -562,8 +562,8 @@ namespace osu.Game.Rulesets.Osu.Tests private void assertKeyCounter(int left, int right) { - AddAssert($"The left key was pressed {left} times", () => leftKeyCounter.CountPresses, () => Is.EqualTo(left)); - AddAssert($"The right key was pressed {right} times", () => rightKeyCounter.CountPresses, () => Is.EqualTo(right)); + AddAssert($"The left key was pressed {left} times", () => leftKeyCounter.CountPresses.Value, () => Is.EqualTo(left)); + AddAssert($"The right key was pressed {right} times", () => rightKeyCounter.CountPresses.Value, () => Is.EqualTo(right)); } private void releaseAllTouches() From d0e8d65766df488c98bf99ccdef7c05df3f694d8 Mon Sep 17 00:00:00 2001 From: tsrk Date: Fri, 17 Feb 2023 00:40:01 +0000 Subject: [PATCH 0120/1400] style(KeyCounter): rename `IsLit` to `IsActive` --- osu.Game/Screens/Play/DefaultKeyCounter.cs | 2 +- osu.Game/Screens/Play/KeyCounter.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/DefaultKeyCounter.cs index 52d54b9d4a..3673281577 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounter.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounter.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Play Height = buttonSprite.DrawHeight; Width = buttonSprite.DrawWidth; - IsLit.BindValueChanged(e => updateGlowSprite(e.NewValue), true); + IsActive.BindValueChanged(e => updateGlowSprite(e.NewValue), true); CountPresses.BindValueChanged(e => countSpriteText.Text = e.NewValue.ToString(@"#,0"), true); } diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index a276c9d59e..212843cbe9 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play Name = trigger.Name; } - protected Bindable IsLit = new BindableBool(); + protected Bindable IsActive = new BindableBool(); public void Increment() { @@ -62,14 +62,14 @@ namespace osu.Game.Screens.Play protected virtual void Activate(bool increment = true) { - IsLit.Value = true; + IsActive.Value = true; if (increment) Increment(); } protected virtual void Deactivate(bool preserve = true) { - IsLit.Value = false; + IsActive.Value = false; if (!preserve) Decrement(); } From 415220a44769fa8a7027ec8d56eb38b63fac6e04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:30:00 +0900 Subject: [PATCH 0121/1400] Tidy up new test method code quality --- osu.Game.Tests/Database/LegacyExporterTest.cs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index d67cb8abf1..803cd40132 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Database; @@ -11,11 +12,11 @@ namespace osu.Game.Tests.Database { public class LegacyExporterTest { - private TestLegacyExporter? legacyExporter; - private TemporaryNativeStorage? storage; + private TestLegacyExporter legacyExporter = null!; + private TemporaryNativeStorage storage = null!; [SetUp] - public void SetupLegacyExporter() + public void SetUp() { storage = new TemporaryNativeStorage("export-storage"); legacyExporter = new TestLegacyExporter(storage); @@ -24,24 +25,24 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameTest() { - var exportStorage = storage?.GetStorageForDirectory(@"exports"); + var exportStorage = storage.GetStorageForDirectory(@"exports"); const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPath(), Is.True); exportItemAndAssert(item, exportStorage, filename); } [Test] public void ExportFileWithNormalNameMultipleTimesTest() { - var exportStorage = storage?.GetStorageForDirectory(@"exports"); + var exportStorage = storage.GetStorageForDirectory(@"exports"); const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.FileName.Length < TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPath(), Is.True); //Export multiple times for (int i = 0; i < 10; i++) @@ -54,59 +55,65 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithSuperLongNameTest() { - var exportStorage = storage?.GetStorageForDirectory(@"exports"); + var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + const string fullname = + "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; - int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); + int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter.GetExtension().Length); string expectedName = fullname.Remove(expectedLength); var item = new TestPathInfo(fullname); - Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPath(), Is.True); exportItemAndAssert(item, exportStorage, expectedName); } [Test] public void ExportFileWithSuperLongNameMultipleTimesTest() { - var exportStorage = storage?.GetStorageForDirectory(@"exports"); + var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + const string fullname = + "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; - int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter?.GetExtension().Length ?? 0); + int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter.GetExtension().Length); string expectedName = fullname.Remove(expectedLength); var item = new TestPathInfo(fullname); - Assert.That(item.FileName.Length > TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPath(), Is.True); //Export multiple times for (int i = 0; i < 10; i++) exportItemAndAssert(item, exportStorage, expectedName); } - private void exportItemAndAssert(IHasNamedFiles item, Storage? exportStorage, string expectedName) + private void exportItemAndAssert(IHasNamedFiles item, Storage exportStorage, string expectedName) { - Assert.DoesNotThrow(() => legacyExporter?.Export(item)); - Assert.That(exportStorage?.Exists($"{expectedName}{legacyExporter?.GetExtension()}"), Is.True); + Assert.DoesNotThrow(() => legacyExporter.Export(item)); + Assert.That(exportStorage.Exists($"{expectedName}{legacyExporter.GetExtension()}"), Is.True); } [TearDown] - public void CleanupAfterTest() + public void TearDown() { - storage?.Dispose(); + if (storage.IsNotNull()) + storage.Dispose(); } private class TestPathInfo : IHasNamedFiles { - public string FileName { get; set; } + public string Filename { get; } - public TestPathInfo(string fileName) => FileName = fileName; + public IEnumerable Files { get; } = new List(); - public IEnumerable Files { get; set; } = new List(); + public TestPathInfo(string filename) + { + Filename = filename; + } - public override string ToString() => FileName; + public override string ToString() => Filename; } private class TestLegacyExporter : LegacyExporter From 96b1498932c4b93126a477cf1acc1b93d11c1b57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:33:22 +0900 Subject: [PATCH 0122/1400] Rename max length variable to make sense (it's a filename limit, not path) --- osu.Game.Tests/Database/LegacyExporterTest.cs | 14 +++++++------- osu.Game/Database/LegacyExporter.cs | 12 +++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 803cd40132..6f144ee833 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Database const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.GetMaxPathLength())); exportItemAndAssert(item, exportStorage, filename); } @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Database const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPathLength(), Is.True); //Export multiple times for (int i = 0; i < 10; i++) @@ -60,12 +60,12 @@ namespace osu.Game.Tests.Database const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; - int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter.GetExtension().Length); + int expectedLength = TestLegacyExporter.GetMaxPathLength() - (legacyExporter.GetExtension().Length); string expectedName = fullname.Remove(expectedLength); var item = new TestPathInfo(fullname); - Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPathLength(), Is.True); exportItemAndAssert(item, exportStorage, expectedName); } @@ -77,12 +77,12 @@ namespace osu.Game.Tests.Database const string fullname = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; - int expectedLength = TestLegacyExporter.GetMaxPath() - (legacyExporter.GetExtension().Length); + int expectedLength = TestLegacyExporter.GetMaxPathLength() - (legacyExporter.GetExtension().Length); string expectedName = fullname.Remove(expectedLength); var item = new TestPathInfo(fullname); - Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPath(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPathLength(), Is.True); //Export multiple times for (int i = 0; i < 10; i++) @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Database { } - public static int GetMaxPath() => MAX_PATH; + public static int GetMaxPathLength() => MAX_FILENAME_LENGTH; public string GetExtension() => FileExtension; diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 9041f58368..1b74454027 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -21,12 +21,14 @@ namespace osu.Game.Database where TModel : class, IHasNamedFiles { /// - /// Max length of filename (including extension) + /// Max length of filename (including extension). /// /// - /// This constant is smaller 256 because adds additional "_" to the end of the path + /// TODO: WHY? DOCUMENTATION PER PLATFORM LINKS HERE. + /// + /// This actual usable length is smaller 256 because adds additional "_" to the end of the path /// - protected const int MAX_PATH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) + protected const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) /// /// The file extension for exports (including the leading '.'). @@ -60,11 +62,11 @@ namespace osu.Game.Database string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - if (filename.Length > MAX_PATH) + if (filename.Length > MAX_FILENAME_LENGTH) { string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_PATH - FileExtension.Length); //Truncating the name to fit the path limit + filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); //Truncating the name to fit the path limit filename = $"{filenameWithoutExtension}{FileExtension}"; } From 8c772a723f0f8ae52cf3141fab286c64c2eba198 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:34:19 +0900 Subject: [PATCH 0123/1400] Expose constant `public`ly rather than reexposing business --- osu.Game/Database/LegacyExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 1b74454027..7434a46602 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -28,7 +28,7 @@ namespace osu.Game.Database /// /// This actual usable length is smaller 256 because adds additional "_" to the end of the path /// - protected const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) + public const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) /// /// The file extension for exports (including the leading '.'). From 99236f0ae80399d9fade78c7331dff63d59301e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:39:24 +0900 Subject: [PATCH 0124/1400] Move long filename to fixture level --- osu.Game.Tests/Database/LegacyExporterTest.cs | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 6f144ee833..114872bcf8 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -15,6 +15,9 @@ namespace osu.Game.Tests.Database private TestLegacyExporter legacyExporter = null!; private TemporaryNativeStorage storage = null!; + private const string long_filename = + "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + [SetUp] public void SetUp() { @@ -30,7 +33,7 @@ namespace osu.Game.Tests.Database const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.GetMaxPathLength())); + Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); exportItemAndAssert(item, exportStorage, filename); } @@ -42,7 +45,7 @@ namespace osu.Game.Tests.Database const string filename = "normal file name"; var item = new TestPathInfo(filename); - Assert.That(item.Filename.Length < TestLegacyExporter.GetMaxPathLength(), Is.True); + Assert.That(item.Filename.Length < TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); //Export multiple times for (int i = 0; i < 10; i++) @@ -57,15 +60,12 @@ namespace osu.Game.Tests.Database { var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string fullname = - "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); + string expectedName = long_filename.Remove(expectedLength); - int expectedLength = TestLegacyExporter.GetMaxPathLength() - (legacyExporter.GetExtension().Length); - string expectedName = fullname.Remove(expectedLength); + var item = new TestPathInfo(long_filename); - var item = new TestPathInfo(fullname); - - Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPathLength(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); exportItemAndAssert(item, exportStorage, expectedName); } @@ -74,15 +74,12 @@ namespace osu.Game.Tests.Database { var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string fullname = - "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; + int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); + string expectedName = long_filename.Remove(expectedLength); - int expectedLength = TestLegacyExporter.GetMaxPathLength() - (legacyExporter.GetExtension().Length); - string expectedName = fullname.Remove(expectedLength); + var item = new TestPathInfo(long_filename); - var item = new TestPathInfo(fullname); - - Assert.That(item.Filename.Length > TestLegacyExporter.GetMaxPathLength(), Is.True); + Assert.That(item.Filename.Length > TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); //Export multiple times for (int i = 0; i < 10; i++) @@ -123,8 +120,6 @@ namespace osu.Game.Tests.Database { } - public static int GetMaxPathLength() => MAX_FILENAME_LENGTH; - public string GetExtension() => FileExtension; protected override string FileExtension => ".ots"; From 4560ae6b026bd1ce575713ccab7d9052f73af40b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:39:31 +0900 Subject: [PATCH 0125/1400] Mark test as fixture --- osu.Game.Tests/Database/LegacyExporterTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 114872bcf8..ec20028a2c 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -10,6 +10,7 @@ using osu.Game.Database; namespace osu.Game.Tests.Database { + [TestFixture] public class LegacyExporterTest { private TestLegacyExporter legacyExporter = null!; From 86d110e893cd2572377c575fc67e5260a1199e27 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:43:42 +0900 Subject: [PATCH 0126/1400] Simplify test storage by removing nested storage --- osu.Game.Tests/Database/LegacyExporterTest.cs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index ec20028a2c..f38ffb7db6 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -29,20 +29,16 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameTest() { - var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string filename = "normal file name"; var item = new TestPathInfo(filename); Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); - exportItemAndAssert(item, exportStorage, filename); + exportItemAndAssert(item, filename); } [Test] public void ExportFileWithNormalNameMultipleTimesTest() { - var exportStorage = storage.GetStorageForDirectory(@"exports"); - const string filename = "normal file name"; var item = new TestPathInfo(filename); @@ -52,29 +48,25 @@ namespace osu.Game.Tests.Database for (int i = 0; i < 10; i++) { string expectedFileName = i == 0 ? filename : $"{filename} ({i})"; - exportItemAndAssert(item, exportStorage, expectedFileName); + exportItemAndAssert(item, expectedFileName); } } [Test] public void ExportFileWithSuperLongNameTest() { - var exportStorage = storage.GetStorageForDirectory(@"exports"); - int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); var item = new TestPathInfo(long_filename); Assert.That(item.Filename.Length > TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); - exportItemAndAssert(item, exportStorage, expectedName); + exportItemAndAssert(item, expectedName); } [Test] public void ExportFileWithSuperLongNameMultipleTimesTest() { - var exportStorage = storage.GetStorageForDirectory(@"exports"); - int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); @@ -84,13 +76,13 @@ namespace osu.Game.Tests.Database //Export multiple times for (int i = 0; i < 10; i++) - exportItemAndAssert(item, exportStorage, expectedName); + exportItemAndAssert(item, expectedName); } - private void exportItemAndAssert(IHasNamedFiles item, Storage exportStorage, string expectedName) + private void exportItemAndAssert(IHasNamedFiles item, string expectedName) { Assert.DoesNotThrow(() => legacyExporter.Export(item)); - Assert.That(exportStorage.Exists($"{expectedName}{legacyExporter.GetExtension()}"), Is.True); + Assert.That(storage.Exists($"exports/{expectedName}{legacyExporter.GetExtension()}"), Is.True); } [TearDown] From 8ef3fb26e056b2c271a690be5539983f6d9d09b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:45:27 +0900 Subject: [PATCH 0127/1400] More constants and assert fixes --- osu.Game.Tests/Database/LegacyExporterTest.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index f38ffb7db6..b8dca6dc7b 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -16,6 +16,8 @@ namespace osu.Game.Tests.Database private TestLegacyExporter legacyExporter = null!; private TemporaryNativeStorage storage = null!; + private const string short_filename = "normal file name"; + private const string long_filename = "some file with super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name super long name"; @@ -29,25 +31,24 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameTest() { - const string filename = "normal file name"; - var item = new TestPathInfo(filename); + var item = new TestPathInfo(short_filename); Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); - exportItemAndAssert(item, filename); + + exportItemAndAssert(item, short_filename); } [Test] public void ExportFileWithNormalNameMultipleTimesTest() { - const string filename = "normal file name"; - var item = new TestPathInfo(filename); + var item = new TestPathInfo(short_filename); - Assert.That(item.Filename.Length < TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); + Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); //Export multiple times for (int i = 0; i < 10; i++) { - string expectedFileName = i == 0 ? filename : $"{filename} ({i})"; + string expectedFileName = i == 0 ? short_filename : $"{short_filename} ({i})"; exportItemAndAssert(item, expectedFileName); } } @@ -60,7 +61,7 @@ namespace osu.Game.Tests.Database var item = new TestPathInfo(long_filename); - Assert.That(item.Filename.Length > TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); + Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); exportItemAndAssert(item, expectedName); } @@ -72,7 +73,7 @@ namespace osu.Game.Tests.Database var item = new TestPathInfo(long_filename); - Assert.That(item.Filename.Length > TestLegacyExporter.MAX_FILENAME_LENGTH, Is.True); + Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); //Export multiple times for (int i = 0; i < 10; i++) From 372b6b794cae69dc16a882f0caa3b91dcfef0491 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Feb 2023 13:45:43 +0900 Subject: [PATCH 0128/1400] I don't know what .ots is but let's not use random file extension that make no sense --- osu.Game.Tests/Database/LegacyExporterTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index b8dca6dc7b..c9aea80585 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -116,7 +116,7 @@ namespace osu.Game.Tests.Database public string GetExtension() => FileExtension; - protected override string FileExtension => ".ots"; + protected override string FileExtension => ".test"; } } } From c94e647e21902db2fc98bc3a42ad1b2a75246842 Mon Sep 17 00:00:00 2001 From: tsrk Date: Fri, 17 Feb 2023 09:09:56 +0000 Subject: [PATCH 0129/1400] style(KeyCounterDisplay): remove type check --- osu.Game/Screens/Play/KeyCounterDisplay.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 0f2f8e43c9..d2b50ff73d 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -29,15 +29,10 @@ namespace osu.Game.Screens.Play public override void Add(KeyCounter key) { - if (!CheckType(key)) - throw new ArgumentException($"{key.GetType()} is not a supported {nameof(KeyCounter)}.", nameof(key)); - base.Add(key); key.IsCounting = IsCounting; } - protected virtual bool CheckType(KeyCounter key) => true; - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 8830e0658834095dd87e3d9b82b425528021b93a Mon Sep 17 00:00:00 2001 From: tsrk Date: Fri, 17 Feb 2023 09:17:11 +0000 Subject: [PATCH 0130/1400] fix: compilation --- osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs index b69ecfd7ae..fbf1b87395 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -49,8 +49,6 @@ namespace osu.Game.Screens.Play defaultKey.KeyUpTextColor = KeyUpTextColor; } - protected override bool CheckType(KeyCounter key) => key is DefaultKeyCounter; - protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); From ceed3606cd7a3b0666c345ea768219ac5e65b91d Mon Sep 17 00:00:00 2001 From: Cootz <50776304+Cootz@users.noreply.github.com> Date: Fri, 17 Feb 2023 13:46:06 +0300 Subject: [PATCH 0131/1400] Remove redundant comment Co-authored-by: Dean Herbert --- osu.Game/Database/LegacyExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 7434a46602..7fe0428db3 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -66,7 +66,7 @@ namespace osu.Game.Database { string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); //Truncating the name to fit the path limit + filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); filename = $"{filenameWithoutExtension}{FileExtension}"; } From a3b440493aeae5fc3fbea99e36be28758c8fe2ba Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 15:23:43 +0300 Subject: [PATCH 0132/1400] Update xml doc --- osu.Game/Database/LegacyExporter.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 7fe0428db3..2d0a1d3528 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -24,9 +24,18 @@ namespace osu.Game.Database /// Max length of filename (including extension). /// /// - /// TODO: WHY? DOCUMENTATION PER PLATFORM LINKS HERE. - /// - /// This actual usable length is smaller 256 because adds additional "_" to the end of the path + /// + /// Filename limit for most OSs is 255, this actual usable length is smaller because adds additional "_" to the end of the path. + /// + /// + /// For more information see: + ///
+ /// File specification syntax + ///
+ ///
+ /// File systems limitations + ///
+ ///
///
public const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) From fd1beaef87ef2156b5f5e56bf6d1656ece326a16 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 15:24:27 +0300 Subject: [PATCH 0133/1400] Fix typo --- osu.Game/Database/LegacyExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 2d0a1d3528..04d5a3aebc 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -25,7 +25,7 @@ namespace osu.Game.Database ///
/// /// - /// Filename limit for most OSs is 255, this actual usable length is smaller because adds additional "_" to the end of the path. + /// The filename limit for most OSs is 255. This actual usable length is smaller because adds an additional "_" to the end of the path. /// /// /// For more information see: From e3bdb3d852a85748032ea468d1763849aee74249 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 17 Feb 2023 15:32:36 +0300 Subject: [PATCH 0134/1400] Align links in one line --- osu.Game/Database/LegacyExporter.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 04d5a3aebc..cf88efb151 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -28,13 +28,7 @@ namespace osu.Game.Database /// The filename limit for most OSs is 255. This actual usable length is smaller because adds an additional "_" to the end of the path. /// /// - /// For more information see: - ///
- /// File specification syntax - ///
- ///
- /// File systems limitations - ///
+ /// For more information see file specification syntax, file systems limitations ///
///
public const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) From eac0aa79a3bcaf23982b590144ec5471cc4f952c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 17 Feb 2023 21:52:10 +0900 Subject: [PATCH 0135/1400] cancellationToken pass, notification adujust --- osu.Game/Database/LegacyModelExporter.cs | 73 ++++++++++++++---------- osu.Game/Database/LegacyScoreExporter.cs | 3 +- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index d896e4bce6..1475f29f89 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; using osu.Framework.Logging; using osu.Framework.Platform; @@ -32,33 +33,52 @@ namespace osu.Game.Database protected Storage UserFileStorage; private readonly Storage exportStorage; - protected RealmAccess RealmAccess; + private readonly RealmAccess realmAccess; private string filename = string.Empty; public Action? PostNotification { get; set; } + /// + /// Construct exporter. + /// Create a new exporter for each export, otherwise it will cause confusing notifications. + /// + /// Storage for storing exported files. Basically it is used to provide export stream + /// The RealmAccess used to provide the exported file. protected LegacyModelExporter(Storage storage, RealmAccess realm) { exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); - RealmAccess = realm; + realmAccess = realm; } /// /// Export the model to default folder. /// /// The model should export. + /// + /// The Cancellation token that can cancel the exporting. + /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. + /// /// - public async Task ExportAsync(TModel model) + public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { string itemFilename = model.GetDisplayString().GetValidFilename(); IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); bool success; + ProgressNotification notification = new ProgressNotification + { + State = ProgressNotificationState.Active, + Text = "Exporting...", + CompletionText = "Export completed" + }; + notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); + PostNotification?.Invoke(notification); + using (var stream = exportStorage.CreateFileSafely(filename)) { - success = await ExportToStreamAsync(model, stream); + success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken); } if (!success) @@ -72,44 +92,34 @@ namespace osu.Game.Database ///
/// The medel which have . /// The stream to export. + /// The notification will displayed to the user + /// The Cancellation token that can cancel the exporting. /// Whether the export was successful - public async Task ExportToStreamAsync(TModel model, Stream stream) + public async Task ExportToStreamAsync(TModel model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) { - ProgressNotification notification = new ProgressNotification - { - State = ProgressNotificationState.Active, - Text = "Exporting...", - CompletionText = "Export completed" - }; - notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); - PostNotification?.Invoke(notification); + ProgressNotification notify = notification ?? new ProgressNotification(); Guid id = model.ID; return await Task.Run(() => { - RealmAccess.Run(r => + realmAccess.Run(r => { TModel refetchModel = r.Find(id); - ExportToStream(refetchModel, stream, notification); + ExportToStream(refetchModel, stream, notify, cancellationToken); }); - }, notification.CancellationToken).ContinueWith(t => + }, cancellationToken).ContinueWith(t => { - if (t.IsCanceled) - { - return false; - } - if (t.IsFaulted) { - notification.State = ProgressNotificationState.Cancelled; + notify.State = ProgressNotificationState.Cancelled; Logger.Error(t.Exception, "An error occurred while exporting"); return false; } - notification.CompletionText = "Export Complete, Click to open the folder"; - notification.State = ProgressNotificationState.Completed; + notify.CompletionText = "Export Complete, Click to open the folder"; + notify.State = ProgressNotificationState.Completed; return true; - }); + }, cancellationToken); } /// @@ -119,7 +129,8 @@ namespace osu.Game.Database /// The item to export. /// The output stream to export to. /// The notification will displayed to the user - protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification); + /// The Cancellation token that can cancel the exporting. + protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default); } public abstract class LegacyArchiveExporter : LegacyModelExporter @@ -130,15 +141,17 @@ namespace osu.Game.Database { } - protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification) => exportZipArchive(model, outputStream, notification); + protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) + => exportZipArchive(model, outputStream, notification, cancellationToken); /// /// Exports an item to Stream as a legacy (.zip based) package. /// - /// The item to export. + /// The model will be exported. /// The output stream to export to. /// The notification will displayed to the user - private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification) + /// The Cancellation token that can cancel the exporting. + private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) { using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); @@ -147,7 +160,7 @@ namespace osu.Game.Database foreach (var file in model.Files) { - notification.CancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) { diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 1a30d823e1..b3a9276d5e 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Threading; using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays.Notifications; @@ -19,7 +20,7 @@ namespace osu.Game.Database protected override string FileExtension => ".osr"; - protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification notification) + protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification notification, CancellationToken cancellationToken = default) { var file = model.Files.SingleOrDefault(); if (file == null) From 29d6483e172597216df72e884ff8f9096985820d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 17 Feb 2023 22:19:24 +0900 Subject: [PATCH 0136/1400] ConfigureAwait for awaited task --- osu.Game/Database/LegacyModelExporter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 1475f29f89..ff0e3de20a 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -78,7 +78,7 @@ namespace osu.Game.Database using (var stream = exportStorage.CreateFileSafely(filename)) { - success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken); + success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken).ConfigureAwait(false); } if (!success) @@ -119,7 +119,7 @@ namespace osu.Game.Database notify.CompletionText = "Export Complete, Click to open the folder"; notify.State = ProgressNotificationState.Completed; return true; - }, cancellationToken); + }, cancellationToken).ConfigureAwait(false); } /// From 843d841f5a4687caccde1dc0a5d3570ee653875f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 17 Feb 2023 22:23:50 +0900 Subject: [PATCH 0137/1400] GetFilename and something other https://github.com/ppy/osu/pull/21739 --- osu.Game/Database/LegacyModelExporter.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index ff0e3de20a..644b486c2d 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -32,10 +32,10 @@ namespace osu.Game.Database protected Storage UserFileStorage; private readonly Storage exportStorage; + protected virtual string GetFilename(TModel item) => item.GetDisplayString(); private readonly RealmAccess realmAccess; - private string filename = string.Empty; public Action? PostNotification { get; set; } /// @@ -62,9 +62,12 @@ namespace osu.Game.Database /// public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { - string itemFilename = model.GetDisplayString().GetValidFilename(); - IEnumerable existingExports = exportStorage.GetFiles("", $"{itemFilename}*{FileExtension}"); - filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); + string itemFilename = GetFilename(model).GetValidFilename(); + IEnumerable existingExports = + exportStorage + .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") + .Concat(exportStorage.GetDirectories(string.Empty)); + string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); bool success; ProgressNotification notification = new ProgressNotification From 309e9b24e28135dc9ef9e341292ddb7137efaa33 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 01:18:27 +0900 Subject: [PATCH 0138/1400] split LegacyArchiveExporter --- osu.Game/Database/LegacyArchiveExporter.cs | 73 ++++++++++++++++++++++ osu.Game/Database/LegacyModelExporter.cs | 60 ------------------ 2 files changed, 73 insertions(+), 60 deletions(-) create mode 100644 osu.Game/Database/LegacyArchiveExporter.cs diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs new file mode 100644 index 0000000000..f87f373624 --- /dev/null +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using System.Linq; +using System.Threading; +using osu.Framework.Platform; +using osu.Game.Extensions; +using osu.Game.Overlays.Notifications; +using Realms; +using SharpCompress.Common; +using SharpCompress.Writers; +using SharpCompress.Writers.Zip; + +namespace osu.Game.Database +{ + public abstract class LegacyArchiveExporter : LegacyModelExporter + where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey + { + protected LegacyArchiveExporter(Storage storage, RealmAccess realm) + : base(storage, realm) + { + } + + protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) + => exportZipArchive(model, outputStream, notification, cancellationToken); + + /// + /// Exports an item to Stream as a legacy (.zip based) package. + /// + /// The model will be exported. + /// The output stream to export to. + /// The notification will displayed to the user + /// The Cancellation token that can cancel the exporting. + private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) + { + using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); + + float i = 0; + bool fileMissing = false; + + foreach (var file in model.Files) + { + cancellationToken.ThrowIfCancellationRequested(); + + using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) + { + // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. + if (stream == null) + { + // Only pop up once to prevent spam. + if (!fileMissing) + { + PostNotification?.Invoke(new SimpleErrorNotification + { + Text = "Some of your files are missing, they will not be included in the archive" + }); + fileMissing = true; + } + } + else + { + writer.Write(file.Filename, stream); + } + } + + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } + } + } +} diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 644b486c2d..69277879dc 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -13,9 +13,6 @@ using osu.Game.Extensions; using osu.Game.Overlays.Notifications; using osu.Game.Utils; using Realms; -using SharpCompress.Common; -using SharpCompress.Writers; -using SharpCompress.Writers.Zip; namespace osu.Game.Database { @@ -135,61 +132,4 @@ namespace osu.Game.Database /// The Cancellation token that can cancel the exporting. protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default); } - - public abstract class LegacyArchiveExporter : LegacyModelExporter - where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey - { - protected LegacyArchiveExporter(Storage storage, RealmAccess realm) - : base(storage, realm) - { - } - - protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) - => exportZipArchive(model, outputStream, notification, cancellationToken); - - /// - /// Exports an item to Stream as a legacy (.zip based) package. - /// - /// The model will be exported. - /// The output stream to export to. - /// The notification will displayed to the user - /// The Cancellation token that can cancel the exporting. - private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) - { - using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); - - float i = 0; - bool fileMissing = false; - - foreach (var file in model.Files) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) - { - // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. - if (stream == null) - { - // Only pop up once to prevent spam. - if (!fileMissing) - { - PostNotification?.Invoke(new SimpleErrorNotification - { - Text = "Some of your files are missing, they will not be included in the archive" - }); - fileMissing = true; - } - } - else - { - writer.Write(file.Filename, stream); - } - } - - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; - } - } - } } From d61160374255aff4b4564207afd2c6aeca93405f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 01:45:09 +0900 Subject: [PATCH 0139/1400] catch OperationCanceledException --- osu.Game/Database/LegacyModelExporter.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 69277879dc..e17805f417 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -76,9 +76,16 @@ namespace osu.Game.Database notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); PostNotification?.Invoke(notification); - using (var stream = exportStorage.CreateFileSafely(filename)) + try { - success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken).ConfigureAwait(false); + using (var stream = exportStorage.CreateFileSafely(filename)) + { + success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken).ConfigureAwait(false); + } + } + catch (OperationCanceledException) + { + success = false; } if (!success) From 30985f192ee462a7e08a5a12792906b16f2229b0 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:06:07 +0900 Subject: [PATCH 0140/1400] catch ObjectDisposedException --- osu.Game/Database/LegacyArchiveExporter.cs | 52 +++++++++++++--------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index f87f373624..2f75e36fee 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.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 System; using System.IO; using System.Linq; using System.Threading; @@ -39,34 +40,45 @@ namespace osu.Game.Database float i = 0; bool fileMissing = false; - foreach (var file in model.Files) + try { - cancellationToken.ThrowIfCancellationRequested(); - - using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) + foreach (var file in model.Files) { - // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. - if (stream == null) + cancellationToken.ThrowIfCancellationRequested(); + + using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) { - // Only pop up once to prevent spam. - if (!fileMissing) + // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. + if (stream == null) { - PostNotification?.Invoke(new SimpleErrorNotification + // Only pop up once to prevent spam. + if (!fileMissing) { - Text = "Some of your files are missing, they will not be included in the archive" - }); - fileMissing = true; + PostNotification?.Invoke(new SimpleErrorNotification + { + Text = "Some of your files are missing, they will not be included in the archive" + }); + fileMissing = true; + } + } + else + { + writer.Write(file.Filename, stream); } } - else - { - writer.Write(file.Filename, stream); - } - } - i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + i++; + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } + } + catch (ObjectDisposedException) + { + // outputStream may close before writing when request cancel + if (cancellationToken.IsCancellationRequested) + return; + + throw; } } } From 2a6ea99e6a0da51b7e610125e4bbb2d6175675b3 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:09:59 +0900 Subject: [PATCH 0141/1400] store exportingModels for all exporter No one wants to export multiple copies of the same model at the same time, right? --- osu.Game/Database/LegacyModelExporter.cs | 28 ++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index e17805f417..f9605140e3 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -35,6 +35,9 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } + // Store the model being exported. + private readonly List exportingModels = new List(); + /// /// Construct exporter. /// Create a new exporter for each export, otherwise it will cause confusing notifications. @@ -59,13 +62,26 @@ namespace osu.Game.Database /// public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { + if (!exportingModels.Contains(model)) + { + exportingModels.Add(model); + } + else + { + PostNotification?.Invoke(new SimpleErrorNotification() + { + Text = "File is being exported" + }); + return; + } + string itemFilename = GetFilename(model).GetValidFilename(); IEnumerable existingExports = exportStorage .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") .Concat(exportStorage.GetDirectories(string.Empty)); string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - bool success; + bool success = false; ProgressNotification notification = new ProgressNotification { @@ -87,10 +103,14 @@ namespace osu.Game.Database { success = false; } - - if (!success) + finally { - exportStorage.Delete(filename); + if (!success) + { + exportStorage.Delete(filename); + } + + exportingModels.Remove(model); } } From 8446e7d841993bcb8644d542daa6a3ae9b482905 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:17:24 +0900 Subject: [PATCH 0142/1400] comment --- osu.Game/Database/LegacyArchiveExporter.cs | 2 +- osu.Game/Database/LegacyModelExporter.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 2f75e36fee..24a5d52f73 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -74,7 +74,7 @@ namespace osu.Game.Database } catch (ObjectDisposedException) { - // outputStream may close before writing when request cancel + // outputStream may close before writing when request cancel. if (cancellationToken.IsCancellationRequested) return; diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index f9605140e3..fd63b5f28a 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -35,7 +35,7 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } - // Store the model being exported. + // Store the model being exporting. private readonly List exportingModels = new List(); /// @@ -62,6 +62,7 @@ namespace osu.Game.Database /// public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { + // check if the model is being exporting already if (!exportingModels.Contains(model)) { exportingModels.Add(model); @@ -105,6 +106,7 @@ namespace osu.Game.Database } finally { + // cleanup if export is failed or canceled. if (!success) { exportStorage.Delete(filename); From 79715fe37b3ac24ce30e1dd50e441c67adc27e5e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:24:07 +0900 Subject: [PATCH 0143/1400] catch when zipWriter dispose ObjectDisposedException also appear when zipwriter dispose after user request cancel --- osu.Game/Database/LegacyArchiveExporter.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 24a5d52f73..fd2befd2e0 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -35,13 +35,13 @@ namespace osu.Game.Database /// The Cancellation token that can cancel the exporting. private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) { - using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); - - float i = 0; - bool fileMissing = false; - try { + var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); + + float i = 0; + bool fileMissing = false; + foreach (var file in model.Files) { cancellationToken.ThrowIfCancellationRequested(); From fba99b344ce666f04057096f42a0edf70fb41dcd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:41:08 +0900 Subject: [PATCH 0144/1400] Accidentally deleted using wtf --- osu.Game/Database/LegacyArchiveExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index fd2befd2e0..e5215e13a6 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -37,7 +37,7 @@ namespace osu.Game.Database { try { - var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); + using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); float i = 0; bool fileMissing = false; From 229b31520f039a9dbacb99cabab04e132dfdf9fb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:42:33 +0900 Subject: [PATCH 0145/1400] remove () --- osu.Game/Database/LegacyModelExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index fd63b5f28a..acb83ce1d5 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -69,7 +69,7 @@ namespace osu.Game.Database } else { - PostNotification?.Invoke(new SimpleErrorNotification() + PostNotification?.Invoke(new SimpleErrorNotification { Text = "File is being exported" }); From 0667b8396083dd52fc1f4d321d49f56068c45ff4 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 19 Feb 2023 02:56:53 +0900 Subject: [PATCH 0146/1400] Path.GetExtension() will not get null --- osu.Game/Database/LegacyScoreImporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyScoreImporter.cs b/osu.Game/Database/LegacyScoreImporter.cs index 131b4ffb0e..b80a35f90a 100644 --- a/osu.Game/Database/LegacyScoreImporter.cs +++ b/osu.Game/Database/LegacyScoreImporter.cs @@ -20,7 +20,7 @@ namespace osu.Game.Database return Enumerable.Empty(); return storage.GetFiles(ImportFromStablePath) - .Where(p => Importer.HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.OrdinalIgnoreCase) ?? false)) + .Where(p => Importer.HandledExtensions.Any(ext => Path.GetExtension(p).Equals(ext, StringComparison.OrdinalIgnoreCase))) .Select(path => storage.GetFullPath(path)); } From 04dcd661e06988365775fec6044ddad12c39aa51 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Feb 2023 20:53:02 +0900 Subject: [PATCH 0147/1400] async logic fix --- osu.Game/Database/LegacyModelExporter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index acb83ce1d5..cd405f90be 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -124,12 +124,12 @@ namespace osu.Game.Database /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. /// Whether the export was successful - public async Task ExportToStreamAsync(TModel model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) + public Task ExportToStreamAsync(TModel model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) { ProgressNotification notify = notification ?? new ProgressNotification(); Guid id = model.ID; - return await Task.Run(() => + return Task.Run(() => { realmAccess.Run(r => { @@ -148,7 +148,7 @@ namespace osu.Game.Database notify.CompletionText = "Export Complete, Click to open the folder"; notify.State = ProgressNotificationState.Completed; return true; - }, cancellationToken).ConfigureAwait(false); + }, cancellationToken); } /// From d20e1df6030cba04cc2d75385608b59b560c5b93 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 21 Feb 2023 20:54:06 +0900 Subject: [PATCH 0148/1400] wrong xmldoc because of https://github.com/ppy/osu/pull/21308/commits/6900d0120a70287ef531a4c0facd398508a76b06 --- osu.Game/Database/LegacyModelExporter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index cd405f90be..96104a68a0 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -152,10 +152,9 @@ namespace osu.Game.Database } /// - /// Exports an item to Stream. - /// Override if custom export method is required. + /// Exports model to Stream. /// - /// The item to export. + /// The model to export. /// The output stream to export to. /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. From 90aa4288d0a9a265d666c8e66545108bce4d8edd Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 21 Feb 2023 18:35:53 +0300 Subject: [PATCH 0149/1400] Reduce the allowed length by 5 to account for (99) suffix. Move truncating logic to `GetFilename`. Update tests. --- osu.Game.Tests/Database/LegacyExporterTest.cs | 9 ++++++--- osu.Game/Database/LegacyExporter.cs | 20 +++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index c9aea80585..d41b3a5017 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Database Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); //Export multiple times - for (int i = 0; i < 10; i++) + for (int i = 0; i < 100; i++) { string expectedFileName = i == 0 ? short_filename : $"{short_filename} ({i})"; exportItemAndAssert(item, expectedFileName); @@ -76,8 +76,11 @@ namespace osu.Game.Tests.Database Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); //Export multiple times - for (int i = 0; i < 10; i++) - exportItemAndAssert(item, expectedName); + for (int i = 0; i < 100; i++) + { + string expectedFilename = i == 0 ? expectedName : $"{expectedName} ({i})"; + exportItemAndAssert(item, expectedFilename); + } } private void exportItemAndAssert(IHasNamedFiles item, string expectedName) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index cf88efb151..0fa7b9e03c 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -31,7 +31,7 @@ namespace osu.Game.Database /// For more information see file specification syntax, file systems limitations /// /// - public const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars) + public const int MAX_FILENAME_LENGTH = 255 - (32 + 4 + 2 + 5); //max path - (Guid + Guid "D" format chars + Storage.CreateFileSafely chars + account for ' (99)' suffix) /// /// The file extension for exports (including the leading '.'). @@ -48,7 +48,15 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } - protected virtual string GetFilename(TModel item) => item.GetDisplayString(); + protected virtual string GetFilename(TModel item) + { + string filename = item.GetDisplayString(); + + if (filename.Length > MAX_FILENAME_LENGTH - FileExtension.Length) + return filename.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); + + return filename; + } /// /// Exports an item to a legacy (.zip based) package. @@ -65,14 +73,6 @@ namespace osu.Game.Database string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - if (filename.Length > MAX_FILENAME_LENGTH) - { - string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - - filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); - filename = $"{filenameWithoutExtension}{FileExtension}"; - } - using (var stream = exportStorage.CreateFileSafely(filename)) ExportModelTo(item, stream); From fc3d74472cc52b6e06cd1c0791f7277d7ed77744 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 21 Feb 2023 15:55:46 +0300 Subject: [PATCH 0150/1400] Add mobile local framework reference support --- UseLocalFramework.ps1 | 48 ++++++++++++++++++++++++++++++++++++++----- UseLocalFramework.sh | 39 +++++++++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/UseLocalFramework.ps1 b/UseLocalFramework.ps1 index 837685f310..9f4547d980 100644 --- a/UseLocalFramework.ps1 +++ b/UseLocalFramework.ps1 @@ -3,15 +3,53 @@ # # https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects -$CSPROJ="osu.Game/osu.Game.csproj" +$GAME_CSPROJ="osu.Game/osu.Game.csproj" +$ANDROID_PROPS="osu.Android.props" +$IOS_PROPS="osu.iOS.props" $SLN="osu.sln" -dotnet remove $CSPROJ package ppy.osu.Framework; -dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj; -dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj +dotnet remove $GAME_CSPROJ reference ppy.osu.Framework; +dotnet remove $ANDROID_PROPS reference ppy.osu.Framework.Android; +dotnet remove $IOS_PROPS reference ppy.osu.Framework.iOS; + +dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ` + ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj ` + ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj ` + ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj; + +dotnet add $GAME_CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj; +dotnet add $ANDROID_PROPS reference ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj; +dotnet add $IOS_PROPS reference ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj; + +# workaround for dotnet add not inserting $(MSBuildThisFileDirectory) on props files +(Get-Content "osu.Android.props") -replace "`"..\\osu-framework", "`"`$(MSBuildThisFileDirectory)..\osu-framework" | Set-Content "osu.Android.props" +(Get-Content "osu.iOS.props") -replace "`"..\\osu-framework", "`"`$(MSBuildThisFileDirectory)..\osu-framework" | Set-Content "osu.iOS.props" + +# needed because iOS framework nupkg includes a set of properties to work around certain issues during building, +# and those get ignored when referencing framework via project, threfore we have to manually include it via props reference. +(Get-Content "osu.iOS.props") | + Foreach-Object { + if ($_ -match "") + { + " " + } + + $_ + } | Set-Content "osu.iOS.props" + +$TMP=New-TemporaryFile $SLNF=Get-Content "osu.Desktop.slnf" | ConvertFrom-Json -$TMP=New-TemporaryFile $SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj") ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8 Move-Item -Path $TMP -Destination "osu.Desktop.slnf" -Force + +$SLNF=Get-Content "osu.Android.slnf" | ConvertFrom-Json +$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj") +ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8 +Move-Item -Path $TMP -Destination "osu.Android.slnf" -Force + +$SLNF=Get-Content "osu.iOS.slnf" | ConvertFrom-Json +$SLNF.solution.projects += ("../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj") +ConvertTo-Json $SLNF | Out-File $TMP -Encoding UTF8 +Move-Item -Path $TMP -Destination "osu.iOS.slnf" -Force diff --git a/UseLocalFramework.sh b/UseLocalFramework.sh index 4fd1fdfd1b..c12b388e96 100755 --- a/UseLocalFramework.sh +++ b/UseLocalFramework.sh @@ -5,14 +5,41 @@ # # https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects -CSPROJ="osu.Game/osu.Game.csproj" +GAME_CSPROJ="osu.Game/osu.Game.csproj" +ANDROID_PROPS="osu.Android.props" +IOS_PROPS="osu.iOS.props" SLN="osu.sln" -dotnet remove $CSPROJ package ppy.osu.Framework -dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj -dotnet add $CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj +dotnet remove $GAME_CSPROJ reference ppy.osu.Framework +dotnet remove $ANDROID_PROPS reference ppy.osu.Framework.Android +dotnet remove $IOS_PROPS reference ppy.osu.Framework.iOS + +dotnet sln $SLN add ../osu-framework/osu.Framework/osu.Framework.csproj \ + ../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj \ + ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj \ + ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj + +dotnet add $GAME_CSPROJ reference ../osu-framework/osu.Framework/osu.Framework.csproj +dotnet add $ANDROID_PROPS reference ../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj +dotnet add $IOS_PROPS reference ../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj + +# workaround for dotnet add not inserting $(MSBuildThisFileDirectory) on props files +sed -i.bak 's:"..\\osu-framework:"$(MSBuildThisFileDirectory)..\\osu-framework:g' ./osu.Android.props && rm osu.Android.props.bak +sed -i.bak 's:"..\\osu-framework:"$(MSBuildThisFileDirectory)..\\osu-framework:g' ./osu.iOS.props && rm osu.iOS.props.bak + +# needed because iOS framework nupkg includes a set of properties to work around certain issues during building, +# and those get ignored when referencing framework via project, threfore we have to manually include it via props reference. +sed -i.bak '/<\/Project>/i\ + \ +' ./osu.iOS.props && rm osu.iOS.props.bak -SLNF="osu.Desktop.slnf" tmp=$(mktemp) + jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj"]' osu.Desktop.slnf > $tmp -mv -f $tmp $SLNF +mv -f $tmp osu.Desktop.slnf + +jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.Android/osu.Framework.Android.csproj"]' osu.Android.slnf > $tmp +mv -f $tmp osu.Android.slnf + +jq '.solution.projects += ["../osu-framework/osu.Framework/osu.Framework.csproj", "../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj", "../osu-framework/osu.Framework.iOS/osu.Framework.iOS.csproj"]' osu.iOS.slnf > $tmp +mv -f $tmp osu.iOS.slnf From 191604340f8cbaf4d42c31cbc2ef2665fdfbb318 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 21 Feb 2023 19:05:10 +0100 Subject: [PATCH 0151/1400] Added a way for mod settings to be kept when changing ruleset + test --- .../TestSceneModSelectOverlay.cs | 48 +++++++++++++++++++ osu.Game/OsuGameBase.cs | 17 ++++++- osu.Game/Rulesets/Mods/Mod.cs | 31 ++++++++++-- 3 files changed, 91 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5ccaebd721..25edcd4e0a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -21,6 +21,7 @@ using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Tests.Mods; using osuTK; using osuTK.Input; @@ -371,6 +372,53 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("no mod selected", () => SelectedMods.Value.Count == 0); } + [Test] + public void TestKeepSharedSettingsFromSimilarMods() + { + const float setting_change = 1.2f; + + createScreen(); + changeRuleset(0); + + AddStep("select difficulty adjust mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod()! }); + + changeRuleset(0); + AddAssert("ensure mod still selected", () => SelectedMods.Value.SingleOrDefault() is OsuModDifficultyAdjust); + + AddStep("change mod settings", () => + { + var osuMod = (getMod() as OsuModDifficultyAdjust)!; + osuMod.ExtendedLimits.Value = true; + osuMod.CircleSize.Value = setting_change; + osuMod.DrainRate.Value = setting_change; + osuMod.OverallDifficulty.Value = setting_change; + osuMod.ApproachRate.Value = setting_change; + }); + + changeRuleset(1); + AddAssert("taiko variant selected", () => SelectedMods.Value.SingleOrDefault() is TaikoModDifficultyAdjust); + + AddAssert("shared settings didn't change", () => + { + var taikoMod = getMod() as TaikoModDifficultyAdjust; + return + taikoMod?.ExtendedLimits.Value == true && + taikoMod?.DrainRate.Value == setting_change && + taikoMod?.OverallDifficulty.Value == setting_change; + }); + + AddAssert("non-shared settings at default", () => + { + var taikoMod = getMod() as TaikoModDifficultyAdjust; + if (taikoMod == null) + return false; + + return taikoMod.ScrollSpeed.Value == taikoMod.ScrollSpeed.Default; + }); + + ModDifficultyAdjust getMod() => (SelectedMods.Value.Single() as ModDifficultyAdjust)!; + } + [Test] public void TestExternallySetCustomizedMod() { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index cf58d07b9e..9644e3fc75 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -393,8 +393,11 @@ namespace osu.Game Ruleset.BindValueChanged(onRulesetChanged); Beatmap.BindValueChanged(onBeatmapChanged); + SelectedMods.BindValueChanged(change => Logger.Log($"{modSetting(change.OldValue)} => {modSetting(change.NewValue)}")); } + private object modSetting(IReadOnlyList mods) => mods.OfType().FirstOrDefault()?.GetSettingsSourceProperties().First().Item2.GetValue(mods.OfType().First())!; + private void addFilesWarning() { var realmStore = new RealmFileStore(realm, Storage); @@ -626,7 +629,8 @@ namespace osu.Game return; } - var previouslySelectedMods = SelectedMods.Value.ToArray(); + //for some reason emptying SelectedMods resets all SettingSources Bindables to default value + var previouslySelectedMods = SelectedMods.Value.Select(mod => mod.DeepClone()).ToArray(); if (!SelectedMods.Disabled) SelectedMods.Value = Array.Empty(); @@ -634,7 +638,16 @@ namespace osu.Game AvailableMods.Value = dict; if (!SelectedMods.Disabled) - SelectedMods.Value = previouslySelectedMods.Select(m => instance.CreateModFromAcronym(m.Acronym)).Where(m => m != null).ToArray(); + { + SelectedMods.Value = previouslySelectedMods.Select(oldMod => + { + Mod newMod = instance.CreateModFromAcronym(oldMod.Acronym); + + newMod?.CopyFromSimilar(oldMod); + + return newMod; + }).Where(m => m != null).ToArray(); + } void revertRulesetChange() => Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); } diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 04d55bc5fe..7cb647d223 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Framework.Testing; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Rulesets.UI; using osu.Game.Utils; @@ -139,6 +140,30 @@ namespace osu.Game.Rulesets.Mods return result; } + /// + /// Copies all shared mod setting values from into this instance. + /// + /// The mod to copy properties from. + public void CopyFromSimilar(Mod source) + { + Dictionary oldSettings = new Dictionary(); + + foreach (var (_, property) in source.GetSettingsSourceProperties()) + { + oldSettings.Add(property.Name.ToSnakeCase(), property.GetValue(source)!); + } + + foreach (var (_, property) in this.GetSettingsSourceProperties()) + { + var targetBindable = (IBindable)property.GetValue(this)!; + + if (!oldSettings.TryGetValue(property.Name.ToSnakeCase(), out object? sourceSetting)) + continue; + + CopyAdjustedSetting(targetBindable, sourceSetting); + } + } + /// /// Copies mod setting values from into this instance, overwriting all existing settings. /// @@ -148,10 +173,10 @@ namespace osu.Game.Rulesets.Mods if (source.GetType() != GetType()) throw new ArgumentException($"Expected mod of type {GetType()}, got {source.GetType()}.", nameof(source)); - foreach (var (_, prop) in this.GetSettingsSourceProperties()) + foreach (var (_, property) in this.GetSettingsSourceProperties()) { - var targetBindable = (IBindable)prop.GetValue(this)!; - var sourceBindable = (IBindable)prop.GetValue(source)!; + var targetBindable = (IBindable)property.GetValue(this)!; + var sourceBindable = (IBindable)property.GetValue(source)!; CopyAdjustedSetting(targetBindable, sourceBindable); } From 5bec2d7c525fac4fd975f0abb3e5fd19a37ef843 Mon Sep 17 00:00:00 2001 From: tsrk Date: Tue, 21 Feb 2023 19:02:56 +0000 Subject: [PATCH 0152/1400] style(KeyCounter): `forwardPlayback` --- osu.Game/Screens/Play/KeyCounter.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 212843cbe9..a07c650736 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -60,17 +60,17 @@ namespace osu.Game.Screens.Play countPresses.Value--; } - protected virtual void Activate(bool increment = true) + protected virtual void Activate(bool forwardPlayback = true) { IsActive.Value = true; - if (increment) + if (forwardPlayback) Increment(); } - protected virtual void Deactivate(bool preserve = true) + protected virtual void Deactivate(bool forwardPlayback = true) { IsActive.Value = false; - if (!preserve) + if (!forwardPlayback) Decrement(); } From 42a5a06b9d6e8e1416c2aaf828dfe236e9617b6e Mon Sep 17 00:00:00 2001 From: tsrk Date: Tue, 21 Feb 2023 19:10:37 +0000 Subject: [PATCH 0153/1400] style(KeyCounter): fields and methods visiblity --- osu.Game/Screens/Play/KeyCounter.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index a07c650736..4bad6920e3 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -42,9 +42,9 @@ namespace osu.Game.Screens.Play Name = trigger.Name; } - protected Bindable IsActive = new BindableBool(); + protected readonly Bindable IsActive = new BindableBool(); - public void Increment() + private void increment() { if (!IsCounting) return; @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Play countPresses.Value++; } - public void Decrement() + private void decrement() { if (!IsCounting) return; @@ -64,14 +64,14 @@ namespace osu.Game.Screens.Play { IsActive.Value = true; if (forwardPlayback) - Increment(); + increment(); } protected virtual void Deactivate(bool forwardPlayback = true) { IsActive.Value = false; if (!forwardPlayback) - Decrement(); + decrement(); } protected override void Dispose(bool isDisposing) From dd53a700711dd79fac8466fca94ea881db5fa537 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 21 Feb 2023 20:59:36 +0100 Subject: [PATCH 0154/1400] Addressed change requests --- .../TestSceneModSelectOverlay.cs | 4 +- osu.Game/OsuGameBase.cs | 8 +--- osu.Game/Rulesets/Mods/Mod.cs | 40 +++++++++---------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 25edcd4e0a..7a46876737 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -403,8 +403,8 @@ namespace osu.Game.Tests.Visual.UserInterface var taikoMod = getMod() as TaikoModDifficultyAdjust; return taikoMod?.ExtendedLimits.Value == true && - taikoMod?.DrainRate.Value == setting_change && - taikoMod?.OverallDifficulty.Value == setting_change; + taikoMod.DrainRate.Value == setting_change && + taikoMod.OverallDifficulty.Value == setting_change; }); AddAssert("non-shared settings at default", () => diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 9644e3fc75..af2fb123d3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -58,7 +58,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; -using File = System.IO.File; using RuntimeInfo = osu.Framework.RuntimeInfo; namespace osu.Game @@ -393,11 +392,8 @@ namespace osu.Game Ruleset.BindValueChanged(onRulesetChanged); Beatmap.BindValueChanged(onBeatmapChanged); - SelectedMods.BindValueChanged(change => Logger.Log($"{modSetting(change.OldValue)} => {modSetting(change.NewValue)}")); } - private object modSetting(IReadOnlyList mods) => mods.OfType().FirstOrDefault()?.GetSettingsSourceProperties().First().Item2.GetValue(mods.OfType().First())!; - private void addFilesWarning() { var realmStore = new RealmFileStore(realm, Storage); @@ -629,7 +625,7 @@ namespace osu.Game return; } - //for some reason emptying SelectedMods resets all SettingSources Bindables to default value + //DeepCloning collection, because emptying SelectedMods resets all SettingSources Bindables to their default value var previouslySelectedMods = SelectedMods.Value.Select(mod => mod.DeepClone()).ToArray(); if (!SelectedMods.Disabled) @@ -643,7 +639,7 @@ namespace osu.Game { Mod newMod = instance.CreateModFromAcronym(oldMod.Acronym); - newMod?.CopyFromSimilar(oldMod); + newMod?.CopySharedSettings(oldMod); return newMod; }).Where(m => m != null).ToArray(); diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 7cb647d223..bc588a5cd8 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -141,10 +141,28 @@ namespace osu.Game.Rulesets.Mods } /// - /// Copies all shared mod setting values from into this instance. + /// Copies mod setting values from into this instance, overwriting all existing settings. /// /// The mod to copy properties from. - public void CopyFromSimilar(Mod source) + public void CopyFrom(Mod source) + { + if (source.GetType() != GetType()) + throw new ArgumentException($"Expected mod of type {GetType()}, got {source.GetType()}.", nameof(source)); + + foreach (var (_, property) in this.GetSettingsSourceProperties()) + { + var targetBindable = (IBindable)property.GetValue(this)!; + var sourceBindable = (IBindable)property.GetValue(source)!; + + CopyAdjustedSetting(targetBindable, sourceBindable); + } + } + + /// + /// Copies all mod setting values sharing same from into this instance. + /// + /// The mod to copy properties from. + internal void CopySharedSettings(Mod source) { Dictionary oldSettings = new Dictionary(); @@ -164,24 +182,6 @@ namespace osu.Game.Rulesets.Mods } } - /// - /// Copies mod setting values from into this instance, overwriting all existing settings. - /// - /// The mod to copy properties from. - public void CopyFrom(Mod source) - { - if (source.GetType() != GetType()) - throw new ArgumentException($"Expected mod of type {GetType()}, got {source.GetType()}.", nameof(source)); - - foreach (var (_, property) in this.GetSettingsSourceProperties()) - { - var targetBindable = (IBindable)property.GetValue(this)!; - var sourceBindable = (IBindable)property.GetValue(source)!; - - CopyAdjustedSetting(targetBindable, sourceBindable); - } - } - /// /// When creating copies or clones of a Mod, this method will be called /// to copy explicitly adjusted user settings from . From 82b07d19f86374a24128ee4e8ff7918bf1aa7acf Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 21 Feb 2023 21:48:11 +0100 Subject: [PATCH 0155/1400] Fix of incorrect `using` optimization --- osu.Game/OsuGameBase.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index af2fb123d3..e16aaf39ee 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -58,6 +58,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; +using File = System.IO.File; using RuntimeInfo = osu.Framework.RuntimeInfo; namespace osu.Game From e321536acc2299c19b131b457838c84f15c1aed3 Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 22 Feb 2023 07:48:43 +0100 Subject: [PATCH 0156/1400] Small clean up --- osu.Game/OsuGameBase.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e16aaf39ee..de1f2e810c 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -626,17 +626,12 @@ namespace osu.Game return; } - //DeepCloning collection, because emptying SelectedMods resets all SettingSources Bindables to their default value - var previouslySelectedMods = SelectedMods.Value.Select(mod => mod.DeepClone()).ToArray(); - - if (!SelectedMods.Disabled) - SelectedMods.Value = Array.Empty(); - AvailableMods.Value = dict; if (!SelectedMods.Disabled) { - SelectedMods.Value = previouslySelectedMods.Select(oldMod => + //converting mods from one ruleset to the other, while also keeping their shared settings unchanged + SelectedMods.Value = SelectedMods.Value.Select(oldMod => { Mod newMod = instance.CreateModFromAcronym(oldMod.Acronym); From 6e48860c79646d0f60e86e7e010954773d300730 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2023 17:13:55 +0900 Subject: [PATCH 0157/1400] Update in line with framework menu handling changes --- osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index ad02e3b2ab..0adff11342 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -77,10 +77,12 @@ namespace osu.Game.Graphics.UserInterface private void updateState() { - hoverClickSounds.Enabled.Value = !Item.Action.Disabled; - Alpha = Item.Action.Disabled ? 0.2f : 1; + bool enabledState = IsActionable || HasSubmenu; - if (IsHovered && !Item.Action.Disabled) + hoverClickSounds.Enabled.Value = enabledState; + Alpha = enabledState ? 1 : 0.2f; + + if (IsHovered && enabledState) { text.BoldText.FadeIn(transition_length, Easing.OutQuint); text.NormalText.FadeOut(transition_length, Easing.OutQuint); From 16c8a392a1c7c73d0aeae9aa02edcd1a6e4d2f7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2023 17:45:38 +0900 Subject: [PATCH 0158/1400] Add ability to send selected skin components to front or back --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 37 ++++++++++++++++++- .../SkinEditor/SkinSelectionHandler.cs | 9 +++++ .../ISerialisableDrawableContainer.cs | 3 +- osu.Game/Skinning/SkinComponentsContainer.cs | 4 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 9d470f58f1..95b88b141f 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -556,11 +556,46 @@ namespace osu.Game.Overlays.SkinEditor changeHandler?.BeginChange(); foreach (var item in items) - availableTargets.FirstOrDefault(t => t.Components.Contains(item))?.Remove(item); + availableTargets.FirstOrDefault(t => t.Components.Contains(item))?.Remove(item, true); changeHandler?.EndChange(); } + public void BringSelectionToFront() + { + if (getTarget(selectedTarget.Value) is not SkinComponentsContainer target) + return; + + // Iterating by target components order ensures we maintain the same order across selected components, regardless + // of the order they were selected in. + foreach (var d in target.Components.ToArray()) + { + if (!SelectedComponents.Contains(d)) + continue; + + target.Remove(d, false); + + // Selection would be reset by the remove. + SelectedComponents.Add(d); + target.Add(d); + } + } + + public void SendSelectionToBack() + { + if (getTarget(selectedTarget.Value) is not SkinComponentsContainer target) + return; + + foreach (var d in target.Components.ToArray()) + { + if (SelectedComponents.Contains(d)) + continue; + + target.Remove(d, false); + target.Add(d); + } + } + #region Drag & drop import handling public Task Import(params string[] paths) diff --git a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs index c628ad8480..b43f4eeb00 100644 --- a/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinSelectionHandler.cs @@ -13,6 +13,7 @@ using osu.Framework.Utils; using osu.Game.Extensions; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Skinning; using osuTK; @@ -206,6 +207,14 @@ namespace osu.Game.Overlays.SkinEditor ((Drawable)blueprint.Item).Position = Vector2.Zero; }); + yield return new EditorMenuItemSpacer(); + + yield return new OsuMenuItem("Bring to front", MenuItemType.Standard, () => skinEditor.BringSelectionToFront()); + + yield return new OsuMenuItem("Send to back", MenuItemType.Standard, () => skinEditor.SendSelectionToBack()); + + yield return new EditorMenuItemSpacer(); + foreach (var item in base.GetContextMenuItemsForSelection(selection)) yield return item; diff --git a/osu.Game/Skinning/ISerialisableDrawableContainer.cs b/osu.Game/Skinning/ISerialisableDrawableContainer.cs index 9f93d8a2e3..a19c8c5162 100644 --- a/osu.Game/Skinning/ISerialisableDrawableContainer.cs +++ b/osu.Game/Skinning/ISerialisableDrawableContainer.cs @@ -45,6 +45,7 @@ namespace osu.Game.Skinning /// Remove an existing skinnable component from this target. /// /// The component to remove. - void Remove(ISerialisableDrawable component); + /// Whether removed items should be immediately disposed. + void Remove(ISerialisableDrawable component, bool disposeImmediately); } } diff --git a/osu.Game/Skinning/SkinComponentsContainer.cs b/osu.Game/Skinning/SkinComponentsContainer.cs index d18e9023cd..adf0a288b4 100644 --- a/osu.Game/Skinning/SkinComponentsContainer.cs +++ b/osu.Game/Skinning/SkinComponentsContainer.cs @@ -100,7 +100,7 @@ namespace osu.Game.Skinning /// /// Thrown when attempting to add an element to a target which is not supported by the current skin. /// Thrown if the provided instance is not a . - public void Remove(ISerialisableDrawable component) + public void Remove(ISerialisableDrawable component, bool disposeImmediately) { if (content == null) throw new NotSupportedException("Attempting to remove a new component from a target container which is not supported by the current skin."); @@ -108,7 +108,7 @@ namespace osu.Game.Skinning if (!(component is Drawable drawable)) throw new ArgumentException($"Provided argument must be of type {nameof(Drawable)}.", nameof(component)); - content.Remove(drawable, true); + content.Remove(drawable, disposeImmediately); components.Remove(component); } From 90ca635a1771d9953f3891656296b7b7d98dda84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2023 17:56:59 +0900 Subject: [PATCH 0159/1400] Fix weird nullability in `TestSceneSkinEditor` --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 2f20d75813..83609b9ae7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -4,6 +4,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneSkinEditor : PlayerTestScene { - private SkinEditor? skinEditor; + private SkinEditor skinEditor = null!; protected override bool Autoplay => true; @@ -40,17 +41,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("reload skin editor", () => { - skinEditor?.Expire(); + if (skinEditor.IsNotNull()) + skinEditor.Expire(); Player.ScaleTo(0.4f); LoadComponentAsync(skinEditor = new SkinEditor(Player), Add); }); - AddUntilStep("wait for loaded", () => skinEditor!.IsLoaded); + AddUntilStep("wait for loaded", () => skinEditor.IsLoaded); } [Test] public void TestToggleEditor() { - AddToggleStep("toggle editor visibility", _ => skinEditor!.ToggleVisibility()); + AddToggleStep("toggle editor visibility", _ => skinEditor.ToggleVisibility()); } [Test] @@ -63,7 +65,7 @@ namespace osu.Game.Tests.Visual.Gameplay var blueprint = skinEditor.ChildrenOfType().First(b => b.Item is BarHitErrorMeter); hitErrorMeter = (BarHitErrorMeter)blueprint.Item; - skinEditor!.SelectedComponents.Clear(); + skinEditor.SelectedComponents.Clear(); skinEditor.SelectedComponents.Add(blueprint.Item); }); From 32a9c066dfd2a02c0cc40f5554417ab5bd8e8c97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Feb 2023 18:17:03 +0900 Subject: [PATCH 0160/1400] Add test coverage of bring-to-front / send-to-back operations --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 83609b9ae7..9690d00d4c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.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 System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -32,12 +33,14 @@ namespace osu.Game.Tests.Visual.Gameplay [Cached] public readonly EditorClipboard Clipboard = new EditorClipboard(); + private SkinComponentsContainer targetContainer => Player.ChildrenOfType().First(); + [SetUpSteps] public override void SetUpSteps() { base.SetUpSteps(); - AddUntilStep("wait for hud load", () => Player.ChildrenOfType().All(c => c.ComponentsLoaded)); + AddUntilStep("wait for hud load", () => targetContainer.ComponentsLoaded); AddStep("reload skin editor", () => { @@ -49,6 +52,52 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for loaded", () => skinEditor.IsLoaded); } + [TestCase(false)] + [TestCase(true)] + public void TestBringToFront(bool alterSelectionOrder) + { + AddAssert("Ensure over three components available", () => targetContainer.Components.Count, () => Is.GreaterThan(3)); + + IEnumerable originalOrder = null!; + + AddStep("Save order of components before operation", () => originalOrder = targetContainer.Components.Take(3).ToArray()); + + if (alterSelectionOrder) + AddStep("Select first three components in reverse order", () => skinEditor.SelectedComponents.AddRange(originalOrder.Reverse())); + else + AddStep("Select first three components", () => skinEditor.SelectedComponents.AddRange(originalOrder)); + + AddAssert("Components are not front-most", () => targetContainer.Components.TakeLast(3).ToArray(), () => Is.Not.EqualTo(skinEditor.SelectedComponents)); + + AddStep("Bring to front", () => skinEditor.BringSelectionToFront()); + AddAssert("Ensure components are now front-most in original order", () => targetContainer.Components.TakeLast(3).ToArray(), () => Is.EqualTo(originalOrder)); + AddStep("Bring to front again", () => skinEditor.BringSelectionToFront()); + AddAssert("Ensure components are still front-most in original order", () => targetContainer.Components.TakeLast(3).ToArray(), () => Is.EqualTo(originalOrder)); + } + + [TestCase(false)] + [TestCase(true)] + public void TestSendToBack(bool alterSelectionOrder) + { + AddAssert("Ensure over three components available", () => targetContainer.Components.Count, () => Is.GreaterThan(3)); + + IEnumerable originalOrder = null!; + + AddStep("Save order of components before operation", () => originalOrder = targetContainer.Components.TakeLast(3).ToArray()); + + if (alterSelectionOrder) + AddStep("Select last three components in reverse order", () => skinEditor.SelectedComponents.AddRange(originalOrder.Reverse())); + else + AddStep("Select last three components", () => skinEditor.SelectedComponents.AddRange(originalOrder)); + + AddAssert("Components are not back-most", () => targetContainer.Components.Take(3).ToArray(), () => Is.Not.EqualTo(skinEditor.SelectedComponents)); + + AddStep("Send to back", () => skinEditor.SendSelectionToBack()); + AddAssert("Ensure components are now back-most in original order", () => targetContainer.Components.Take(3).ToArray(), () => Is.EqualTo(originalOrder)); + AddStep("Send to back again", () => skinEditor.SendSelectionToBack()); + AddAssert("Ensure components are still back-most in original order", () => targetContainer.Components.Take(3).ToArray(), () => Is.EqualTo(originalOrder)); + } + [Test] public void TestToggleEditor() { From 1beec7103725ca9ade4b081804d8a7cc83e5c912 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 22 Feb 2023 14:58:27 +0000 Subject: [PATCH 0161/1400] refactor(KeyCounterDisplay): apply suggestions I also took the freedom to add type checking, as we can't limit the usage of `Add()` since it's a Container. The exception thrown also advises of using the suggested `AddTrigger()` instead. --- .../Visual/Gameplay/TestSceneAutoplay.cs | 2 +- .../Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- .../Visual/Gameplay/TestSceneKeyCounter.cs | 4 +- .../TestSceneSkinEditorMultipleSkins.cs | 2 +- .../Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 10 +-- .../Screens/Play/DefaultKeyCounterDisplay.cs | 27 ++++-- osu.Game/Screens/Play/KeyCounter.cs | 6 +- osu.Game/Screens/Play/KeyCounterDisplay.cs | 84 +++++++++++-------- osu.Game/Screens/Play/Player.cs | 7 +- 10 files changed, 86 insertions(+), 60 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 4b6e1f089f..903cd178b7 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 2)); seekTo(referenceBeatmap.Breaks[0].StartTime); - AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting); + AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting.Value); AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType().Single().AccuracyDisplay.Current.Value == 1); AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000)); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index af79650d29..a586d798f5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); + hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); scoreProcessor.Combo.Value = 1; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 9eeee800d9..5405274cd0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); - kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboardTrigger(key))); + kc.AddTrigger(new KeyCounterKeyboardTrigger(key)); }); Key testKey = ((KeyCounterKeyboardTrigger)kc.Children.First().Trigger).Key; @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1); addPressKeyStep(); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2); - AddStep("Disable counting", () => testCounter.IsCounting = false); + AddStep("Disable counting", () => testCounter.IsCounting.Value = false); addPressKeyStep(); AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 432ff2fc7e..e4f257582d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); + hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); scoreProcessor.Combo.Value = 1; return new Container diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 24de29fa03..9848894f84 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space))); + hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); action?.Invoke(hudOverlay); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 6a38fa4824..32b2a19e21 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -162,11 +162,11 @@ namespace osu.Game.Rulesets.UI KeyBindingContainer.Add(receptor); keyCounter.SetReceptor(receptor); - keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings - .Select(b => b.GetAction()) - .Distinct() - .OrderBy(action => action) - .Select(action => keyCounter.CreateKeyCounter(new KeyCounterActionTrigger(action)))); + keyCounter.AddTriggerRange(KeyBindingContainer.DefaultKeyBindings + .Select(b => b.GetAction()) + .Distinct() + .OrderBy(action => action) + .Select(action => new KeyCounterActionTrigger(action))); } private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs index fbf1b87395..367eb483a0 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -13,7 +13,9 @@ namespace osu.Game.Screens.Play private const int duration = 100; private const double key_fade_time = 80; - protected override Container Content => KeyFlow; + private readonly FillFlowContainer keyFlow = new FillFlowContainer(); + + protected override Container Content => keyFlow; public new IReadOnlyList Children { @@ -22,12 +24,13 @@ namespace osu.Game.Screens.Play } public DefaultKeyCounterDisplay() + : base(typeof(DefaultKeyCounter)) { - KeyFlow.Direction = FillDirection.Horizontal; - KeyFlow.AutoSizeAxes = Axes.Both; - KeyFlow.Alpha = 0; + keyFlow.Direction = FillDirection.Horizontal; + keyFlow.AutoSizeAxes = Axes.Both; + keyFlow.Alpha = 0; - InternalChild = KeyFlow; + InternalChild = keyFlow; } protected override void Update() @@ -36,12 +39,22 @@ namespace osu.Game.Screens.Play // Don't use autosize as it will shrink to zero when KeyFlow is hidden. // In turn this can cause the display to be masked off screen and never become visible again. - Size = KeyFlow.Size; + Size = keyFlow.Size; + } + + public override void AddTrigger(KeyCounter.InputTrigger trigger) + { + DefaultKeyCounter key = new DefaultKeyCounter(trigger); + Add(key); + key.FadeTime = key_fade_time; + key.KeyDownTextColor = KeyDownTextColor; + key.KeyUpTextColor = KeyUpTextColor; } public override void Add(KeyCounter key) { base.Add(key); + DefaultKeyCounter defaultKey = (DefaultKeyCounter)key; defaultKey.FadeTime = key_fade_time; @@ -51,7 +64,7 @@ namespace osu.Game.Screens.Play protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. - KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); + keyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); private Color4 keyDownTextColor = Color4.DarkGray; diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 4bad6920e3..26bb6f1a22 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -21,7 +21,7 @@ namespace osu.Game.Screens.Play MinValue = 0 }; - public bool IsCounting { get; set; } = true; + public Bindable IsCounting { get; } = new BindableBool(true); public IBindable CountPresses => countPresses; @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play private void increment() { - if (!IsCounting) + if (!IsCounting.Value) return; countPresses.Value++; @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play private void decrement() { - if (!IsCounting) + if (!IsCounting.Value) return; countPresses.Value--; diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index d2b50ff73d..d1fbfe166d 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -2,9 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -15,22 +17,58 @@ namespace osu.Game.Screens.Play { public abstract partial class KeyCounterDisplay : Container { - protected readonly Bindable ConfigVisibility = new Bindable(); - - protected readonly FillFlowContainer KeyFlow = new FillFlowContainer(); - - protected override Container Content => KeyFlow; - /// /// Whether the key counter should be visible regardless of the configuration value. /// This is true by default, but can be changed. /// - public readonly Bindable AlwaysVisible = new Bindable(true); + public Bindable AlwaysVisible { get; } = new Bindable(true); + + public Bindable IsCounting { get; } = new BindableBool(true); + + public IReadOnlyList Triggers + { + get => Children.Select(c => c.Trigger).ToArray(); + set + { + Clear(); + value.ForEach(AddTrigger); + } + } + + protected readonly Bindable ConfigVisibility = new Bindable(); + + protected abstract void UpdateVisibility(); + + private Receptor? receptor; + + private readonly Type[] acceptedTypes; + + protected KeyCounterDisplay(params Type[] acceptedTypes) + { + this.acceptedTypes = acceptedTypes; + } + + public void SetReceptor(Receptor receptor) + { + if (this.receptor != null) + throw new InvalidOperationException("Cannot set a new receptor when one is already active"); + + this.receptor = receptor; + } + + public abstract void AddTrigger(KeyCounter.InputTrigger trigger); + + public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); + + private bool checkType(KeyCounter key) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(key)); public override void Add(KeyCounter key) { + if (!checkType(key)) + throw new InvalidOperationException($"{key.GetType()} is not a supported counter type. (hint: you may want to use {nameof(AddTrigger)} instead.)"); + base.Add(key); - key.IsCounting = IsCounting; + key.IsCounting.BindTo(IsCounting); } [BackgroundDependencyLoader] @@ -47,38 +85,10 @@ namespace osu.Game.Screens.Play ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true); } - private bool isCounting = true; - - public bool IsCounting - { - get => isCounting; - set - { - if (value == isCounting) return; - - isCounting = value; - foreach (var child in Children) - child.IsCounting = value; - } - } - - protected abstract void UpdateVisibility(); - public override bool HandleNonPositionalInput => receptor == null; + public override bool HandlePositionalInput => receptor == null; - private Receptor? receptor; - - public void SetReceptor(Receptor receptor) - { - if (this.receptor != null) - throw new InvalidOperationException("Cannot set a new receptor when one is already active"); - - this.receptor = receptor; - } - - public virtual KeyCounter CreateKeyCounter(KeyCounter.InputTrigger trigger) => new DefaultKeyCounter(trigger); - public partial class Receptor : Drawable { protected readonly KeyCounterDisplay Target; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 6dc4854e80..b141848a21 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -440,8 +440,11 @@ namespace osu.Game.Screens.Play }, KeyCounter = { + IsCounting = + { + Value = false + }, AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded }, - IsCounting = false }, Anchor = Anchor.Centre, Origin = Anchor.Centre @@ -481,7 +484,7 @@ namespace osu.Game.Screens.Play { updateGameplayState(); updatePauseOnFocusLostState(); - HUDOverlay.KeyCounter.IsCounting = !isBreakTime.NewValue; + HUDOverlay.KeyCounter.IsCounting.Value = !isBreakTime.NewValue; } private void updateGameplayState() From 8c94b77de18e4ce57edd57aa50db5848f4d8e60b Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 22 Feb 2023 15:03:44 +0000 Subject: [PATCH 0162/1400] refactor(InputTrigger): move out of KCD I love JetBrains Rider. --- .../TestSceneOsuTouchInput.cs | 2 +- .../Screens/Play/DefaultKeyCounterDisplay.cs | 2 +- osu.Game/Screens/Play/InputTrigger.cs | 23 +++++++++++++++++++ osu.Game/Screens/Play/KeyCounter.cs | 16 ------------- .../Screens/Play/KeyCounterActionTrigger.cs | 2 +- osu.Game/Screens/Play/KeyCounterDisplay.cs | 6 ++--- .../Screens/Play/KeyCounterKeyboardTrigger.cs | 2 +- .../Screens/Play/KeyCounterMouseTrigger.cs | 2 +- 8 files changed, 31 insertions(+), 24 deletions(-) create mode 100644 osu.Game/Screens/Play/InputTrigger.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 4cb017cc56..ec8fad9bf3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -579,7 +579,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void checkNotPressed(OsuAction action) => AddAssert($"Not pressing {action}", () => !osuInputManager.PressedActions.Contains(action)); private void checkPressed(OsuAction action) => AddAssert($"Is pressing {action}", () => osuInputManager.PressedActions.Contains(action)); - public partial class TestActionKeyCounterTrigger : KeyCounter.InputTrigger, IKeyBindingHandler + public partial class TestActionKeyCounterTrigger : InputTrigger, IKeyBindingHandler { public OsuAction Action { get; } diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs index 367eb483a0..10f5a3cfe0 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play Size = keyFlow.Size; } - public override void AddTrigger(KeyCounter.InputTrigger trigger) + public override void AddTrigger(InputTrigger trigger) { DefaultKeyCounter key = new DefaultKeyCounter(trigger); Add(key); diff --git a/osu.Game/Screens/Play/InputTrigger.cs b/osu.Game/Screens/Play/InputTrigger.cs new file mode 100644 index 0000000000..b8951b0f8e --- /dev/null +++ b/osu.Game/Screens/Play/InputTrigger.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; + +namespace osu.Game.Screens.Play +{ + public abstract partial class InputTrigger : Component + { + public event Action? OnActivate; + public event Action? OnDeactivate; + + protected InputTrigger(string name) + { + Name = name; + } + + protected void Activate(bool forwardPlayback = true) => OnActivate?.Invoke(forwardPlayback); + + protected void Deactivate(bool forwardPlayback = true) => OnDeactivate?.Invoke(forwardPlayback); + } +} diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 26bb6f1a22..7ee9c94f62 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -80,20 +79,5 @@ namespace osu.Game.Screens.Play Trigger.OnActivate -= Activate; Trigger.OnDeactivate -= Deactivate; } - - public abstract partial class InputTrigger : Component - { - public event Action? OnActivate; - public event Action? OnDeactivate; - - protected InputTrigger(string name) - { - Name = name; - } - - protected void Activate(bool forwardPlayback = true) => OnActivate?.Invoke(forwardPlayback); - - protected void Deactivate(bool forwardPlayback = true) => OnDeactivate?.Invoke(forwardPlayback); - } } } diff --git a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs index 8bb9bdc886..be0d259f85 100644 --- a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterActionTrigger.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Screens.Play { - public partial class KeyCounterActionTrigger : KeyCounter.InputTrigger + public partial class KeyCounterActionTrigger : InputTrigger where T : struct { public T Action { get; } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index d1fbfe166d..01686ae6de 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play public Bindable IsCounting { get; } = new BindableBool(true); - public IReadOnlyList Triggers + public IReadOnlyList Triggers { get => Children.Select(c => c.Trigger).ToArray(); set @@ -56,9 +56,9 @@ namespace osu.Game.Screens.Play this.receptor = receptor; } - public abstract void AddTrigger(KeyCounter.InputTrigger trigger); + public abstract void AddTrigger(InputTrigger trigger); - public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); + public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); private bool checkType(KeyCounter key) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(key)); diff --git a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs index 56c5ab0083..1d89c58fc3 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs @@ -8,7 +8,7 @@ using osuTK.Input; namespace osu.Game.Screens.Play { - public partial class KeyCounterKeyboardTrigger : KeyCounter.InputTrigger + public partial class KeyCounterKeyboardTrigger : InputTrigger { public Key Key { get; } diff --git a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs index 66890073a8..e710c6e33f 100644 --- a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs +++ b/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Screens.Play { - public partial class KeyCounterMouseTrigger : KeyCounter.InputTrigger + public partial class KeyCounterMouseTrigger : InputTrigger { public MouseButton Button { get; } From 6307b3948a2ace0140cdf9c43fe4c6b7cbe7f7db Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 22 Feb 2023 17:59:39 +0000 Subject: [PATCH 0163/1400] style: use Trigger initialisation --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 5405274cd0..12cd7e1be9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -17,21 +17,21 @@ namespace osu.Game.Tests.Visual.Gameplay { public TestSceneKeyCounter() { - DefaultKeyCounter testCounter; - KeyCounterDisplay kc = new DefaultKeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Children = new[] + Triggers = new InputTrigger[] { - testCounter = new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), - new DefaultKeyCounter(new KeyCounterKeyboardTrigger(Key.X)), - new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Left)), - new DefaultKeyCounter(new KeyCounterMouseTrigger(MouseButton.Right)), - }, + new KeyCounterKeyboardTrigger(Key.X), + new KeyCounterKeyboardTrigger(Key.X), + new KeyCounterMouseTrigger(MouseButton.Left), + new KeyCounterMouseTrigger(MouseButton.Right), + } }; + var testCounter = (DefaultKeyCounter)kc.Children.First(); + AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); From c48aceb055433f57bd00d885691d8a61e8317460 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Feb 2023 20:03:36 +0900 Subject: [PATCH 0164/1400] Fix undo history not being batched correctly for depth change operations --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 95b88b141f..02ede8c08b 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -566,6 +566,8 @@ namespace osu.Game.Overlays.SkinEditor if (getTarget(selectedTarget.Value) is not SkinComponentsContainer target) return; + changeHandler?.BeginChange(); + // Iterating by target components order ensures we maintain the same order across selected components, regardless // of the order they were selected in. foreach (var d in target.Components.ToArray()) @@ -579,6 +581,8 @@ namespace osu.Game.Overlays.SkinEditor SelectedComponents.Add(d); target.Add(d); } + + changeHandler?.EndChange(); } public void SendSelectionToBack() @@ -586,6 +590,8 @@ namespace osu.Game.Overlays.SkinEditor if (getTarget(selectedTarget.Value) is not SkinComponentsContainer target) return; + changeHandler?.BeginChange(); + foreach (var d in target.Components.ToArray()) { if (SelectedComponents.Contains(d)) @@ -594,6 +600,8 @@ namespace osu.Game.Overlays.SkinEditor target.Remove(d, false); target.Add(d); } + + changeHandler?.EndChange(); } #region Drag & drop import handling From ba345e559131e2c7c9dadc1237346c45883119e8 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Feb 2023 20:10:50 +0900 Subject: [PATCH 0165/1400] delete notify post when duplicate export --- osu.Game/Database/LegacyModelExporter.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 96104a68a0..c826b37689 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -60,7 +60,7 @@ namespace osu.Game.Database /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. /// /// - public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) + public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { // check if the model is being exporting already if (!exportingModels.Contains(model)) @@ -69,10 +69,7 @@ namespace osu.Game.Database } else { - PostNotification?.Invoke(new SimpleErrorNotification - { - Text = "File is being exported" - }); + // model is being exported return; } @@ -114,6 +111,8 @@ namespace osu.Game.Database exportingModels.Remove(model); } + + return success; } /// From 9e1eb50d9bf65390dcceec2835dc0e3d41e7083d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Feb 2023 20:20:54 +0900 Subject: [PATCH 0166/1400] use log --- osu.Game/Database/LegacyArchiveExporter.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index e5215e13a6..1af8c454c1 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; using System.Threading; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays.Notifications; @@ -12,6 +13,7 @@ using Realms; using SharpCompress.Common; using SharpCompress.Writers; using SharpCompress.Writers.Zip; +using Logger = osu.Framework.Logging.Logger; namespace osu.Game.Database { @@ -54,10 +56,7 @@ namespace osu.Game.Database // Only pop up once to prevent spam. if (!fileMissing) { - PostNotification?.Invoke(new SimpleErrorNotification - { - Text = "Some of your files are missing, they will not be included in the archive" - }); + Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); fileMissing = true; } } From dc3c1150b8401b4f4d49b1ecb6c8ba30663fe217 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Feb 2023 21:10:15 +0900 Subject: [PATCH 0167/1400] Set better defaults for `SkinBlueprint` transforms --- osu.Game/Overlays/SkinEditor/SkinBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinBlueprint.cs b/osu.Game/Overlays/SkinEditor/SkinBlueprint.cs index 034ca11c5c..c090878899 100644 --- a/osu.Game/Overlays/SkinEditor/SkinBlueprint.cs +++ b/osu.Game/Overlays/SkinEditor/SkinBlueprint.cs @@ -82,6 +82,7 @@ namespace osu.Game.Overlays.SkinEditor { Text = Item.GetType().Name, Font = OsuFont.Default.With(size: 10, weight: FontWeight.Bold), + Alpha = 0, Anchor = Anchor.BottomRight, Origin = Anchor.TopRight, }, @@ -99,7 +100,6 @@ namespace osu.Game.Overlays.SkinEditor base.LoadComplete(); updateSelectedState(); - this.FadeInFromZero(200, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) From 60bdae41b62a36ed48eb4b2a0978518d5c6a987e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Feb 2023 22:17:13 +0900 Subject: [PATCH 0168/1400] make static --- osu.Game/Database/LegacyModelExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index c826b37689..635af14e76 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } // Store the model being exporting. - private readonly List exportingModels = new List(); + private static readonly List exportingModels = new List(); /// /// Construct exporter. From 78201c464905b418379ce66013c19a04ef036946 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Feb 2023 22:17:35 +0900 Subject: [PATCH 0169/1400] log to database --- osu.Game/Database/LegacyModelExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 635af14e76..f14cae62e1 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -140,7 +140,7 @@ namespace osu.Game.Database if (t.IsFaulted) { notify.State = ProgressNotificationState.Cancelled; - Logger.Error(t.Exception, "An error occurred while exporting"); + Logger.Error(t.Exception, "An error occurred while exporting", LoggingTarget.Database); return false; } From 09e7c21b23a71c8df297c4037af11f1d45046052 Mon Sep 17 00:00:00 2001 From: Terochi Date: Fri, 24 Feb 2023 15:11:22 +0100 Subject: [PATCH 0170/1400] Implemented a more complex setting conversion logic + tests --- osu.Game.Tests/Mods/ModSettingsTest.cs | 42 ++++++++++++ .../TestSceneModSelectOverlay.cs | 67 +++++++++++++++---- osu.Game/Rulesets/Mods/Mod.cs | 38 ++++++++++- 3 files changed, 133 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index b9ea1f2567..99198f6bae 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -2,6 +2,9 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Bindables; +using osu.Framework.Localisation; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -32,5 +35,44 @@ namespace osu.Game.Tests.Mods Assert.That(((OsuModDoubleTime)original.Mods[0]).SpeedChange.Value, Is.EqualTo(2.0)); Assert.That(((OsuModDoubleTime)copy.Mods[0]).SpeedChange.Value, Is.EqualTo(1.5)); } + + [Test] + public void TestCopySharedSettingsOfDifferentType() + { + const double setting_change = 2.5; + + var osuMod = new TestNonMatchinSettingTypeOsuMod(); + var maniaMod = new TestNonMatchinSettingTypeManiaMod(); + + osuMod.TestSetting.Value = setting_change; + maniaMod.CopySharedSettings(osuMod); + osuMod.CopySharedSettings(maniaMod); + + Assert.That(maniaMod.TestSetting.IsDefault, "Value has been changed"); + Assert.That(osuMod.TestSetting.Value == setting_change); + } + + private class TestNonMatchinSettingTypeOsuMod : TestNonMatchinSettingTypeMod + { + public override string Acronym => "NMO"; + public override BindableNumber TestSetting { get; } = new BindableDouble(3.5); + } + + private class TestNonMatchinSettingTypeManiaMod : TestNonMatchinSettingTypeMod + { + public override string Acronym => "NMM"; + public override Bindable TestSetting { get; } = new BindableBool(true); + } + + private abstract class TestNonMatchinSettingTypeMod : Mod + { + public override string Name => "Non-matching setting type mod"; + public override LocalisableString Description => "Description"; + public override double ScoreMultiplier => 1; + public override ModType Type => ModType.Conversion; + + [SettingSource("Test setting")] + public abstract IBindable TestSetting { get; } + } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 7a46876737..a354a22fb7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -18,6 +18,7 @@ using osu.Game.Overlays.Mods; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -387,7 +388,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("change mod settings", () => { - var osuMod = (getMod() as OsuModDifficultyAdjust)!; + var osuMod = getMod(); + osuMod.ExtendedLimits.Value = true; osuMod.CircleSize.Value = setting_change; osuMod.DrainRate.Value = setting_change; @@ -400,23 +402,60 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("shared settings didn't change", () => { - var taikoMod = getMod() as TaikoModDifficultyAdjust; - return - taikoMod?.ExtendedLimits.Value == true && - taikoMod.DrainRate.Value == setting_change && - taikoMod.OverallDifficulty.Value == setting_change; + var taikoMod = getMod(); + + return taikoMod.ExtendedLimits.Value && + taikoMod.DrainRate.Value == setting_change && + taikoMod.OverallDifficulty.Value == setting_change; }); - AddAssert("non-shared settings at default", () => + AddAssert("non-shared settings unchanged", () => { - var taikoMod = getMod() as TaikoModDifficultyAdjust; - if (taikoMod == null) - return false; + var taikoMod = getMod(); - return taikoMod.ScrollSpeed.Value == taikoMod.ScrollSpeed.Default; + return taikoMod.ScrollSpeed.IsDefault; + }); + } + + [Test] + public void TestKeepSharedSettingsRatio() + { + const float setting_change = 1.8f; + + createScreen(); + changeRuleset(0); + + AddStep("select flashlight mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod()! }); + + changeRuleset(0); + AddAssert("ensure mod still selected", () => SelectedMods.Value.SingleOrDefault() is OsuModFlashlight); + + AddStep("change mod settings", () => + { + var osuMod = getMod(); + + // range <0.5 - 2> + osuMod.SizeMultiplier.Value = setting_change; }); - ModDifficultyAdjust getMod() => (SelectedMods.Value.Single() as ModDifficultyAdjust)!; + changeRuleset(3); + AddAssert("mania variant selected", () => SelectedMods.Value.SingleOrDefault() is ManiaModFlashlight); + + AddAssert("shared settings changed to closest ratio", () => + { + var maniaMod = getMod(); + + // range <0.5 - 3> + // converted value based on ratio = (setting_change - 0.5) / (2 - 0.5) * (3 - 0.5) + 0.5 = 2.66 + return maniaMod.SizeMultiplier.Value == 2.7f; // taking precision into account + }); + + AddAssert("other settings unchanged", () => + { + var maniaMod = getMod(); + + return maniaMod.ComboBasedSize.IsDefault; + }); } [Test] @@ -514,6 +553,8 @@ namespace osu.Game.Tests.Visual.UserInterface waitForColumnLoad(); AddAssert("unimplemented mod panel is filtered", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value); + + AddStep("disable panel filtering", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value = false); } [Test] @@ -629,6 +670,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert($"customisation toggle is {(active ? "" : "not ")}active", () => modSelectOverlay.CustomisationButton.AsNonNull().Active.Value == active); } + private T getMod() where T : Mod => (T)SelectedMods.Value.Single(); + private ModPanel getPanelForMod(Type modType) => modSelectOverlay.ChildrenOfType().Single(panel => panel.Mod.GetType() == modType); diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index bc588a5cd8..f6c0e851fd 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using AutoMapper.Internal; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -173,13 +174,46 @@ namespace osu.Game.Rulesets.Mods foreach (var (_, property) in this.GetSettingsSourceProperties()) { - var targetBindable = (IBindable)property.GetValue(this)!; + object targetSetting = property.GetValue(this)!; if (!oldSettings.TryGetValue(property.Name.ToSnakeCase(), out object? sourceSetting)) continue; - CopyAdjustedSetting(targetBindable, sourceSetting); + if (((IBindable)sourceSetting).IsDefault) + // keep at default value if the source is default + continue; + + Type? targetType = getGenericBaseType(targetSetting, typeof(BindableNumber<>)); + Type? sourceType = getGenericBaseType(sourceSetting, typeof(BindableNumber<>)); + + if (targetType == null || sourceType == null) + { + if (getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == + getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single()) + // change settings only if the type is the same + CopyAdjustedSetting((IBindable)targetSetting, sourceSetting); + + continue; + } + + double targetMin = getValue(targetSetting, nameof(IBindableNumber.MinValue)); + double targetMax = getValue(targetSetting, nameof(IBindableNumber.MaxValue)); + double sourceMin = getValue(sourceSetting, nameof(IBindableNumber.MinValue)); + double sourceMax = getValue(sourceSetting, nameof(IBindableNumber.MaxValue)); + double sourceValue = getValue(sourceSetting, nameof(IBindableNumber.Value)); + + // convert value to same ratio + double targetValue = (sourceValue - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin; + + targetType.GetProperty(nameof(IBindableNumber.Value))!.SetValue(targetSetting, + Convert.ChangeType(targetValue, targetType.GenericTypeArguments.Single())); } + + double getValue(object target, string name) => + Convert.ToDouble(target.GetType().GetProperty(name)!.GetValue(target)!); + + Type? getGenericBaseType(object target, Type genericType) => + target.GetType().GetTypeInheritance().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == genericType); } /// From dd9748a25cb3d29537b3abf01a382a9f2be2d7e9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 25 Feb 2023 01:21:37 +0900 Subject: [PATCH 0171/1400] Adjust DrawNodes to use UBOs --- .../UI/Cursor/CursorTrail.cs | 22 ++++++++++++-- .../TestSceneTriangleBorderShader.cs | 19 ++++++++++-- .../Backgrounds/TriangleBorderData.cs | 16 ++++++++++ osu.Game/Graphics/Backgrounds/Triangles.cs | 17 +++++++---- osu.Game/Graphics/Backgrounds/TrianglesV2.cs | 13 ++++++-- osu.Game/Graphics/Sprites/LogoAnimation.cs | 22 +++++++++++++- osu.Game/Rulesets/Mods/ModFlashlight.cs | 30 +++++++++++++++---- 7 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 osu.Game/Graphics/Backgrounds/TriangleBorderData.cs diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 9ecabd1d5e..a29faac5a0 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Vertices; using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Shaders.Types; using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Framework.Input.Events; @@ -255,15 +256,23 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Source.parts.CopyTo(parts, 0); } + private IUniformBuffer cursorTrailParameters; + public override void Draw(IRenderer renderer) { base.Draw(renderer); vertexBatch ??= renderer.CreateQuadBatch(max_sprites, 1); + cursorTrailParameters ??= renderer.CreateUniformBuffer(); + cursorTrailParameters.Data = cursorTrailParameters.Data with + { + FadeClock = time, + FadeExponent = fadeExponent + }; + shader.Bind(); - shader.GetUniform("g_FadeClock").UpdateValue(ref time); - shader.GetUniform("g_FadeExponent").UpdateValue(ref fadeExponent); + shader.BindUniformBlock("m_CursorTrailParameters", cursorTrailParameters); texture.Bind(); @@ -323,6 +332,15 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor base.Dispose(isDisposing); vertexBatch?.Dispose(); + cursorTrailParameters?.Dispose(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private record struct CursorTrailParameters + { + public UniformFloat FadeClock; + public UniformFloat FadeExponent; + private readonly UniformPadding8 pad1; } } diff --git a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs index 271642edd1..07427c242f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs @@ -9,6 +9,7 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Rendering; +using osu.Game.Graphics.Backgrounds; namespace osu.Game.Tests.Visual.Background { @@ -97,15 +98,29 @@ namespace osu.Game.Tests.Visual.Background texelSize = Source.texelSize; } + private IUniformBuffer? borderDataBuffer; + public override void Draw(IRenderer renderer) { - TextureShader.GetUniform("thickness").UpdateValue(ref thickness); - TextureShader.GetUniform("texelSize").UpdateValue(ref texelSize); + borderDataBuffer ??= renderer.CreateUniformBuffer(); + borderDataBuffer.Data = borderDataBuffer.Data with + { + Thickness = thickness, + TexelSize = texelSize + }; + + TextureShader.BindUniformBlock("m_BorderData", borderDataBuffer); base.Draw(renderer); } protected override bool CanDrawOpaqueInterior => false; + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + borderDataBuffer?.Dispose(); + } } } } diff --git a/osu.Game/Graphics/Backgrounds/TriangleBorderData.cs b/osu.Game/Graphics/Backgrounds/TriangleBorderData.cs new file mode 100644 index 0000000000..f4d327dc8e --- /dev/null +++ b/osu.Game/Graphics/Backgrounds/TriangleBorderData.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Runtime.InteropServices; +using osu.Framework.Graphics.Shaders.Types; + +namespace osu.Game.Graphics.Backgrounds +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public record struct TriangleBorderData + { + public UniformFloat Thickness; + public UniformFloat TexelSize; + private readonly UniformPadding8 pad1; + } +} diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 68ece56d8a..f3ebdd875a 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -284,6 +284,8 @@ namespace osu.Game.Graphics.Backgrounds parts.AddRange(Source.parts); } + private IUniformBuffer borderDataBuffer; + public override void Draw(IRenderer renderer) { base.Draw(renderer); @@ -294,14 +296,16 @@ namespace osu.Game.Graphics.Backgrounds vertexBatch = renderer.CreateQuadBatch(Source.AimCount, 1); } - // Due to triangles having various sizes we would need to set a different "texelSize" value for each of them, which is insanely expensive, thus we should use one single value. - // texelSize computed for an average triangle (size 100) will result in big triangles becoming blurry, so we may just use 0 for all of them. - // But we still need to specify at least something, because otherwise other shader usages will override this value. - float texelSize = 0f; + borderDataBuffer ??= renderer.CreateUniformBuffer(); + borderDataBuffer.Data = borderDataBuffer.Data with + { + Thickness = fill, + // Due to triangles having various sizes we would need to set a different "TexelSize" value for each of them, which is insanely expensive, thus we should use one single value. + // TexelSize computed for an average triangle (size 100) will result in big triangles becoming blurry, so we may just use 0 for all of them. + TexelSize = 0 + }; shader.Bind(); - shader.GetUniform("thickness").UpdateValue(ref fill); - shader.GetUniform("texelSize").UpdateValue(ref texelSize); foreach (TriangleParticle particle in parts) { @@ -352,6 +356,7 @@ namespace osu.Game.Graphics.Backgrounds base.Dispose(isDisposing); vertexBatch?.Dispose(); + borderDataBuffer?.Dispose(); } } diff --git a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs index 3bc8bb6df1..b108649ce4 100644 --- a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs +++ b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs @@ -227,6 +227,8 @@ namespace osu.Game.Graphics.Backgrounds parts.AddRange(Source.parts); } + private IUniformBuffer? borderDataBuffer; + public override void Draw(IRenderer renderer) { base.Draw(renderer); @@ -240,9 +242,15 @@ namespace osu.Game.Graphics.Backgrounds vertexBatch = renderer.CreateQuadBatch(Source.AimCount, 1); } + borderDataBuffer ??= renderer.CreateUniformBuffer(); + borderDataBuffer.Data = borderDataBuffer.Data with + { + Thickness = thickness, + TexelSize = texelSize + }; + shader.Bind(); - shader.GetUniform("thickness").UpdateValue(ref thickness); - shader.GetUniform("texelSize").UpdateValue(ref texelSize); + shader.BindUniformBlock("m_BorderData", borderDataBuffer); Vector2 relativeSize = Vector2.Divide(triangleSize, size); @@ -303,6 +311,7 @@ namespace osu.Game.Graphics.Backgrounds base.Dispose(isDisposing); vertexBatch?.Dispose(); + borderDataBuffer?.Dispose(); } } diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index e177cc604b..220f57e9fa 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -3,10 +3,12 @@ #nullable disable +using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Shaders.Types; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Sprites @@ -55,14 +57,32 @@ namespace osu.Game.Graphics.Sprites progress = source.animationProgress; } + private IUniformBuffer animationDataBuffer; + protected override void Blit(IRenderer renderer) { - TextureShader.GetUniform("progress").UpdateValue(ref progress); + animationDataBuffer ??= renderer.CreateUniformBuffer(); + animationDataBuffer.Data = animationDataBuffer.Data with { Progress = progress }; + + TextureShader.BindUniformBlock("m_AnimationData", animationDataBuffer); base.Blit(renderer); } protected override bool CanDrawOpaqueInterior => false; + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + animationDataBuffer?.Dispose(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private record struct AnimationData + { + public UniformFloat Progress; + private readonly UniformPadding12 pad1; + } } } } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 45fa55c7f2..d1446444bf 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -9,6 +10,7 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Rendering.Vertices; using osu.Framework.Graphics.Shaders; +using osu.Framework.Graphics.Shaders.Types; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Configuration; @@ -245,6 +247,8 @@ namespace osu.Game.Rulesets.Mods flashlightSmoothness = Source.flashlightSmoothness; } + private IUniformBuffer? flashlightParametersBuffer; + public override void Draw(IRenderer renderer) { base.Draw(renderer); @@ -259,12 +263,17 @@ namespace osu.Game.Rulesets.Mods }); } - shader.Bind(); + flashlightParametersBuffer ??= renderer.CreateUniformBuffer(); + flashlightParametersBuffer.Data = flashlightParametersBuffer.Data with + { + Position = flashlightPosition, + Size = flashlightSize, + Dim = flashlightDim, + Smoothness = flashlightSmoothness + }; - shader.GetUniform("flashlightPos").UpdateValue(ref flashlightPosition); - shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize); - shader.GetUniform("flashlightDim").UpdateValue(ref flashlightDim); - shader.GetUniform("flashlightSmoothness").UpdateValue(ref flashlightSmoothness); + shader.Bind(); + shader.BindUniformBlock("m_FlashlightParameters", flashlightParametersBuffer); renderer.DrawQuad(renderer.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: addAction); @@ -275,6 +284,17 @@ namespace osu.Game.Rulesets.Mods { base.Dispose(isDisposing); quadBatch?.Dispose(); + flashlightParametersBuffer?.Dispose(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private record struct FlashlightParameters + { + public UniformVector2 Position; + public UniformVector2 Size; + public UniformFloat Dim; + public UniformFloat Smoothness; + private readonly UniformPadding8 pad1; } } } From 069b77dd23ffc9aaa04ebd1995f9fd37f1a1c076 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 25 Feb 2023 02:15:56 +0900 Subject: [PATCH 0172/1400] Update language version --- osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 1 + osu.Game/osu.Game.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index bf776fe5dd..75656e2976 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -4,6 +4,7 @@ Library true click the circles. to the beat. + 10 diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 65ea301cbd..c5001cdc93 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -3,6 +3,7 @@ net6.0 Library true + 10 osu! From a44c9d10d77047669db8e67f474c4427f1afe4db Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 25 Feb 2023 02:18:40 +0900 Subject: [PATCH 0173/1400] Fix buffer not being bound --- osu.Game/Graphics/Backgrounds/Triangles.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index f3ebdd875a..5b7b94ff4c 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -306,6 +306,7 @@ namespace osu.Game.Graphics.Backgrounds }; shader.Bind(); + shader.BindUniformBlock("m_BorderData", borderDataBuffer); foreach (TriangleParticle particle in parts) { From a20e2685bee85872cadd858036f6938fb5375f71 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 25 Feb 2023 20:11:08 +0900 Subject: [PATCH 0174/1400] make static name fix --- osu.Game/Database/LegacyModelExporter.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index f14cae62e1..4ac48aaa09 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } // Store the model being exporting. - private static readonly List exportingModels = new List(); + private static readonly List exporting_models = new List(); /// /// Construct exporter. @@ -63,14 +63,14 @@ namespace osu.Game.Database public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) { // check if the model is being exporting already - if (!exportingModels.Contains(model)) + if (!exporting_models.Contains(model)) { - exportingModels.Add(model); + exporting_models.Add(model); } else { // model is being exported - return; + return false; } string itemFilename = GetFilename(model).GetValidFilename(); @@ -109,7 +109,7 @@ namespace osu.Game.Database exportStorage.Delete(filename); } - exportingModels.Remove(model); + exporting_models.Remove(model); } return success; From fdf95446882f67ab27621a70ce05095b8ee25216 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 26 Feb 2023 15:28:10 +0900 Subject: [PATCH 0175/1400] cancel handle --- osu.Game/Database/LegacyModelExporter.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 4ac48aaa09..b47e0a9913 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -137,6 +137,12 @@ namespace osu.Game.Database }); }, cancellationToken).ContinueWith(t => { + if (cancellationToken.IsCancellationRequested) + { + notify.State = ProgressNotificationState.Cancelled; + return false; + } + if (t.IsFaulted) { notify.State = ProgressNotificationState.Cancelled; @@ -144,10 +150,8 @@ namespace osu.Game.Database return false; } - notify.CompletionText = "Export Complete, Click to open the folder"; - notify.State = ProgressNotificationState.Completed; return true; - }, cancellationToken); + }, CancellationToken.None); } /// From e8092bff4686eb4491c4751cb5d927f4f74a1515 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 26 Feb 2023 15:28:24 +0900 Subject: [PATCH 0176/1400] logic fix? --- osu.Game/Database/LegacyModelExporter.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index b47e0a9913..06e4497e81 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -87,7 +87,6 @@ namespace osu.Game.Database Text = "Exporting...", CompletionText = "Export completed" }; - notification.CompletionClickAction += () => exportStorage.PresentFileExternally(filename); PostNotification?.Invoke(notification); try @@ -101,16 +100,20 @@ namespace osu.Game.Database { success = false; } - finally - { - // cleanup if export is failed or canceled. - if (!success) - { - exportStorage.Delete(filename); - } - exporting_models.Remove(model); + // cleanup if export is failed or canceled. + if (!success) + { + exportStorage.Delete(filename); } + else + { + notification.CompletionText = "Export Complete, Click to open the folder"; + notification.CompletionClickAction = () => exportStorage.PresentFileExternally(filename); + notification.State = ProgressNotificationState.Completed; + } + + exporting_models.Remove(model); return success; } From 1d5c87039eb42bf4fb342e8ced0e5fbcba61d535 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 26 Feb 2023 15:28:43 +0900 Subject: [PATCH 0177/1400] typo --- osu.Game/Database/LegacyModelExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 06e4497e81..6f2fe90957 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -121,7 +121,7 @@ namespace osu.Game.Database /// /// Export model to stream. /// - /// The medel which have . + /// The model which have . /// The stream to export. /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. From a705698ab64c7cfe63c82f7be048ed03de54aed8 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 26 Feb 2023 21:13:05 +0900 Subject: [PATCH 0178/1400] beatmapset that already deletePending should not be fetched --- osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs index 8908163646..8ee2cc6241 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs @@ -24,6 +24,6 @@ namespace osu.Game.Scoring.Legacy } protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId)?.CreateInstance(); - protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); + protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash && !b.BeatmapSet.DeletePending)); } } From ff0d1aa9f704560a96f6a3f1d048d44f70e33af8 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 26 Feb 2023 20:38:50 +0100 Subject: [PATCH 0179/1400] Make reverting changes to a given skin into a "dangerous action" --- osu.Game/Localisation/SkinEditorStrings.cs | 12 +++++++- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 32 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/SkinEditorStrings.cs b/osu.Game/Localisation/SkinEditorStrings.cs index 5cf2e5b5c5..029d50df32 100644 --- a/osu.Game/Localisation/SkinEditorStrings.cs +++ b/osu.Game/Localisation/SkinEditorStrings.cs @@ -42,7 +42,17 @@ namespace osu.Game.Localisation /// /// "Currently editing" /// - public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), "Currently editing"); + public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), @"Currently editing"); + + /// + /// "Revert?" + /// + public static LocalisableString Revert => new TranslatableString(getKey(@"revert"), @"Revert?"); + + /// + /// "The skin will return to the state it was in upon import" + /// + public static LocalisableString ResetDialogue => new TranslatableString(getKey(@"the_skin_will_return_to"), @"The skin will return to the state it was in upon import"); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 9d470f58f1..936dc7fa84 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -12,11 +12,13 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; +using web = osu.Game.Resources.Localisation.Web; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Graphics; @@ -24,6 +26,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; +using osu.Game.Overlays.Dialog; using osu.Game.Overlays.OSD; using osu.Game.Overlays.Settings; using osu.Game.Screens.Edit; @@ -97,6 +100,9 @@ namespace osu.Game.Overlays.SkinEditor [Resolved] private OnScreenDisplay? onScreenDisplay { get; set; } + [Resolved] + private IDialogOverlay? dialogOverlay { get; set; } + public SkinEditor() { } @@ -148,7 +154,7 @@ namespace osu.Game.Overlays.SkinEditor Items = new[] { new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), - new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, revert), + new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new ResetConfirmDialog(revert))), new EditorMenuItemSpacer(), new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), }, @@ -625,6 +631,30 @@ namespace osu.Game.Overlays.SkinEditor } } + public partial class ResetConfirmDialog : PopupDialog + { + public ResetConfirmDialog(Action reset) + { + HeaderText = SkinEditorStrings.Revert; + BodyText = SkinEditorStrings.ResetDialogue; + + Icon = FontAwesome.Solid.ExclamationTriangle; + + Buttons = new PopupDialogButton[] + { + new PopupDialogDangerousButton + { + Text = BeatmapOverlayStrings.UserContentConfirmButtonText, + Action = reset + }, + new PopupDialogCancelButton + { + Text = web.CommonStrings.ButtonsCancel, + }, + }; + } + } + #region Delegation of IEditorChangeHandler public event Action? OnStateChange From d98d330da20e2bced3a4d753f40c6a50f614f926 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Feb 2023 14:30:46 -0800 Subject: [PATCH 0180/1400] Add expected behavior test for scroll back to previous position --- .../TestSceneOverlayScrollContainer.cs | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs index 926bc01aea..ade950e2d5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs @@ -61,6 +61,18 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("scroll to 500", () => scroll.ScrollTo(500)); AddUntilStep("scrolled to 500", () => Precision.AlmostEquals(scroll.Current, 500, 0.1f)); AddAssert("button is visible", () => scroll.Button.State == Visibility.Visible); + + AddStep("click button", () => + { + InputManager.MoveMouseTo(scroll.Button); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("button is visible", () => scroll.Button.State == Visibility.Visible); + + AddStep("user scroll down by 1", () => InputManager.ScrollVerticalBy(-1)); + + AddAssert("button is hidden", () => scroll.Button.State == Visibility.Hidden); } [Test] @@ -71,6 +83,10 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("invoke action", () => scroll.Button.Action.Invoke()); AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f)); + + AddStep("invoke action", () => scroll.Button.Action.Invoke()); + + AddAssert("scrolled to end", () => scroll.IsScrolledToEnd()); } [Test] @@ -85,6 +101,14 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddUntilStep("scrolled back to start", () => Precision.AlmostEquals(scroll.Current, 0, 0.1f)); + + AddStep("click button", () => + { + InputManager.MoveMouseTo(scroll.Button); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("scrolled to end", () => scroll.IsScrolledToEnd()); } [Test] @@ -97,7 +121,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("hover button", () => InputManager.MoveMouseTo(scroll.Button)); AddRepeatStep("click button", () => InputManager.Click(MouseButton.Left), 3); - AddAssert("invocation count is 1", () => invocationCount == 1); + AddAssert("invocation count is 3", () => invocationCount == 3); } private partial class TestScrollContainer : OverlayScrollContainer From dc00905f8df0b24f974315a7efdac099373f09eb Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Feb 2023 14:38:51 -0800 Subject: [PATCH 0181/1400] Add ability to scroll back to previous position after scrolling to top via button on overlays --- osu.Game/Overlays/OverlayScrollContainer.cs | 50 +++++++++++++++++---- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 5bd7f014a9..8176ddb370 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -30,16 +31,20 @@ namespace osu.Game.Overlays /// private const int button_scroll_position = 200; - protected readonly ScrollToTopButton Button; + protected ScrollToTopButton Button; - public OverlayScrollContainer() + private readonly Bindable lastScrollTarget = new Bindable(); + + [BackgroundDependencyLoader] + private void load() { AddInternal(Button = new ScrollToTopButton { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(20), - Action = scrollToTop + Action = scrollBack, + LastScrollTarget = { BindTarget = lastScrollTarget } }); } @@ -53,13 +58,28 @@ namespace osu.Game.Overlays return; } - Button.State = Target > button_scroll_position ? Visibility.Visible : Visibility.Hidden; + Button.State = Target > button_scroll_position || lastScrollTarget.Value != null ? Visibility.Visible : Visibility.Hidden; } - private void scrollToTop() + protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default) { - ScrollToStart(); - Button.State = Visibility.Hidden; + base.OnUserScroll(value, animated, distanceDecay); + + lastScrollTarget.Value = null; + } + + private void scrollBack() + { + if (lastScrollTarget.Value == null) + { + lastScrollTarget.Value = Target; + ScrollToStart(); + } + else + { + ScrollTo(lastScrollTarget.Value.Value); + lastScrollTarget.Value = null; + } } public partial class ScrollToTopButton : OsuHoverContainer @@ -88,6 +108,9 @@ namespace osu.Game.Overlays private readonly Container content; private readonly Box background; + private readonly SpriteIcon spriteIcon; + + public Bindable LastScrollTarget = new Bindable(); public ScrollToTopButton() : base(HoverSampleSet.ScrollToTop) @@ -113,7 +136,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both }, - new SpriteIcon + spriteIcon = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -134,6 +157,17 @@ namespace osu.Game.Overlays flashColour = colourProvider.Light1; } + protected override void LoadComplete() + { + base.LoadComplete(); + + LastScrollTarget.BindValueChanged(target => + { + spriteIcon.RotateTo(target.NewValue != null ? 180 : 0, fade_duration, Easing.OutQuint); + TooltipText = target.NewValue != null ? CommonStrings.ButtonsBackToPrevious : CommonStrings.ButtonsBackToTop; + }, true); + } + protected override bool OnClick(ClickEvent e) { background.FlashColour(flashColour, 800, Easing.OutQuint); From fa710ae1b00dd9f618e481271b25aa2df5d558a4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Feb 2023 14:39:34 -0800 Subject: [PATCH 0182/1400] Rename `ScrollToTopButton` to `ScrollBackButton` --- .../UserInterface/TestSceneOverlayScrollContainer.cs | 2 +- osu.Game/Overlays/OverlayScrollContainer.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs index ade950e2d5..77e7178c9e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayScrollContainer.cs @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.UserInterface private partial class TestScrollContainer : OverlayScrollContainer { - public new ScrollToTopButton Button => base.Button; + public new ScrollBackButton Button => base.Button; } } } diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 8176ddb370..9752e04f44 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -22,23 +22,23 @@ using osuTK.Graphics; namespace osu.Game.Overlays { /// - /// which provides . Mostly used in . + /// which provides . Mostly used in . /// public partial class OverlayScrollContainer : UserTrackingScrollContainer { /// - /// Scroll position at which the will be shown. + /// Scroll position at which the will be shown. /// private const int button_scroll_position = 200; - protected ScrollToTopButton Button; + protected ScrollBackButton Button; private readonly Bindable lastScrollTarget = new Bindable(); [BackgroundDependencyLoader] private void load() { - AddInternal(Button = new ScrollToTopButton + AddInternal(Button = new ScrollBackButton { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, @@ -82,7 +82,7 @@ namespace osu.Game.Overlays } } - public partial class ScrollToTopButton : OsuHoverContainer + public partial class ScrollBackButton : OsuHoverContainer { private const int fade_duration = 500; @@ -112,7 +112,7 @@ namespace osu.Game.Overlays public Bindable LastScrollTarget = new Bindable(); - public ScrollToTopButton() + public ScrollBackButton() : base(HoverSampleSet.ScrollToTop) { Size = new Vector2(50); From 2b9d13cfee0e3c7fc46a2bf9d25077e75e01f02d Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 26 Feb 2023 20:58:20 -0300 Subject: [PATCH 0183/1400] Add group badges to list view --- .../Visual/Online/TestSceneFriendDisplay.cs | 17 +++++++++++++++-- .../Profile/Header/Components/GroupBadgeFlow.cs | 6 ++++++ osu.Game/Users/ExtendedUserPanel.cs | 8 ++++++++ osu.Game/Users/UserListPanel.cs | 5 +++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs index 7925b252b6..5028a532b7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneFriendDisplay.cs @@ -56,7 +56,13 @@ namespace osu.Game.Tests.Visual.Online IsOnline = true, Statistics = new UserStatistics { GlobalRank = 1111 }, CountryCode = CountryCode.JP, - CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" + CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c6.jpg", + IsSupporter = true, + SupportLevel = 1, + Groups = new[] + { + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" } + } }, new APIUser { @@ -68,6 +74,11 @@ namespace osu.Game.Tests.Visual.Online CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", IsSupporter = true, SupportLevel = 3, + Groups = new[] + { + new APIUserGroup { Colour = "#0066FF", ShortName = "PPY", Name = "peppy" }, + new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" } + } }, new APIUser { @@ -76,7 +87,9 @@ namespace osu.Game.Tests.Visual.Online CountryCode = CountryCode.BY, CoverUrl = "https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg", IsOnline = false, - LastVisit = DateTimeOffset.Now + LastVisit = DateTimeOffset.Now, + IsSupporter = true, + SupportLevel = 2 } }; } diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs index 33b3de94db..2498543b11 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs @@ -25,8 +25,14 @@ namespace osu.Game.Overlays.Profile.Header.Components Clear(true); if (user.NewValue?.Groups != null) + { AddRange(user.NewValue.Groups.Select(g => new GroupBadge(g))); + Show(); + } + else + Hide(); }); + } } } diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index 3c1b68f9ef..af4da22906 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -13,6 +13,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users.Drawables; using osu.Framework.Input.Events; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile.Header.Components; namespace osu.Game.Users { @@ -97,6 +98,13 @@ namespace osu.Game.Users return statusContainer; } + protected FillFlowContainer CreateGroupBadges() + { + var groupBadgeFlow = new GroupBadgeFlow(); + groupBadgeFlow.User.Value = User; + return groupBadgeFlow; + } + private void displayStatus(UserStatus status, UserActivity activity = null) { if (status != null) diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index bbd3c60a33..ebe58c2b93 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.cs @@ -67,6 +67,11 @@ namespace osu.Game.Users { username.Anchor = Anchor.CentreLeft; username.Origin = Anchor.CentreLeft; + }), + CreateGroupBadges().With(badges => + { + badges.Anchor = Anchor.CentreLeft; + badges.Origin = Anchor.CentreLeft; }) } }, From d722e09b2cc2840edfc540e9b52de00370930fe3 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Sun, 26 Feb 2023 21:05:41 -0300 Subject: [PATCH 0184/1400] oops --- osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs index 2498543b11..4d4b16d7f5 100644 --- a/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs +++ b/osu.Game/Overlays/Profile/Header/Components/GroupBadgeFlow.cs @@ -32,7 +32,6 @@ namespace osu.Game.Overlays.Profile.Header.Components else Hide(); }); - } } } From 17a05de107f15a3336b3410ce87c4c276e22f2ac Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 13 Feb 2023 21:25:52 +0000 Subject: [PATCH 0185/1400] Initial Taiko single tap implementation (still needs code to allow for Strong hits) --- .../Mods/InputBlockingMod.cs | 131 ++++++++++++++++++ .../Mods/TaikoModSingleTap.cs | 16 +++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 + 3 files changed, 148 insertions(+) create mode 100644 osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs create mode 100644 osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs diff --git a/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs new file mode 100644 index 0000000000..c815d62336 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs @@ -0,0 +1,131 @@ +// 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; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; +using osu.Game.Utils; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public abstract partial class InputBlockingMod : Mod, IApplicableToDrawableRuleset, IUpdatableByPlayfield + { + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) }; + public override ModType Type => ModType.Conversion; + + private const double flash_duration = 1000; + + private DrawableRuleset ruleset = null!; + + protected TaikoAction? LastAcceptedDonAction { get; private set; } + protected TaikoAction? LastAcceptedKatAction { get; private set; } + + /// + /// A tracker for periods where alternate should not be forced (i.e. non-gameplay periods). + /// + /// + /// This is different from in that the periods here end strictly at the first object after the break, rather than the break's end time. + /// + private PeriodTracker nonGameplayPeriods = null!; + + private IFrameStableClock gameplayClock = null!; + + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) + { + ruleset = drawableRuleset; + drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this)); + + var periods = new List(); + + if (drawableRuleset.Objects.Any()) + { + periods.Add(new Period(int.MinValue, getValidJudgementTime(ruleset.Objects.First()) - 1)); + + foreach (BreakPeriod b in drawableRuleset.Beatmap.Breaks) + periods.Add(new Period(b.StartTime, getValidJudgementTime(ruleset.Objects.First(h => h.StartTime >= b.EndTime)) - 1)); + + static double getValidJudgementTime(HitObject hitObject) => hitObject.StartTime - hitObject.HitWindows.WindowFor(HitResult.Meh); + } + + nonGameplayPeriods = new PeriodTracker(periods); + + gameplayClock = drawableRuleset.FrameStableClock; + } + + public void Update(Playfield playfield) + { + if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) + { + if (LastAcceptedDonAction != null) + LastAcceptedDonAction = null; + + if (LastAcceptedKatAction != null) + LastAcceptedKatAction = null; + } + } + + protected abstract bool CheckValidNewAction(TaikoAction action); + + private bool checkCorrectAction(TaikoAction action) + { + if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) + return true; + + switch (action) + { + case TaikoAction.LeftCentre: + case TaikoAction.RightCentre: + case TaikoAction.LeftRim: + case TaikoAction.RightRim: + break; + + // Any action which is not left or right button should be ignored. + default: + return true; + } + + if (CheckValidNewAction(action)) + { + if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) + LastAcceptedDonAction = action; + if (action == TaikoAction.LeftRim || action == TaikoAction.RightRim) + LastAcceptedKatAction = action; + return true; + } + + //ruleset.Cursor.FlashColour(Colour4.Red, flash_duration, Easing.OutQuint); + return false; + } + + private partial class InputInterceptor : Component, IKeyBindingHandler + { + private readonly InputBlockingMod mod; + + public InputInterceptor(InputBlockingMod mod) + { + this.mod = mod; + } + + public bool OnPressed(KeyBindingPressEvent e) + // if the pressed action is incorrect, block it from reaching gameplay. + => !mod.checkCorrectAction(e.Action); + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs new file mode 100644 index 0000000000..20c37fcb71 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModSingleTap : InputBlockingMod + { + public override string Name => @"Single Tap"; + public override string Acronym => @"SG"; + public override LocalisableString Description => @"You must only use one key!"; + + protected override bool CheckValidNewAction(TaikoAction action) => LastAcceptedDonAction == null || LastAcceptedDonAction == action || LastAcceptedKatAction == null || LastAcceptedKatAction == action; + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 4f435e73b3..a35fdb890d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -158,6 +158,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModDifficultyAdjust(), new TaikoModClassic(), new TaikoModSwap(), + new TaikoModSingleTap(), }; case ModType.Automation: From 715df42a690ca1d33792f8be5b1d0e860c700d77 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Sun, 26 Feb 2023 22:22:45 +0000 Subject: [PATCH 0186/1400] Strong hits are now allowed to be hit --- osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs index c815d62336..7613ce7c67 100644 --- a/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs @@ -15,8 +15,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Utils; -using osu.Game.Rulesets.Taiko.Mods; -using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Taiko.UI; namespace osu.Game.Rulesets.Taiko.Mods { @@ -30,6 +29,8 @@ namespace osu.Game.Rulesets.Taiko.Mods private DrawableRuleset ruleset = null!; + private TaikoPlayfield playfield { get; set; } = null!; + protected TaikoAction? LastAcceptedDonAction { get; private set; } protected TaikoAction? LastAcceptedKatAction { get; private set; } @@ -46,6 +47,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { ruleset = drawableRuleset; + playfield = (TaikoPlayfield)ruleset.Playfield; drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this)); var periods = new List(); @@ -97,6 +99,10 @@ namespace osu.Game.Rulesets.Taiko.Mods return true; } + // If next hit object is strong, allow usage of all actions + if (playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true)?.HitObject is TaikoStrongableHitObject hitObject && hitObject.IsStrong) + return true; + if (CheckValidNewAction(action)) { if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) @@ -106,7 +112,6 @@ namespace osu.Game.Rulesets.Taiko.Mods return true; } - //ruleset.Cursor.FlashColour(Colour4.Red, flash_duration, Easing.OutQuint); return false; } From b883c6af34a7601023d7fe84c37cd3ae8f96d652 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 10:30:57 +0000 Subject: [PATCH 0187/1400] Renamed all instances of Taiko's InputBlockingMod to TaikoInputBlockingMod --- .../Mods/{InputBlockingMod.cs => TaikoInputBlockingMod.cs} | 6 +++--- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game.Rulesets.Taiko/Mods/{InputBlockingMod.cs => TaikoInputBlockingMod.cs} (95%) diff --git a/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs similarity index 95% rename from osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs rename to osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index 7613ce7c67..a843e99671 100644 --- a/osu.Game.Rulesets.Taiko/Mods/InputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -19,7 +19,7 @@ using osu.Game.Rulesets.Taiko.UI; namespace osu.Game.Rulesets.Taiko.Mods { - public abstract partial class InputBlockingMod : Mod, IApplicableToDrawableRuleset, IUpdatableByPlayfield + public abstract partial class TaikoInputBlockingMod : Mod, IApplicableToDrawableRuleset, IUpdatableByPlayfield { public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) }; @@ -117,9 +117,9 @@ namespace osu.Game.Rulesets.Taiko.Mods private partial class InputInterceptor : Component, IKeyBindingHandler { - private readonly InputBlockingMod mod; + private readonly TaikoInputBlockingMod mod; - public InputInterceptor(InputBlockingMod mod) + public InputInterceptor(TaikoInputBlockingMod mod) { this.mod = mod; } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 20c37fcb71..57e041f151 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -5,7 +5,7 @@ using osu.Framework.Localisation; namespace osu.Game.Rulesets.Taiko.Mods { - public class TaikoModSingleTap : InputBlockingMod + public class TaikoModSingleTap : TaikoInputBlockingMod { public override string Name => @"Single Tap"; public override string Acronym => @"SG"; From f2cada4584db82428ebcee47914084fc4bdad7e7 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 12:22:38 +0000 Subject: [PATCH 0188/1400] Strong drumrolls no longer allow all actions to be used --- osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index a843e99671..fe9f190d91 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -99,8 +99,10 @@ namespace osu.Game.Rulesets.Taiko.Mods return true; } - // If next hit object is strong, allow usage of all actions - if (playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true)?.HitObject is TaikoStrongableHitObject hitObject && hitObject.IsStrong) + // If next hit object is strong, allow usage of all actions. Strong drumrolls are ignored in this check. + if (playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true)?.HitObject is TaikoStrongableHitObject hitObject + && hitObject.IsStrong + && hitObject as DrumRoll == null) return true; if (CheckValidNewAction(action)) From 12b983495c9883ca0fd691f95ec93143a7688096 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 13:40:55 +0000 Subject: [PATCH 0189/1400] Fixed issues caused by branch being stale --- osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs | 6 +++--- osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index fe9f190d91..eecb8c0bbd 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Mods private const double flash_duration = 1000; - private DrawableRuleset ruleset = null!; + private DrawableTaikoRuleset ruleset = null!; private TaikoPlayfield playfield { get; set; } = null!; @@ -46,9 +46,9 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - ruleset = drawableRuleset; + ruleset = (DrawableTaikoRuleset)drawableRuleset; + ruleset.InputManager.Add(new InputInterceptor(this)); playfield = (TaikoPlayfield)ruleset.Playfield; - drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this)); var periods = new List(); diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 40203440c5..5390d3b138 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Taiko.UI public readonly BindableBool LockPlayfieldMaxAspect = new BindableBool(true); + public TaikoInputManager InputManager { get; private set; } + protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; protected override bool UserScrollSpeedAdjustment => false; @@ -93,7 +95,7 @@ namespace osu.Game.Rulesets.Taiko.UI LockPlayfieldMaxAspect = { BindTarget = LockPlayfieldMaxAspect } }; - protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateInputManager() => InputManager = new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(); From dd9194b976089afc985589fa3100338b896e1596 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 13:58:40 +0000 Subject: [PATCH 0190/1400] Code formatting fix --- osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index eecb8c0bbd..63bc156d2d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -101,8 +101,8 @@ namespace osu.Game.Rulesets.Taiko.Mods // If next hit object is strong, allow usage of all actions. Strong drumrolls are ignored in this check. if (playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true)?.HitObject is TaikoStrongableHitObject hitObject - && hitObject.IsStrong - && hitObject as DrumRoll == null) + && hitObject.IsStrong + && hitObject as DrumRoll == null) return true; if (CheckValidNewAction(action)) From d823faed081db916e967747ac0076bb631e8c0d1 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 14:33:47 +0000 Subject: [PATCH 0191/1400] Remove unused `flash_duration` const --- osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index 63bc156d2d..5512a7d775 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -25,8 +25,6 @@ namespace osu.Game.Rulesets.Taiko.Mods public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) }; public override ModType Type => ModType.Conversion; - private const double flash_duration = 1000; - private DrawableTaikoRuleset ruleset = null!; private TaikoPlayfield playfield { get; set; } = null!; From 12a2037086c8878173f85c8af60a14dad0fec538 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 14:39:12 +0000 Subject: [PATCH 0192/1400] Removed useless TaikoAction check from TaikoInputBlockingMod --- .../Mods/TaikoInputBlockingMod.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index 5512a7d775..f437d53b93 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -84,19 +84,6 @@ namespace osu.Game.Rulesets.Taiko.Mods if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) return true; - switch (action) - { - case TaikoAction.LeftCentre: - case TaikoAction.RightCentre: - case TaikoAction.LeftRim: - case TaikoAction.RightRim: - break; - - // Any action which is not left or right button should be ignored. - default: - return true; - } - // If next hit object is strong, allow usage of all actions. Strong drumrolls are ignored in this check. if (playfield.HitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true)?.HitObject is TaikoStrongableHitObject hitObject && hitObject.IsStrong From bf1897a98fc5d215c9c75a1faffba4d853bf4b9e Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 27 Feb 2023 16:08:14 +0100 Subject: [PATCH 0193/1400] Adjust warning text slightly. --- osu.Game/Localisation/SkinEditorStrings.cs | 4 ++-- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Localisation/SkinEditorStrings.cs b/osu.Game/Localisation/SkinEditorStrings.cs index 029d50df32..b83a105c14 100644 --- a/osu.Game/Localisation/SkinEditorStrings.cs +++ b/osu.Game/Localisation/SkinEditorStrings.cs @@ -45,9 +45,9 @@ namespace osu.Game.Localisation public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), @"Currently editing"); /// - /// "Revert?" + /// "Revert to default?" /// - public static LocalisableString Revert => new TranslatableString(getKey(@"revert"), @"Revert?"); + public static LocalisableString RevertToDefault => new TranslatableString(getKey(@"revert_to_default"), @"Revert to default?"); /// /// "The skin will return to the state it was in upon import" diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 936dc7fa84..7661abc551 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -635,7 +635,7 @@ namespace osu.Game.Overlays.SkinEditor { public ResetConfirmDialog(Action reset) { - HeaderText = SkinEditorStrings.Revert; + HeaderText = SkinEditorStrings.RevertToDefault; BodyText = SkinEditorStrings.ResetDialogue; Icon = FontAwesome.Solid.ExclamationTriangle; From 25ef1f199d64c32760ad694826970e90a74761f3 Mon Sep 17 00:00:00 2001 From: OpenSauce <48618519+OpenSauce04@users.noreply.github.com> Date: Mon, 27 Feb 2023 15:22:06 +0000 Subject: [PATCH 0194/1400] Update description for Taiko Single Tap mod --- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 57e041f151..666e550c93 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override string Name => @"Single Tap"; public override string Acronym => @"SG"; - public override LocalisableString Description => @"You must only use one key!"; + public override LocalisableString Description => @"One key for dons, one key for kats."; protected override bool CheckValidNewAction(TaikoAction action) => LastAcceptedDonAction == null || LastAcceptedDonAction == action || LastAcceptedKatAction == null || LastAcceptedKatAction == action; } From 8d747f240220e98cb40a9edd567f6778c31115e0 Mon Sep 17 00:00:00 2001 From: OpenSauce <48618519+OpenSauce04@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:06:33 +0000 Subject: [PATCH 0195/1400] Fixed grammar mistake in Taiko Relax mod description --- osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs index d1e9ab1428..69a98f8372 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModRelax : ModRelax { - public override LocalisableString Description => @"No ninja-like spinners, demanding drumrolls or unexpected katu's."; + public override LocalisableString Description => @"No ninja-like spinners, demanding drumrolls or unexpected katus."; } } From 1239de6f41fd36b0fca8d3e41708e0f8095d30fd Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 27 Feb 2023 21:34:07 +0100 Subject: [PATCH 0196/1400] Upper case web `using` alias --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 7661abc551..53669e9f9c 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -18,7 +18,7 @@ using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Localisation; -using web = osu.Game.Resources.Localisation.Web; +using Web = osu.Game.Resources.Localisation.Web; using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Graphics; @@ -153,7 +153,7 @@ namespace osu.Game.Overlays.SkinEditor { Items = new[] { - new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), + new EditorMenuItem(Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new ResetConfirmDialog(revert))), new EditorMenuItemSpacer(), new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), @@ -649,7 +649,7 @@ namespace osu.Game.Overlays.SkinEditor }, new PopupDialogCancelButton { - Text = web.CommonStrings.ButtonsCancel, + Text = Web.CommonStrings.ButtonsCancel, }, }; } From 00a00ead225c8426e83582a88969cb2e39418ebc Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 27 Feb 2023 21:50:27 +0100 Subject: [PATCH 0197/1400] Make `ResetConfirmDialog` inherit from `DeleteConfirmationDialog` --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 53669e9f9c..bab5344e1e 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -631,7 +631,7 @@ namespace osu.Game.Overlays.SkinEditor } } - public partial class ResetConfirmDialog : PopupDialog + public partial class ResetConfirmDialog : DeleteConfirmationDialog { public ResetConfirmDialog(Action reset) { From 90227a64966383e7a313132d339c84c434ad8be0 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Mon, 27 Feb 2023 21:57:59 +0100 Subject: [PATCH 0198/1400] Rename `DeleteConfirmationDialog.cs` into `DangerousActionDialog.cs` --- osu.Game/Collections/DeleteCollectionDialog.cs | 2 +- .../{DeleteConfirmationDialog.cs => DangerousActionDialog.cs} | 4 ++-- osu.Game/Overlays/Mods/DeleteModPresetDialog.cs | 2 +- .../Sections/Maintenance/MassDeleteConfirmationDialog.cs | 2 +- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 2 +- osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs | 2 +- osu.Game/Screens/Select/BeatmapClearScoresDialog.cs | 2 +- osu.Game/Screens/Select/BeatmapDeleteDialog.cs | 2 +- .../Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs | 2 +- osu.Game/Screens/Select/LocalScoreDeleteDialog.cs | 2 +- osu.Game/Screens/Select/SkinDeleteDialog.cs | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) rename osu.Game/Overlays/Dialog/{DeleteConfirmationDialog.cs => DangerousActionDialog.cs} (91%) diff --git a/osu.Game/Collections/DeleteCollectionDialog.cs b/osu.Game/Collections/DeleteCollectionDialog.cs index 4b23f661f9..4da2979481 100644 --- a/osu.Game/Collections/DeleteCollectionDialog.cs +++ b/osu.Game/Collections/DeleteCollectionDialog.cs @@ -8,7 +8,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Collections { - public partial class DeleteCollectionDialog : DeleteConfirmationDialog + public partial class DeleteCollectionDialog : DangerousActionDialog { public DeleteCollectionDialog(Live collection, Action deleteAction) { diff --git a/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs similarity index 91% rename from osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs rename to osu.Game/Overlays/Dialog/DangerousActionDialog.cs index ddb59c4c9e..aaec72fc4d 100644 --- a/osu.Game/Overlays/Dialog/DeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs @@ -12,14 +12,14 @@ namespace osu.Game.Overlays.Dialog /// Differs from in that the confirmation button is a "dangerous" one /// (requires the confirm button to be held). /// - public abstract partial class DeleteConfirmationDialog : PopupDialog + public abstract partial class DangerousActionDialog : PopupDialog { /// /// The action which performs the deletion. /// protected Action? DeleteAction { get; set; } - protected DeleteConfirmationDialog() + protected DangerousActionDialog() { HeaderText = DeleteConfirmationDialogStrings.HeaderText; diff --git a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs index 800ebe8b4e..5b329a32d5 100644 --- a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs +++ b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class DeleteModPresetDialog : DeleteConfirmationDialog + public partial class DeleteModPresetDialog : DangerousActionDialog { public DeleteModPresetDialog(Live modPreset) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs index 948d646e3d..71226803c8 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs @@ -6,7 +6,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Overlays.Settings.Sections.Maintenance { - public partial class MassDeleteConfirmationDialog : DeleteConfirmationDialog + public partial class MassDeleteConfirmationDialog : DangerousActionDialog { public MassDeleteConfirmationDialog(Action deleteAction) { diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index bab5344e1e..770a3c5930 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -631,7 +631,7 @@ namespace osu.Game.Overlays.SkinEditor } } - public partial class ResetConfirmDialog : DeleteConfirmationDialog + public partial class ResetConfirmDialog : DangerousActionDialog { public ResetConfirmDialog(Action reset) { diff --git a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs index 68a0ef4250..6db31967d6 100644 --- a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs +++ b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Edit { - public partial class DeleteDifficultyConfirmationDialog : DeleteConfirmationDialog + public partial class DeleteDifficultyConfirmationDialog : DangerousActionDialog { public DeleteDifficultyConfirmationDialog(BeatmapInfo beatmapInfo, Action deleteAction) { diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index c0f97a05e2..2704a1afb4 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -10,7 +10,7 @@ using osu.Game.Scoring; namespace osu.Game.Screens.Select { - public partial class BeatmapClearScoresDialog : DeleteConfirmationDialog + public partial class BeatmapClearScoresDialog : DangerousActionDialog { [Resolved] private ScoreManager scoreManager { get; set; } = null!; diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index 4ab23c3a3a..0692cc3745 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Select { - public partial class BeatmapDeleteDialog : DeleteConfirmationDialog + public partial class BeatmapDeleteDialog : DangerousActionDialog { private readonly BeatmapSetInfo beatmapSet; diff --git a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs index e1aa662942..ecb21d4e2c 100644 --- a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs +++ b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs @@ -8,7 +8,7 @@ using osu.Game.Localisation; namespace osu.Game.Screens.Select.Carousel { - public partial class UpdateLocalConfirmationDialog : DeleteConfirmationDialog + public partial class UpdateLocalConfirmationDialog : DangerousActionDialog { public UpdateLocalConfirmationDialog(Action onConfirm) { diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 6349e9e5eb..660122c80e 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -10,7 +10,7 @@ using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { - public partial class LocalScoreDeleteDialog : DeleteConfirmationDialog + public partial class LocalScoreDeleteDialog : DangerousActionDialog { private readonly ScoreInfo score; diff --git a/osu.Game/Screens/Select/SkinDeleteDialog.cs b/osu.Game/Screens/Select/SkinDeleteDialog.cs index 9e11629890..3c95de0620 100644 --- a/osu.Game/Screens/Select/SkinDeleteDialog.cs +++ b/osu.Game/Screens/Select/SkinDeleteDialog.cs @@ -7,7 +7,7 @@ using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Select { - public partial class SkinDeleteDialog : DeleteConfirmationDialog + public partial class SkinDeleteDialog : DangerousActionDialog { private readonly Skin skin; From beb04379f9a518c78802da385caa92f5f05c3670 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 27 Feb 2023 22:36:09 +0000 Subject: [PATCH 0199/1400] Inverted an if statement for code clarity --- .../Mods/TaikoInputBlockingMod.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs index f437d53b93..16d885b5d5 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoInputBlockingMod.cs @@ -67,14 +67,13 @@ namespace osu.Game.Rulesets.Taiko.Mods public void Update(Playfield playfield) { - if (nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) - { - if (LastAcceptedDonAction != null) - LastAcceptedDonAction = null; + if (!nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) return; - if (LastAcceptedKatAction != null) - LastAcceptedKatAction = null; - } + if (LastAcceptedDonAction != null) + LastAcceptedDonAction = null; + + if (LastAcceptedKatAction != null) + LastAcceptedKatAction = null; } protected abstract bool CheckValidNewAction(TaikoAction action); From 2615453b3143e59886a56adb2f5d835a241a2a5d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Feb 2023 11:45:32 +0900 Subject: [PATCH 0200/1400] Rename `SettingSource` tests to match attribute name --- ...ingsSourceAttributeTest.cs => SettingSourceAttributeTest.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Mods/{SettingsSourceAttributeTest.cs => SettingSourceAttributeTest.cs} (98%) diff --git a/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs b/osu.Game.Tests/Mods/SettingSourceAttributeTest.cs similarity index 98% rename from osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs rename to osu.Game.Tests/Mods/SettingSourceAttributeTest.cs index bf59862787..5da303d3a7 100644 --- a/osu.Game.Tests/Mods/SettingsSourceAttributeTest.cs +++ b/osu.Game.Tests/Mods/SettingSourceAttributeTest.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Tests.Mods { [TestFixture] - public partial class SettingsSourceAttributeTest + public partial class SettingSourceAttributeTest { [Test] public void TestOrdering() From bd1460a8d5726a67acfdfbfb08568b872fcc8d83 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Feb 2023 14:32:58 +0900 Subject: [PATCH 0201/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4bdf5d68c5..abd8406cf7 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -10,7 +10,7 @@ true - + true true + manifestmerger.jar + + + diff --git a/osu.Android/AndroidManifest.xml b/osu.Android/AndroidManifest.xml index 9ea57969b7..bc2f49b1a9 100644 --- a/osu.Android/AndroidManifest.xml +++ b/osu.Android/AndroidManifest.xml @@ -2,16 +2,4 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/osu.Android/Properties/AndroidManifestOverlay.xml b/osu.Android/Properties/AndroidManifestOverlay.xml new file mode 100644 index 0000000000..815f935383 --- /dev/null +++ b/osu.Android/Properties/AndroidManifestOverlay.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml index 22b4ea9191..bf7c0bfeca 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Catch.Tests.Android/AndroidManifest.xml @@ -3,16 +3,4 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml index c8b0de9f42..4a1545a423 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Mania.Tests.Android/AndroidManifest.xml @@ -2,16 +2,4 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml index d91fc062fe..45d27dda70 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Osu.Tests.Android/AndroidManifest.xml @@ -2,16 +2,4 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml index f678d63dbb..452b9683ec 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Rulesets.Taiko.Tests.Android/AndroidManifest.xml @@ -2,16 +2,4 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/osu.Game.Tests.Android/AndroidManifest.xml b/osu.Game.Tests.Android/AndroidManifest.xml index 105f2b1e8b..f25b2e5328 100644 --- a/osu.Game.Tests.Android/AndroidManifest.xml +++ b/osu.Game.Tests.Android/AndroidManifest.xml @@ -2,16 +2,4 @@ - - - - - - - - - - - - \ No newline at end of file From 908651cc11251cf80e13b8b539abcfc0bd4454a2 Mon Sep 17 00:00:00 2001 From: mk56-spn Date: Sun, 5 Mar 2023 20:57:26 +0100 Subject: [PATCH 0249/1400] make `ResetConfirmDialog` properly utilise its parent's logic Adjust name of `DeleteAction` to `DangerousAction` --- .../Collections/DeleteCollectionDialog.cs | 2 +- .../Overlays/Dialog/DangerousActionDialog.cs | 4 ++-- .../Overlays/Mods/DeleteModPresetDialog.cs | 2 +- .../MassDeleteConfirmationDialog.cs | 2 +- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 19 ++----------------- .../DeleteDifficultyConfirmationDialog.cs | 2 +- .../Select/BeatmapClearScoresDialog.cs | 2 +- .../Screens/Select/BeatmapDeleteDialog.cs | 2 +- .../Carousel/UpdateLocalConfirmationDialog.cs | 2 +- .../Screens/Select/LocalScoreDeleteDialog.cs | 2 +- osu.Game/Screens/Select/SkinDeleteDialog.cs | 2 +- 11 files changed, 13 insertions(+), 28 deletions(-) diff --git a/osu.Game/Collections/DeleteCollectionDialog.cs b/osu.Game/Collections/DeleteCollectionDialog.cs index 4da2979481..9edc213077 100644 --- a/osu.Game/Collections/DeleteCollectionDialog.cs +++ b/osu.Game/Collections/DeleteCollectionDialog.cs @@ -13,7 +13,7 @@ namespace osu.Game.Collections public DeleteCollectionDialog(Live collection, Action deleteAction) { BodyText = collection.PerformRead(c => $"{c.Name} ({"beatmap".ToQuantity(c.BeatmapMD5Hashes.Count)})"); - DeleteAction = deleteAction; + DangerousAction = deleteAction; } } } diff --git a/osu.Game/Overlays/Dialog/DangerousActionDialog.cs b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs index aaec72fc4d..85cae5e0d2 100644 --- a/osu.Game/Overlays/Dialog/DangerousActionDialog.cs +++ b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Dialog /// /// The action which performs the deletion. /// - protected Action? DeleteAction { get; set; } + protected Action? DangerousAction { get; set; } protected DangerousActionDialog() { @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Dialog new PopupDialogDangerousButton { Text = DeleteConfirmationDialogStrings.Confirm, - Action = () => DeleteAction?.Invoke() + Action = () => DangerousAction?.Invoke() }, new PopupDialogCancelButton { diff --git a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs index 5b329a32d5..9788764453 100644 --- a/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs +++ b/osu.Game/Overlays/Mods/DeleteModPresetDialog.cs @@ -12,7 +12,7 @@ namespace osu.Game.Overlays.Mods public DeleteModPresetDialog(Live modPreset) { BodyText = modPreset.PerformRead(preset => preset.Name); - DeleteAction = () => modPreset.PerformWrite(preset => preset.DeletePending = true); + DangerousAction = () => modPreset.PerformWrite(preset => preset.DeletePending = true); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs index 71226803c8..99ef62d94b 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/MassDeleteConfirmationDialog.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance public MassDeleteConfirmationDialog(Action deleteAction) { BodyText = "Everything?"; - DeleteAction = deleteAction; + DangerousAction = deleteAction; } } } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 5ffdaa11d4..a7fe459aa4 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -12,7 +12,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -633,25 +632,11 @@ namespace osu.Game.Overlays.SkinEditor public partial class ResetConfirmDialog : DangerousActionDialog { - public ResetConfirmDialog(Action reset) + public ResetConfirmDialog(Action revert) { HeaderText = SkinEditorStrings.RevertToDefaultDescription; BodyText = SkinEditorStrings.ResetDialogue; - - Icon = FontAwesome.Solid.ExclamationTriangle; - - Buttons = new PopupDialogButton[] - { - new PopupDialogDangerousButton - { - Text = BeatmapOverlayStrings.UserContentConfirmButtonText, - Action = reset - }, - new PopupDialogCancelButton - { - Text = Web.CommonStrings.ButtonsCancel, - }, - }; + DangerousAction = revert; } } diff --git a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs index 6db31967d6..8556949528 100644 --- a/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs +++ b/osu.Game/Screens/Edit/DeleteDifficultyConfirmationDialog.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Edit public DeleteDifficultyConfirmationDialog(BeatmapInfo beatmapInfo, Action deleteAction) { BodyText = $"\"{beatmapInfo.DifficultyName}\" difficulty"; - DeleteAction = deleteAction; + DangerousAction = deleteAction; } } } diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs index 2704a1afb4..8efad451df 100644 --- a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Select public BeatmapClearScoresDialog(BeatmapInfo beatmapInfo, Action onCompletion) { BodyText = $"All local scores on {beatmapInfo.GetDisplayTitle()}"; - DeleteAction = () => + DangerousAction = () => { Task.Run(() => scoreManager.Delete(beatmapInfo)) .ContinueWith(_ => onCompletion); diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index 0692cc3745..e98af8cca2 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader] private void load(BeatmapManager beatmapManager) { - DeleteAction = () => beatmapManager.Delete(beatmapSet); + DangerousAction = () => beatmapManager.Delete(beatmapSet); } } } diff --git a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs index ecb21d4e2c..6157e8f6a5 100644 --- a/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs +++ b/osu.Game/Screens/Select/Carousel/UpdateLocalConfirmationDialog.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select.Carousel HeaderText = PopupDialogStrings.UpdateLocallyModifiedText; BodyText = PopupDialogStrings.UpdateLocallyModifiedDescription; Icon = FontAwesome.Solid.ExclamationTriangle; - DeleteAction = onConfirm; + DangerousAction = onConfirm; } } } diff --git a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs index 660122c80e..c4add31a4f 100644 --- a/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs +++ b/osu.Game/Screens/Select/LocalScoreDeleteDialog.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select BodyText = $"{score.User} ({score.DisplayAccuracy}, {score.Rank})"; Icon = FontAwesome.Regular.TrashAlt; - DeleteAction = () => scoreManager.Delete(score); + DangerousAction = () => scoreManager.Delete(score); } } } diff --git a/osu.Game/Screens/Select/SkinDeleteDialog.cs b/osu.Game/Screens/Select/SkinDeleteDialog.cs index 3c95de0620..6612ae837a 100644 --- a/osu.Game/Screens/Select/SkinDeleteDialog.cs +++ b/osu.Game/Screens/Select/SkinDeleteDialog.cs @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader] private void load(SkinManager manager) { - DeleteAction = () => + DangerousAction = () => { manager.Delete(skin.SkinInfo.Value); manager.CurrentSkinInfo.SetDefault(); From 082bfe3621f8502b81376f5a92e031cf3c7d4803 Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Mar 2023 23:09:02 +0000 Subject: [PATCH 0250/1400] refactor: `SkinnableAvatar` to `PlayerAvatar` --- .../Screens/Play/HUD/{SkinnableAvatar.cs => PlayerAvatar.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game/Screens/Play/HUD/{SkinnableAvatar.cs => PlayerAvatar.cs} (92%) diff --git a/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs similarity index 92% rename from osu.Game/Screens/Play/HUD/SkinnableAvatar.cs rename to osu.Game/Screens/Play/HUD/PlayerAvatar.cs index 41fe8c6a06..d4ab555d04 100644 --- a/osu.Game/Screens/Play/HUD/SkinnableAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -12,7 +12,7 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { - public partial class SkinnableAvatar : CompositeDrawable, ISerialisableDrawable + public partial class PlayerAvatar : CompositeDrawable, ISerialisableDrawable { [SettingSource("Corner radius", "How much the edges should be rounded.")] public new BindableFloat CornerRadius { get; set; } = new BindableFloat @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play.HUD private readonly UpdateableAvatar avatar; - public SkinnableAvatar() + public PlayerAvatar() { Size = new Vector2(128f); InternalChild = avatar = new UpdateableAvatar(isInteractive: false) From 654eacd4496cde2601015abc053d8d081f25869d Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Mar 2023 23:10:42 +0000 Subject: [PATCH 0251/1400] feat(l10n): localise `CornerRadius` --- .../SkinComponents/SkinnableComponentStrings.cs | 10 ++++++++++ osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs b/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs index 547df86fc7..5cec9442e4 100644 --- a/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs +++ b/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs @@ -39,6 +39,16 @@ namespace osu.Game.Localisation.SkinComponents /// public static LocalisableString TextElementTextDescription => new TranslatableString(getKey(@"text_element_text_description"), "The text to be displayed."); + /// + /// "Corner Radius" + /// + public static LocalisableString CornerRadius => new TranslatableString(getKey(@"corner_radius"), "Corner Radius"); + + /// + /// "How rounded the corners should be." + /// + public static LocalisableString CornerRadiusDescription => new TranslatableString(getKey(@"corner_radius_description"), "How rounded the corners should be."); + private static string getKey(string key) => $"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index d4ab555d04..6cea463193 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; +using osu.Game.Localisation.SkinComponents; using osu.Game.Skinning; using osu.Game.Users.Drawables; using osuTK; @@ -14,7 +15,7 @@ namespace osu.Game.Screens.Play.HUD { public partial class PlayerAvatar : CompositeDrawable, ISerialisableDrawable { - [SettingSource("Corner radius", "How much the edges should be rounded.")] + [SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.CornerRadius), nameof(SkinnableComponentStrings.CornerRadiusDescription))] public new BindableFloat CornerRadius { get; set; } = new BindableFloat { MinValue = 0, From 20a610ea6c4c407cedcdffc8a9ac3ae0fbd1f8b0 Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Mar 2023 23:15:58 +0000 Subject: [PATCH 0252/1400] style: a NRT pass on `UpdateableFlag` --- osu.Game/Users/Drawables/UpdateableFlag.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs index a208f3c7c4..8f8d7052e5 100644 --- a/osu.Game/Users/Drawables/UpdateableFlag.cs +++ b/osu.Game/Users/Drawables/UpdateableFlag.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -30,14 +28,14 @@ namespace osu.Game.Users.Drawables /// Perform an action in addition to showing the country ranking. /// This should be used to perform auxiliary tasks and not as a primary action for clicking a flag (to maintain a consistent UX). /// - public Action Action; + public Action? Action; public UpdateableFlag(CountryCode countryCode = CountryCode.Unknown) { CountryCode = countryCode; } - protected override Drawable CreateDrawable(CountryCode countryCode) + protected override Drawable? CreateDrawable(CountryCode countryCode) { if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown) return null; @@ -56,8 +54,8 @@ namespace osu.Game.Users.Drawables }; } - [Resolved(canBeNull: true)] - private RankingsOverlay rankingsOverlay { get; set; } + [Resolved] + private RankingsOverlay? rankingsOverlay { get; set; } protected override bool OnClick(ClickEvent e) { From 07bde4990d50836a64e62f61a60f991165bb6436 Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Mar 2023 23:17:30 +0000 Subject: [PATCH 0253/1400] feat: implement `PlayerAvatar` --- osu.Game/Screens/Play/HUD/PlayerFlag.cs | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 osu.Game/Screens/Play/HUD/PlayerFlag.cs diff --git a/osu.Game/Screens/Play/HUD/PlayerFlag.cs b/osu.Game/Screens/Play/HUD/PlayerFlag.cs new file mode 100644 index 0000000000..17188d0009 --- /dev/null +++ b/osu.Game/Screens/Play/HUD/PlayerFlag.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Skinning; +using osu.Game.Users.Drawables; +using osuTK; + +namespace osu.Game.Screens.Play.HUD +{ + public partial class PlayerFlag : CompositeDrawable, ISerialisableDrawable + { + [Resolved] + private GameplayState gameplayState { get; set; } = null!; + + private readonly UpdateableFlag flag; + + public PlayerFlag() + { + Size = new Vector2(114, 80); + InternalChild = flag = new UpdateableFlag + { + RelativeSizeAxes = Axes.Both, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + flag.CountryCode = gameplayState.Score.ScoreInfo.User.CountryCode; + } + + public bool UsesFixedAnchor { get; set; } + } +} From ddee6400dfa3c28f476e0c9fea11a17874c82257 Mon Sep 17 00:00:00 2001 From: tsrk Date: Sun, 5 Mar 2023 23:46:51 +0000 Subject: [PATCH 0254/1400] test: add coverage for `Player{Avatar,Flag}` --- .../Archives/modified-argon-20230305.osk | Bin 0 -> 1897 bytes osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/Archives/modified-argon-20230305.osk diff --git a/osu.Game.Tests/Resources/Archives/modified-argon-20230305.osk b/osu.Game.Tests/Resources/Archives/modified-argon-20230305.osk new file mode 100644 index 0000000000000000000000000000000000000000..c85f3b6352af3357089a797c287659a0d8e848f7 GIT binary patch literal 1897 zcmZ`)2{ha37XJrDwM>j<6dg)aofm6Nl`=@FlHetRpxP!SwNw*ZQW6}y5s4*KF={EH zN^R8^#bCygmIl?)Djh?_UPTSDj7j_Ey*c&X`@VC}J@-4`@1A?V@7~`N?B_rB4NU|rVlAmS1QZ5D)sBQZsC%Y@)DD`?fvQgW%$c95cG#nwX5eaNBy!>}^x zSMnoc3Ae1r;c-(M3B@4=N}}*4N1bz$rM~DOQvG&rj>c9JM;D3N!SAoqeU77@MDnSzO%AM%6NUOL18A1WCPf&1x=^Hr@-YKH;#HEae+Y?K$)9#Y zp;nQ74leahsHb|mF3#Vh5!whYHwEo9pbyiB4LJ|=_WzS(|IFS21k?HUW@x)deu|SE zay7-W`RrQ#+Um2lqAv@=yCBKoklbWQt{}W1+)sdtTOW(bo;~2>!=EPb*$XDIi@-{# zJdTBE@q7q;9w5sc$)t(`K$Q{zC<+5~!21zxU97E0*8@pJ0x>k?Q>067Xwn-aaFkl@ z9*+0=gl%$GFDSe>pM2y|arf9e_DM01wq8$Pm^!<`W^m8^Y2CufVp;Vdp8Vb2E8{mN zZwtncE^kiH6pF`XhGLyWl%Go~&CPFdp0mECH6>MyEWXe-D>w<=HN&b+n zHvTxQ&#A2@r^Q?FE^O+n-!W*D@YYu?FVAORzPojLrfOT|EO}!VJ9mclb(~0#l>XZb z(c4ukV&`+0>4li7y=#00?T+CDS8+PE_$gE_IC#8$Y^|wb)Tlbg4m)q;`(f9V$V8vB(W^<3RQMb^q4L(#q25!yjaJWPgxI?H|lk0dHv z69fR(A^`A(uv;-Cq7Q};K=2Cv)TZPNB(YN;oVan5Dgj;SmGVPav9<4gD884XAvs>8 zYp)cWU}zI{S3OH~UA5KiwxyKpxwm~0duCDLlo4!vSQCT-xC(8*>Fw(iJ434N=Sk_qq46_?0cwbTrb3fm^Ie z_w9``>IV!Cb~kcIe9W1q@W}E(?v0LzBjo0Ex0GAwih;z|%R|JIw ziO2*0f5ZqM^wjSYAg1##)PG2RKXgCg{tfjKe(e9I-~B%Jm%-mY YWDopTQJ|0q#6MmT6Yf=^#(%Q@1WNchY5)KL literal 0 HcmV?d00001 diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index 04b8c6dd4e..eb1df954aa 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -9,6 +9,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; +using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.IO; using osu.Game.IO.Archives; @@ -48,7 +49,9 @@ namespace osu.Game.Tests.Skins // Covers BPM counter. "Archives/modified-default-20221205.osk", // Covers judgement counter. - "Archives/modified-default-20230117.osk" + "Archives/modified-default-20230117.osk", + // Covers player avatar and flag. + "Archives/modified-argon-20230305.osk", }; /// @@ -61,6 +64,8 @@ namespace osu.Game.Tests.Skins foreach (string oskFile in available_skins) { + Logger.Log($"Testing file {oskFile}..."); + using (var stream = TestResources.OpenResource(oskFile)) using (var storage = new ZipArchiveReader(stream)) { From 87d0bef313fc9e5563dc3d368f3daf59b437c6aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 6 Mar 2023 15:16:31 +0900 Subject: [PATCH 0255/1400] Use nullable comparison helper method instead of manual implementation --- .../Screens/Select/Carousel/CarouselBeatmapSet.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 63493a3b02..67822a27ee 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Select.Carousel break; case SortMode.DateRanked: - comparison = compareNullableDateTimeOffset(BeatmapSet.DateRanked, otherSet.BeatmapSet.DateRanked); + comparison = Nullable.Compare(otherSet.BeatmapSet.DateRanked, BeatmapSet.DateRanked); break; case SortMode.LastPlayed: @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Select.Carousel break; case SortMode.DateSubmitted: - comparison = compareNullableDateTimeOffset(BeatmapSet.DateSubmitted, otherSet.BeatmapSet.DateSubmitted); + comparison = Nullable.Compare(otherSet.BeatmapSet.DateSubmitted, BeatmapSet.DateSubmitted); break; } @@ -124,14 +124,6 @@ namespace osu.Game.Screens.Select.Carousel return otherSet.BeatmapSet.ID.CompareTo(BeatmapSet.ID); } - private static int compareNullableDateTimeOffset(DateTimeOffset? x, DateTimeOffset? y) - { - if (x == null) return 1; - if (y == null) return -1; - - return y.Value.CompareTo(x.Value); - } - /// /// All beatmaps which are not filtered and valid for display. /// From 3a240aaa5fa1e55bcc9b50c26345ebdf0c001d99 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Mar 2023 10:27:59 +0000 Subject: [PATCH 0256/1400] style: use 64 radius --- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index 6cea463193..32ed045df7 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Play.HUD public new BindableFloat CornerRadius { get; set; } = new BindableFloat { MinValue = 0, - MaxValue = 63, + MaxValue = 64, Precision = 0.01f }; From df34bdc825e5496339de30ad3173f93dd28f40df Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 6 Mar 2023 19:31:45 +0900 Subject: [PATCH 0257/1400] Use lang version 10 --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 3b6b985961..734374c840 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  - 9.0 + 10.0 true enable From a7be59175d15298d1a7eff2c9e090dca03c8492f Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 6 Mar 2023 10:57:09 +0000 Subject: [PATCH 0258/1400] Made private + renamed Taiko Single Tap tracking variables for better readability --- .../Mods/TaikoModSingleTap.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 1130338521..30e4946833 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -29,9 +29,9 @@ namespace osu.Game.Rulesets.Taiko.Mods protected bool CheckValidNewAction(TaikoAction action) { if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) - return LastAcceptedDonAction == null || LastAcceptedDonAction == action; + return lastAcceptedCentreAction == null || lastAcceptedCentreAction == action; if (action == TaikoAction.LeftRim || action == TaikoAction.RightRim) - return LastAcceptedKatAction == null || LastAcceptedKatAction == action; + return lastAcceptedRimAction == null || lastAcceptedRimAction == action; return true; } @@ -44,8 +44,8 @@ namespace osu.Game.Rulesets.Taiko.Mods private TaikoPlayfield playfield { get; set; } = null!; - protected TaikoAction? LastAcceptedDonAction { get; private set; } - protected TaikoAction? LastAcceptedKatAction { get; private set; } + private TaikoAction? lastAcceptedCentreAction { get; set; } + private TaikoAction? lastAcceptedRimAction { get; set; } /// /// A tracker for periods where alternate should not be forced (i.e. non-gameplay periods). @@ -84,11 +84,11 @@ namespace osu.Game.Rulesets.Taiko.Mods { if (!nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) return; - if (LastAcceptedDonAction != null) - LastAcceptedDonAction = null; + if (lastAcceptedCentreAction != null) + lastAcceptedCentreAction = null; - if (LastAcceptedKatAction != null) - LastAcceptedKatAction = null; + if (lastAcceptedRimAction != null) + lastAcceptedRimAction = null; } private bool checkCorrectAction(TaikoAction action) @@ -105,9 +105,9 @@ namespace osu.Game.Rulesets.Taiko.Mods if (CheckValidNewAction(action)) { if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) - LastAcceptedDonAction = action; + lastAcceptedCentreAction = action; if (action == TaikoAction.LeftRim || action == TaikoAction.RightRim) - LastAcceptedKatAction = action; + lastAcceptedRimAction = action; return true; } From ac6c8e600a4ef58cedae8f19b8fabf50fa8aa6fc Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 6 Mar 2023 10:59:47 +0000 Subject: [PATCH 0259/1400] Updated a comment for correctness --- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 30e4946833..9b411b49d4 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Taiko.Mods private TaikoAction? lastAcceptedRimAction { get; set; } /// - /// A tracker for periods where alternate should not be forced (i.e. non-gameplay periods). + /// A tracker for periods where single tap should not be enforced (i.e. non-gameplay periods). /// /// /// This is different from in that the periods here end strictly at the first object after the break, rather than the break's end time. From 4ae2661f1bd90181b54917ef55df431c7622ad57 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 6 Mar 2023 11:00:37 +0000 Subject: [PATCH 0260/1400] Removed useless null checks --- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 9b411b49d4..92aff90ae0 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -84,11 +84,8 @@ namespace osu.Game.Rulesets.Taiko.Mods { if (!nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime)) return; - if (lastAcceptedCentreAction != null) - lastAcceptedCentreAction = null; - - if (lastAcceptedRimAction != null) - lastAcceptedRimAction = null; + lastAcceptedCentreAction = null; + lastAcceptedRimAction = null; } private bool checkCorrectAction(TaikoAction action) From 36108ea841603febdc2602e9f4a85ad69c25f34a Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 6 Mar 2023 11:10:57 +0000 Subject: [PATCH 0261/1400] Moved `CheckValidNewAction` checks into `checkCorrectAction` --- .../Mods/TaikoModSingleTap.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 92aff90ae0..556e31d2c2 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -26,16 +26,6 @@ namespace osu.Game.Rulesets.Taiko.Mods public override string Acronym => @"SG"; public override LocalisableString Description => @"One key for dons, one key for kats."; - protected bool CheckValidNewAction(TaikoAction action) - { - if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) - return lastAcceptedCentreAction == null || lastAcceptedCentreAction == action; - if (action == TaikoAction.LeftRim || action == TaikoAction.RightRim) - return lastAcceptedRimAction == null || lastAcceptedRimAction == action; - - return true; - } - public override double ScoreMultiplier => 1.0; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) }; public override ModType Type => ModType.Conversion; @@ -99,13 +89,17 @@ namespace osu.Game.Rulesets.Taiko.Mods && hitObject is not DrumRoll) return true; - if (CheckValidNewAction(action)) + if ((action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) + && (lastAcceptedCentreAction == null || lastAcceptedCentreAction == action)) { - if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) - lastAcceptedCentreAction = action; - if (action == TaikoAction.LeftRim || action == TaikoAction.RightRim) - lastAcceptedRimAction = action; + lastAcceptedCentreAction = action; + return true; + } + if ((action == TaikoAction.LeftRim || action == TaikoAction.RightRim) + && (lastAcceptedRimAction == null || lastAcceptedRimAction == action)) + { + lastAcceptedRimAction = action; return true; } From b2d453fd2edae6478bb0dfbfa860bea39a8251c3 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Mon, 6 Mar 2023 11:44:00 +0000 Subject: [PATCH 0262/1400] Fixed indentation --- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index 556e31d2c2..fa876555e1 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -90,14 +90,14 @@ namespace osu.Game.Rulesets.Taiko.Mods return true; if ((action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre) - && (lastAcceptedCentreAction == null || lastAcceptedCentreAction == action)) + && (lastAcceptedCentreAction == null || lastAcceptedCentreAction == action)) { lastAcceptedCentreAction = action; return true; } if ((action == TaikoAction.LeftRim || action == TaikoAction.RightRim) - && (lastAcceptedRimAction == null || lastAcceptedRimAction == action)) + && (lastAcceptedRimAction == null || lastAcceptedRimAction == action)) { lastAcceptedRimAction = action; return true; From 1fcf41379d5d5c37d211644fc96e4e99c4710ab0 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 6 Mar 2023 16:20:36 +0100 Subject: [PATCH 0263/1400] Added maintainability patch by bdach --- osu.Game/Beatmaps/BeatmapInfoExtensions.cs | 22 +++++------- .../Beatmaps/BeatmapMetadataInfoExtensions.cs | 35 +++++++++++++------ 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs index 460944d2fa..3aab9a24e1 100644 --- a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs @@ -1,7 +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 System; +using System.Collections.Generic; using osu.Framework.Localisation; namespace osu.Game.Beatmaps @@ -29,25 +29,19 @@ namespace osu.Game.Beatmaps return new RomanisableString($"{metadata.GetPreferred(true)}".Trim(), $"{metadata.GetPreferred(false)}".Trim()); } - public static ReadOnlySpan GetSearchableTerms(this IBeatmapInfo beatmapInfo) + public static List GetSearchableTerms(this IBeatmapInfo beatmapInfo) { - string[] terms = new string[8]; - int i = 0; - var metadata = beatmapInfo.Metadata; + var termsList = new List(BeatmapMetadataInfoExtensions.MAX_SEARCHABLE_TERM_COUNT + 1); + addIfNotNull(beatmapInfo.DifficultyName); - addIfNotNull(metadata.Author.Username); - addIfNotNull(metadata.Artist); - addIfNotNull(metadata.ArtistUnicode); - addIfNotNull(metadata.Title); - addIfNotNull(metadata.TitleUnicode); - addIfNotNull(metadata.Source); - addIfNotNull(metadata.Tags); - return terms.AsSpan(0, i); + + BeatmapMetadataInfoExtensions.CollectSearchableTerms(beatmapInfo.Metadata, termsList); + return termsList; void addIfNotNull(string? s) { if (!string.IsNullOrEmpty(s)) - terms[i++] = s; + termsList.Add(s); } } diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index 738bdb0839..fe4e815e62 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -3,7 +3,7 @@ #nullable disable -using System.Linq; +using System.Collections.Generic; using osu.Framework.Localisation; namespace osu.Game.Beatmaps @@ -13,16 +13,31 @@ namespace osu.Game.Beatmaps /// /// An array of all searchable terms provided in contained metadata. /// - public static string[] GetSearchableTerms(this IBeatmapMetadataInfo metadataInfo) => new[] + public static string[] GetSearchableTerms(this IBeatmapMetadataInfo metadataInfo) { - metadataInfo.Author.Username, - metadataInfo.Artist, - metadataInfo.ArtistUnicode, - metadataInfo.Title, - metadataInfo.TitleUnicode, - metadataInfo.Source, - metadataInfo.Tags - }.Where(s => !string.IsNullOrEmpty(s)).ToArray(); + var termsList = new List(MAX_SEARCHABLE_TERM_COUNT); + CollectSearchableTerms(metadataInfo, termsList); + return termsList.ToArray(); + } + + internal const int MAX_SEARCHABLE_TERM_COUNT = 7; + + internal static void CollectSearchableTerms(IBeatmapMetadataInfo metadataInfo, IList termsList) + { + addIfNotNull(metadataInfo.Author.Username); + addIfNotNull(metadataInfo.Artist); + addIfNotNull(metadataInfo.ArtistUnicode); + addIfNotNull(metadataInfo.Title); + addIfNotNull(metadataInfo.TitleUnicode); + addIfNotNull(metadataInfo.Source); + addIfNotNull(metadataInfo.Tags); + + void addIfNotNull(string s) + { + if (!string.IsNullOrEmpty(s)) + termsList.Add(s); + } + } /// /// A user-presentable display title representing this metadata. From 4858d3fd4282e0f2ea48f3a5f1138f341d00edc6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 02:00:40 +0900 Subject: [PATCH 0264/1400] Added ability to edit mod presets --- .../UserInterface/TestSceneModPresetColumn.cs | 171 +++++++++++++++++- osu.Game/Overlays/Mods/EditPresetPopover.cs | 140 ++++++++++++++ osu.Game/Overlays/Mods/ModPresetPanel.cs | 8 +- 3 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/Mods/EditPresetPopover.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 1090764788..f48c52ad40 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -243,7 +243,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); AddStep("click delete", () => { - var deleteItem = this.ChildrenOfType().Single(); + var deleteItem = this.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(deleteItem); InputManager.Click(MouseButton.Left); }); @@ -261,6 +261,175 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("preset soft-deleted", () => Realm.Run(r => r.All().Count(preset => preset.DeletePending) == 1)); } + [Test] + public void TestEditPresentName() + { + ModPresetColumn modPresetColumn = null!; + string presetName = null!; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + presetName = panel.Preset.Value.Name; + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("clear preset name", () => popover.ChildrenOfType().First().Current.Value = ""); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + + AddWaitStep("wait some", 3); + AddAssert("present is not changed", () => this.ChildrenOfType().First().Preset.Value.Name == presetName); + AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); + AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present is changed", () => this.ChildrenOfType().First().Preset.Value.Name != presetName); + } + + [Test] + public void TestEditPresetMod() + { + ModPresetColumn modPresetColumn = null!; + var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + AddStep("select mods", () => SelectedMods.Value = mods); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("enable switch", () => popover.ChildrenOfType().Single().Current.Value = true); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + } + + [Test] + public void TestEditModSwitchDisableWithNoModSelest() + { + ModPresetColumn modPresetColumn = null!; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + } + + [Test] + public void TestEditModSwitchDisableWithPresetSelest() + { + ModPresetColumn modPresetColumn = null!; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + AddStep("select first preset mod", () => + SelectedMods.Value = this.ChildrenOfType().First().Preset.Value.Mods.ToList()); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + } + private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs new file mode 100644 index 0000000000..270b6f43d9 --- /dev/null +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -0,0 +1,140 @@ +// 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 System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Extensions; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Localisation; +using osu.Game.Rulesets.Mods; +using osuTK; + +namespace osu.Game.Overlays.Mods +{ + internal partial class EditPresetPopover : OsuPopover + { + private readonly ModPresetPanel button; + + private readonly LabelledTextBox nameTextBox; + private readonly LabelledTextBox descriptionTextBox; + private readonly LabelledSwitchButton useCurrentSwitch; + private readonly ShearedButton createButton; + + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + private readonly ModPreset preset; + + public EditPresetPopover(ModPresetPanel modPresetPanel) + { + button = modPresetPanel; + preset = button.Preset.Value; + + Child = new FillFlowContainer + { + Width = 300, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + nameTextBox = new LabelledTextBox + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = CommonStrings.Name, + TabbableContentContainer = this + }, + descriptionTextBox = new LabelledTextBox + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = CommonStrings.Description, + TabbableContentContainer = this + }, + useCurrentSwitch = new LabelledSwitchButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Label = "Use Current Mod select", + }, + createButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = CommonStrings.MenuBarEdit, + Action = tryEditPreset + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider, OsuColour colours) + { + Body.BorderThickness = 3; + Body.BorderColour = colours.Orange1; + + nameTextBox.Current.Value = preset.Name; + descriptionTextBox.Current.Value = preset.Description; + + selectedMods.BindValueChanged(_ => updateMods(), true); + + createButton.DarkerColour = colours.Orange1; + createButton.LighterColour = colours.Orange0; + createButton.TextColour = colourProvider.Background6; + } + + private void updateMods() + { + useCurrentSwitch.Current.Disabled = false; + + // disable the switch when mod is equal. + if (button.Active.Value) + { + useCurrentSwitch.Current.Value = true; + useCurrentSwitch.Current.Disabled = true; + } + else + { + useCurrentSwitch.Current.Value = false; + useCurrentSwitch.Current.Disabled = !selectedMods.Value.Any(); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); + } + + private void tryEditPreset() + { + if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) + { + Body.Shake(); + return; + } + + button.Preset.PerformWrite(s => + { + s.Name = nameTextBox.Current.Value; + s.Description = descriptionTextBox.Current.Value; + + if (useCurrentSwitch.Current.Value) + { + s.Mods = selectedMods.Value.ToArray(); + } + }); + + this.HidePopover(); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 6e12e34124..f4f1af50df 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; @@ -17,7 +18,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover { public readonly Live Preset; @@ -91,7 +92,8 @@ namespace osu.Game.Overlays.Mods public MenuItem[] ContextMenuItems => new MenuItem[] { - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))) + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), }; #endregion @@ -102,5 +104,7 @@ namespace osu.Game.Overlays.Mods settingChangeTracker?.Dispose(); } + + public Popover GetPopover() => new EditPresetPopover(this); } } From 0095fd85cad0a7b8dcddd29c983991af959a57fb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 02:18:34 +0900 Subject: [PATCH 0265/1400] remove `== true` --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index f48c52ad40..8fbc8940c7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -386,7 +386,7 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); } [Test] @@ -422,12 +422,12 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value == true); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled == true); + AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); } private ICollection createTestPresets() => new[] From 952814604ed43ab85b799198268cd222b7f9b9a9 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Mar 2023 20:06:56 +0000 Subject: [PATCH 0266/1400] style: fix late night oopsies --- osu.Game.Tests/Skins/SkinDeserialisationTest.cs | 3 --- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs index eb1df954aa..bd8088cfb6 100644 --- a/osu.Game.Tests/Skins/SkinDeserialisationTest.cs +++ b/osu.Game.Tests/Skins/SkinDeserialisationTest.cs @@ -9,7 +9,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; -using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.IO; using osu.Game.IO.Archives; @@ -64,8 +63,6 @@ namespace osu.Game.Tests.Skins foreach (string oskFile in available_skins) { - Logger.Log($"Testing file {oskFile}..."); - using (var stream = TestResources.OpenResource(oskFile)) using (var storage = new ZipArchiveReader(stream)) { diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index 32ed045df7..d2f4f0be17 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -43,8 +43,7 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); avatar.User = gameplayState.Score.ScoreInfo.User; - avatar.CornerRadius = CornerRadius.Value; - CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue); + CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue, true); } public bool UsesFixedAnchor { get; set; } From fc0e27fb15e3eb1a143e5924a9adf3f472944a06 Mon Sep 17 00:00:00 2001 From: tsrk Date: Mon, 6 Mar 2023 20:11:52 +0000 Subject: [PATCH 0267/1400] style: use normalised `CornerRadius` values --- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index d2f4f0be17..f293199911 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -16,10 +16,10 @@ namespace osu.Game.Screens.Play.HUD public partial class PlayerAvatar : CompositeDrawable, ISerialisableDrawable { [SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.CornerRadius), nameof(SkinnableComponentStrings.CornerRadiusDescription))] - public new BindableFloat CornerRadius { get; set; } = new BindableFloat + public new BindableFloat CornerRadius { get; set; } = new BindableFloat(0.25f) { MinValue = 0, - MaxValue = 64, + MaxValue = 0.5f, Precision = 0.01f }; @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); avatar.User = gameplayState.Score.ScoreInfo.User; - CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue, true); + CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue * 128f, true); } public bool UsesFixedAnchor { get; set; } From 21bdbb20e6b362f96f53863614474dfae32f1726 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 14:22:12 +0900 Subject: [PATCH 0268/1400] Add optional support for cyclic selection to `BlueprintContainer` --- .../SkinEditor/SkinBlueprintContainer.cs | 2 + .../Compose/Components/BlueprintContainer.cs | 72 +++++++++++++++---- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinBlueprintContainer.cs b/osu.Game/Overlays/SkinEditor/SkinBlueprintContainer.cs index 3f8d9f80d4..db27e20010 100644 --- a/osu.Game/Overlays/SkinEditor/SkinBlueprintContainer.cs +++ b/osu.Game/Overlays/SkinEditor/SkinBlueprintContainer.cs @@ -25,6 +25,8 @@ namespace osu.Game.Overlays.SkinEditor [Resolved] private SkinEditor editor { get; set; } = null!; + protected override bool AllowCyclicSelection => true; + public SkinBlueprintContainer(ISerialisableDrawableContainer targetContainer) { this.targetContainer = targetContainer; diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index e4e67d10d7..87cee59d83 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -45,6 +45,15 @@ namespace osu.Game.Screens.Edit.Compose.Components protected readonly BindableList SelectedItems = new BindableList(); + /// + /// Whether to allow cyclic selection on clicking multiple times. + /// + /// + /// Disabled by default as it does not work well with editors that support double-clicking or other advanced interactions. + /// Can probably be made to work with more thought. + /// + protected virtual bool AllowCyclicSelection => false; + protected BlueprintContainer() { RelativeSizeAxes = Axes.Both; @@ -167,7 +176,7 @@ namespace osu.Game.Screens.Edit.Compose.Components Schedule(() => { endClickSelection(e); - clickSelectionBegan = false; + clickSelectionHandled = false; isDraggingBlueprint = false; }); @@ -339,7 +348,12 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Whether a blueprint was selected by a previous click event. /// - private bool clickSelectionBegan; + private bool clickSelectionHandled; + + /// + /// Whether the selected blueprint(s) were already selected on mouse down. Generally used to perform selection cycling on mouse up in such a case. + /// + private bool selectedBlueprintAlreadySelectedOnMouseDown; /// /// Attempts to select any hovered blueprints. @@ -354,7 +368,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (!blueprint.IsHovered) continue; - return clickSelectionBegan = SelectionHandler.MouseDownSelectionRequested(blueprint, e); + selectedBlueprintAlreadySelectedOnMouseDown = blueprint.State == SelectionState.Selected; + return clickSelectionHandled = SelectionHandler.MouseDownSelectionRequested(blueprint, e); } return false; @@ -367,18 +382,45 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Whether a click selection was active. private bool endClickSelection(MouseButtonEvent e) { - if (!clickSelectionBegan && !isDraggingBlueprint) + if (!clickSelectionHandled && !isDraggingBlueprint) { - // if a selection didn't occur, we may want to trigger a deselection. - if (e.ControlPressed && e.Button == MouseButton.Left) + if (e.Button == MouseButton.Left) { - // Iterate from the top of the input stack (blueprints closest to the front of the screen first). - // Priority is given to already-selected blueprints. - foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren.Reverse().OrderByDescending(b => b.IsSelected)) + if (e.ControlPressed) { - if (!blueprint.IsHovered) continue; + // if a selection didn't occur, we may want to trigger a deselection. - return clickSelectionBegan = SelectionHandler.MouseUpSelectionRequested(blueprint, e); + // Iterate from the top of the input stack (blueprints closest to the front of the screen first). + // Priority is given to already-selected blueprints. + foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren.OrderByDescending(b => b.IsSelected)) + { + if (!blueprint.IsHovered) continue; + + return clickSelectionHandled = SelectionHandler.MouseUpSelectionRequested(blueprint, e); + } + } + else if (selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) + { + // If a click occurred and was handled by the currently selected blueprint but didn't result in a drag, + // cycle between other blueprints which are also under the cursor. + + // The depth of blueprints is constantly changing (see above where selected blueprints are brought to the front). + // For this logic, we want a stable sort order so we can correctly cycle, thus using the blueprintMap instead. + IEnumerable> cyclingSelectionBlueprints = blueprintMap.Values; + + // If there's already a selection, let's start from the blueprint after the selection. + cyclingSelectionBlueprints = cyclingSelectionBlueprints.SkipWhile(b => !b.IsSelected).Skip(1); + + // Add the blueprints from before the selection to the end of the enumerable to allow for cyclic selection. + cyclingSelectionBlueprints = cyclingSelectionBlueprints.Concat(blueprintMap.Values.TakeWhile(b => !b.IsSelected)); + + foreach (SelectionBlueprint blueprint in cyclingSelectionBlueprints) + { + if (!blueprint.IsHovered) continue; + + // We are performing a mouse up, but selection handlers perform selection on mouse down, so we need to call that instead. + return clickSelectionHandled = SelectionHandler.MouseDownSelectionRequested(blueprint, e); + } } } @@ -441,7 +483,11 @@ namespace osu.Game.Screens.Edit.Compose.Components private Vector2[][] movementBlueprintsOriginalPositions; private SelectionBlueprint[] movementBlueprints; - private bool isDraggingBlueprint; + + /// + /// Whether a blueprint is currently being dragged. + /// + private bool isDraggingBlueprint { get; set; } /// /// Attempts to begin the movement of any selected blueprints. @@ -454,7 +500,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // Any selected blueprint that is hovered can begin the movement of the group, however only the first item (according to SortForMovement) is used for movement. // A special case is added for when a click selection occurred before the drag - if (!clickSelectionBegan && !SelectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) + if (!clickSelectionHandled && !SelectionHandler.SelectedBlueprints.Any(b => b.IsHovered)) return false; // Movement is tracked from the blueprint of the earliest item, since it only makes sense to distance snap from that item From d2fcdf6e0e464ec389cff62ca715411402df6323 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 14:22:19 +0900 Subject: [PATCH 0269/1400] Add test coverage of cyclic selection in skin editor --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 9690d00d4c..7af2b7d6fe 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -17,6 +17,8 @@ using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; using osu.Game.Screens.Play.HUD.HitErrorMeters; using osu.Game.Skinning; +using osu.Game.Skinning.Components; +using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay @@ -52,6 +54,44 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for loaded", () => skinEditor.IsLoaded); } + [Test] + public void TestCyclicSelection() + { + SkinBlueprint[] blueprints = null!; + + AddStep("Add big black boxes", () => + { + InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + InputManager.Click(MouseButton.Left); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("Three black boxes added", () => targetContainer.Components.OfType().Count(), () => Is.EqualTo(3)); + + AddStep("Store black box blueprints", () => + { + blueprints = skinEditor.ChildrenOfType().Where(b => b.Item is BigBlackBox).ToArray(); + }); + + AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); + + AddStep("move cursor to black box", () => + { + // Slightly offset from centre to avoid random failures (see https://github.com/ppy/osu-framework/issues/5669). + InputManager.MoveMouseTo(((Drawable)blueprints[0].Item).ScreenSpaceDrawQuad.Centre + new Vector2(1)); + }); + + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddAssert("Selection is black box 2", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[1].Item)); + + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddAssert("Selection is black box 3", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[2].Item)); + + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); + } + [TestCase(false)] [TestCase(true)] public void TestBringToFront(bool alterSelectionOrder) From 2cce785fa5bb7fd1ab6b77d1a757a76a6fc3f94b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 15:54:33 +0900 Subject: [PATCH 0270/1400] Fix storyboard videos not fading out on completion Closes https://github.com/ppy/osu/issues/22802. Stable uses a 1,000 ms fade-in / out. Rather than matching that, I've stuck with 500ms (what lazer was already using for the fade-in) because I think it feels better. Tested using the beatmap linked in the issue thread. --- osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs index f4b0692619..eec2cd6a60 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardVideo.cs @@ -58,7 +58,11 @@ namespace osu.Game.Storyboards.Drawables using (drawableVideo.BeginAbsoluteSequence(Video.StartTime)) { Schedule(() => drawableVideo.PlaybackPosition = Time.Current - Video.StartTime); + drawableVideo.FadeIn(500); + + using (drawableVideo.BeginDelayedSequence(drawableVideo.Duration - 500)) + drawableVideo.FadeOut(500); } } } From 15d65059b5403824059b753fd9359280a475afb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 16:21:57 +0900 Subject: [PATCH 0271/1400] Tidy up `Add` method logic --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 16 ++++++------ osu.Game/Screens/Play/KeyCounterDisplay.cs | 26 ++++++------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 12cd7e1be9..d0c691e23f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -3,7 +3,6 @@ #nullable disable -using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; @@ -21,15 +20,16 @@ namespace osu.Game.Tests.Visual.Gameplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Triggers = new InputTrigger[] - { - new KeyCounterKeyboardTrigger(Key.X), - new KeyCounterKeyboardTrigger(Key.X), - new KeyCounterMouseTrigger(MouseButton.Left), - new KeyCounterMouseTrigger(MouseButton.Right), - } }; + kc.AddTriggerRange(new InputTrigger[] + { + new KeyCounterKeyboardTrigger(Key.X), + new KeyCounterKeyboardTrigger(Key.X), + new KeyCounterMouseTrigger(MouseButton.Left), + new KeyCounterMouseTrigger(MouseButton.Right), + }); + var testCounter = (DefaultKeyCounter)kc.Children.First(); AddStep("Add random", () => diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 01686ae6de..50670fb2fe 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -25,16 +25,6 @@ namespace osu.Game.Screens.Play public Bindable IsCounting { get; } = new BindableBool(true); - public IReadOnlyList Triggers - { - get => Children.Select(c => c.Trigger).ToArray(); - set - { - Clear(); - value.ForEach(AddTrigger); - } - } - protected readonly Bindable ConfigVisibility = new Bindable(); protected abstract void UpdateVisibility(); @@ -60,17 +50,17 @@ namespace osu.Game.Screens.Play public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); - private bool checkType(KeyCounter key) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(key)); - - public override void Add(KeyCounter key) + public override void Add(KeyCounter counter) { - if (!checkType(key)) - throw new InvalidOperationException($"{key.GetType()} is not a supported counter type. (hint: you may want to use {nameof(AddTrigger)} instead.)"); + if (!checkType(counter)) + throw new InvalidOperationException($"{counter.GetType()} is not a supported counter type. (hint: you may want to use {nameof(AddTrigger)} instead.)"); - base.Add(key); - key.IsCounting.BindTo(IsCounting); + base.Add(counter); + counter.IsCounting.BindTo(IsCounting); } + private bool checkType(KeyCounter counter) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(counter)); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -110,7 +100,7 @@ namespace osu.Game.Screens.Play case KeyUpEvent: case MouseDownEvent: case MouseUpEvent: - return Target.Children.Any(c => c.TriggerEvent(e)); + return Target.InternalChildren.Any(c => c.TriggerEvent(e)); } return base.Handle(e); From 28520414aa5d857724b093b6e6b1999d80c6a21b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 16:28:54 +0900 Subject: [PATCH 0272/1400] Move `KeyCounter` components to `HUD` namespace --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 1 + osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 3 ++- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 1 + .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 1 + .../Navigation/TestSceneChangeAndUseGameplayBindings.cs | 1 + osu.Game/Rulesets/UI/DrawableRuleset.cs | 1 + osu.Game/Rulesets/UI/RulesetInputManager.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/DefaultKeyCounter.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/DefaultKeyCounterDisplay.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/InputTrigger.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/KeyCounter.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/KeyCounterActionTrigger.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/KeyCounterDisplay.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/KeyCounterKeyboardTrigger.cs | 2 +- osu.Game/Screens/Play/{ => HUD}/KeyCounterMouseTrigger.cs | 4 ++-- 15 files changed, 17 insertions(+), 11 deletions(-) rename osu.Game/Screens/Play/{ => HUD}/DefaultKeyCounter.cs (99%) rename osu.Game/Screens/Play/{ => HUD}/DefaultKeyCounterDisplay.cs (98%) rename osu.Game/Screens/Play/{ => HUD}/InputTrigger.cs (94%) rename osu.Game/Screens/Play/{ => HUD}/KeyCounter.cs (98%) rename osu.Game/Screens/Play/{ => HUD}/KeyCounterActionTrigger.cs (96%) rename osu.Game/Screens/Play/{ => HUD}/KeyCounterDisplay.cs (99%) rename osu.Game/Screens/Play/{ => HUD}/KeyCounterKeyboardTrigger.cs (95%) rename osu.Game/Screens/Play/{ => HUD}/KeyCounterMouseTrigger.cs (97%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index ec8fad9bf3..4e13bde755 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index d0c691e23f..3260ba8e33 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -3,10 +3,11 @@ #nullable disable +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; -using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osuTK.Input; namespace osu.Game.Tests.Visual.Gameplay diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 01d3bfa23e..aa7119829a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Gameplay; using osuTK.Input; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 9848894f84..808241729b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Gameplay; using osuTK.Input; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index 59a0f9cea8..224e7e411e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Overlays.Settings.Sections.Input; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Select; using osu.Game.Tests.Beatmaps.IO; using osuTK.Input; diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 64fe9c8a86..4f22c0c617 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -30,6 +30,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD.ClicksPerSecond; using osuTK; diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 32b2a19e21..c2f0b1a951 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -19,7 +19,7 @@ using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.Input.Handlers; using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Play; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD.ClicksPerSecond; using static osu.Game.Input.Handlers.ReplayInputHandler; diff --git a/osu.Game/Screens/Play/DefaultKeyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs similarity index 99% rename from osu.Game/Screens/Play/DefaultKeyCounter.cs rename to osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs index 3673281577..69a3e53dfc 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs @@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public partial class DefaultKeyCounter : KeyCounter { diff --git a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs similarity index 98% rename from osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs rename to osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 10f5a3cfe0..1d79b2d27a 100644 --- a/osu.Game/Screens/Play/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK.Graphics; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public partial class DefaultKeyCounterDisplay : KeyCounterDisplay { diff --git a/osu.Game/Screens/Play/InputTrigger.cs b/osu.Game/Screens/Play/HUD/InputTrigger.cs similarity index 94% rename from osu.Game/Screens/Play/InputTrigger.cs rename to osu.Game/Screens/Play/HUD/InputTrigger.cs index b8951b0f8e..34d286d697 100644 --- a/osu.Game/Screens/Play/InputTrigger.cs +++ b/osu.Game/Screens/Play/HUD/InputTrigger.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Graphics; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public abstract partial class InputTrigger : Component { diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/HUD/KeyCounter.cs similarity index 98% rename from osu.Game/Screens/Play/KeyCounter.cs rename to osu.Game/Screens/Play/HUD/KeyCounter.cs index 7ee9c94f62..4b3da4f785 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounter.cs @@ -5,7 +5,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public abstract partial class KeyCounter : Container { diff --git a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs similarity index 96% rename from osu.Game/Screens/Play/KeyCounterActionTrigger.cs rename to osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs index be0d259f85..1af69fdd81 100644 --- a/osu.Game/Screens/Play/KeyCounterActionTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public partial class KeyCounterActionTrigger : InputTrigger where T : struct diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs similarity index 99% rename from osu.Game/Screens/Play/KeyCounterDisplay.cs rename to osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 50670fb2fe..0dbae50466 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -13,7 +13,7 @@ using osu.Framework.Input.Events; using osu.Game.Configuration; using osuTK; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public abstract partial class KeyCounterDisplay : Container { diff --git a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs similarity index 95% rename from osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs rename to osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs index 1d89c58fc3..742cbc1569 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboardTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs @@ -6,7 +6,7 @@ using osu.Framework.Input.Events; using osuTK.Input; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public partial class KeyCounterKeyboardTrigger : InputTrigger { diff --git a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs similarity index 97% rename from osu.Game/Screens/Play/KeyCounterMouseTrigger.cs rename to osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs index e710c6e33f..cd71fef705 100644 --- a/osu.Game/Screens/Play/KeyCounterMouseTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs @@ -4,10 +4,10 @@ #nullable disable using osu.Framework.Input.Events; -using osuTK.Input; using osuTK; +using osuTK.Input; -namespace osu.Game.Screens.Play +namespace osu.Game.Screens.Play.HUD { public partial class KeyCounterMouseTrigger : InputTrigger { From 97ba236eb146fe69eb318aff6dce1db3ba8bf78d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 16:31:36 +0900 Subject: [PATCH 0273/1400] Add basic xmldoc to `KeyCounter` classes --- osu.Game/Screens/Play/HUD/InputTrigger.cs | 3 +++ osu.Game/Screens/Play/HUD/KeyCounter.cs | 3 +++ osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/InputTrigger.cs b/osu.Game/Screens/Play/HUD/InputTrigger.cs index 34d286d697..93b45daab3 100644 --- a/osu.Game/Screens/Play/HUD/InputTrigger.cs +++ b/osu.Game/Screens/Play/HUD/InputTrigger.cs @@ -6,6 +6,9 @@ using osu.Framework.Graphics; namespace osu.Game.Screens.Play.HUD { + /// + /// An event trigger which can be used with to create visual tracking of button/key presses. + /// public abstract partial class InputTrigger : Component { public event Action? OnActivate; diff --git a/osu.Game/Screens/Play/HUD/KeyCounter.cs b/osu.Game/Screens/Play/HUD/KeyCounter.cs index 4b3da4f785..93cc4f908a 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounter.cs @@ -7,6 +7,9 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Screens.Play.HUD { + /// + /// An individual key display which is intended to be displayed within a . + /// public abstract partial class KeyCounter : Container { public readonly InputTrigger Trigger; diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 0dbae50466..4080e561cd 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -15,6 +15,9 @@ using osuTK; namespace osu.Game.Screens.Play.HUD { + /// + /// A flowing display of all gameplay keys. Individual keys can be added using implementations. + /// public abstract partial class KeyCounterDisplay : Container { /// From 6a7c4d0bf7ffef86abc7eef6f34a09d26238ffc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 16:32:38 +0900 Subject: [PATCH 0274/1400] Remove `NRT` disables in new classes --- osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs | 2 -- osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs | 2 -- osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs | 2 -- 3 files changed, 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs index 1af69fdd81..e5951a8bf4 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterActionTrigger.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. -#nullable disable - using System.Collections.Generic; namespace osu.Game.Screens.Play.HUD diff --git a/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs index 742cbc1569..3052c1e666 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterKeyboardTrigger.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. -#nullable disable - using osu.Framework.Input.Events; using osuTK.Input; diff --git a/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs b/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs index cd71fef705..369aaa9f74 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterMouseTrigger.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. -#nullable disable - using osu.Framework.Input.Events; using osuTK; using osuTK.Input; From f7f1dff6471784c79a14c27e79f168597ca30a0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 16:45:33 +0900 Subject: [PATCH 0275/1400] Fix incorrect case of localisable string for "corner radius" --- .../Localisation/SkinComponents/SkinnableComponentStrings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs b/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs index 5cec9442e4..7c11ea6ac6 100644 --- a/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs +++ b/osu.Game/Localisation/SkinComponents/SkinnableComponentStrings.cs @@ -40,9 +40,9 @@ namespace osu.Game.Localisation.SkinComponents public static LocalisableString TextElementTextDescription => new TranslatableString(getKey(@"text_element_text_description"), "The text to be displayed."); /// - /// "Corner Radius" + /// "Corner radius" /// - public static LocalisableString CornerRadius => new TranslatableString(getKey(@"corner_radius"), "Corner Radius"); + public static LocalisableString CornerRadius => new TranslatableString(getKey(@"corner_radius"), "Corner radius"); /// /// "How rounded the corners should be." From d98199961b2d0820a3e4ff12816ac1c8e2190004 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 17:00:10 +0900 Subject: [PATCH 0276/1400] Adjust default sizing to fit a bit better with existing elements --- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 7 +++++-- osu.Game/Screens/Play/HUD/PlayerFlag.cs | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index f293199911..1c558aaa8a 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -28,9 +28,12 @@ namespace osu.Game.Screens.Play.HUD private readonly UpdateableAvatar avatar; + private const float default_size = 80f; + public PlayerAvatar() { - Size = new Vector2(128f); + Size = new Vector2(default_size); + InternalChild = avatar = new UpdateableAvatar(isInteractive: false) { RelativeSizeAxes = Axes.Both, @@ -43,7 +46,7 @@ namespace osu.Game.Screens.Play.HUD base.LoadComplete(); avatar.User = gameplayState.Score.ScoreInfo.User; - CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue * 128f, true); + CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue * default_size, true); } public bool UsesFixedAnchor { get; set; } diff --git a/osu.Game/Screens/Play/HUD/PlayerFlag.cs b/osu.Game/Screens/Play/HUD/PlayerFlag.cs index 17188d0009..bf65ee23d8 100644 --- a/osu.Game/Screens/Play/HUD/PlayerFlag.cs +++ b/osu.Game/Screens/Play/HUD/PlayerFlag.cs @@ -17,9 +17,11 @@ namespace osu.Game.Screens.Play.HUD private readonly UpdateableFlag flag; + private const float default_size = 40f; + public PlayerFlag() { - Size = new Vector2(114, 80); + Size = new Vector2(default_size, default_size / 1.4f); InternalChild = flag = new UpdateableFlag { RelativeSizeAxes = Axes.Both, From 5e90b67be09b842a9fb4b7114f49e4463afdce52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 17:01:29 +0900 Subject: [PATCH 0277/1400] Move `GameplayState` usage to BDL --- osu.Game/Screens/Play/HUD/PlayerFlag.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerFlag.cs b/osu.Game/Screens/Play/HUD/PlayerFlag.cs index bf65ee23d8..85799c03d3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerFlag.cs +++ b/osu.Game/Screens/Play/HUD/PlayerFlag.cs @@ -12,9 +12,6 @@ namespace osu.Game.Screens.Play.HUD { public partial class PlayerFlag : CompositeDrawable, ISerialisableDrawable { - [Resolved] - private GameplayState gameplayState { get; set; } = null!; - private readonly UpdateableFlag flag; private const float default_size = 40f; @@ -28,10 +25,9 @@ namespace osu.Game.Screens.Play.HUD }; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(GameplayState gameplayState) { - base.LoadComplete(); - flag.CountryCode = gameplayState.Score.ScoreInfo.User.CountryCode; } From 5af41bb1c81054205c4cb77ccc9b0faf4686288d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 17:24:17 +0900 Subject: [PATCH 0278/1400] Move filter matching code into own method to simplify early returns --- .../Select/Carousel/CarouselBeatmap.cs | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 2cfa163b7a..7e48bc5cdd 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -26,6 +26,11 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); + Filtered.Value = !checkMatch(criteria); + } + + private bool checkMatch(FilterCriteria criteria) + { bool match = criteria.Ruleset == null || BeatmapInfo.Ruleset.ShortName == criteria.Ruleset.ShortName || @@ -34,8 +39,7 @@ namespace osu.Game.Screens.Select.Carousel if (BeatmapInfo.BeatmapSet?.Equals(criteria.SelectedBeatmapSet) == true) { // only check ruleset equality or convertability for selected beatmap - Filtered.Value = !match; - return; + return match; } match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(BeatmapInfo.StarRating); @@ -49,11 +53,7 @@ namespace osu.Game.Screens.Select.Carousel match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(BeatmapInfo.BeatDivisor); match &= !criteria.OnlineStatus.HasFilter || criteria.OnlineStatus.IsInRange(BeatmapInfo.Status); - if (!match) - { - Filtered.Value = !match; - return; - } + if (!match) return false; match &= !criteria.Creator.HasFilter || criteria.Creator.Matches(BeatmapInfo.Metadata.Author.Username); match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(BeatmapInfo.Metadata.Artist) || @@ -61,11 +61,7 @@ namespace osu.Game.Screens.Select.Carousel match &= !criteria.UserStarDifficulty.HasFilter || criteria.UserStarDifficulty.IsInRange(BeatmapInfo.StarRating); - if (!match) - { - Filtered.Value = !match; - return; - } + if (!match) return false; if (criteria.SearchTerms.Length > 0) { @@ -99,18 +95,14 @@ namespace osu.Game.Screens.Select.Carousel } } - if (!match) - { - Filtered.Value = !match; - return; - } + if (!match) return false; match &= criteria.CollectionBeatmapMD5Hashes?.Contains(BeatmapInfo.MD5Hash) ?? true; if (match && criteria.RulesetCriteria != null) match &= criteria.RulesetCriteria.Matches(BeatmapInfo); - Filtered.Value = !match; + return match; } public override int CompareTo(FilterCriteria criteria, CarouselItem other) From dc2945f4f8635a08c83c84fd57f65c6da4eb8e47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 17:39:21 +0900 Subject: [PATCH 0279/1400] Move avatar user loading to BDL also --- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index 1c558aaa8a..e3fab499f3 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -23,9 +23,6 @@ namespace osu.Game.Screens.Play.HUD Precision = 0.01f }; - [Resolved] - private GameplayState gameplayState { get; set; } = null!; - private readonly UpdateableAvatar avatar; private const float default_size = 80f; @@ -41,11 +38,16 @@ namespace osu.Game.Screens.Play.HUD }; } + [BackgroundDependencyLoader] + private void load(GameplayState gameplayState) + { + avatar.User = gameplayState.Score.ScoreInfo.User; + } + protected override void LoadComplete() { base.LoadComplete(); - avatar.User = gameplayState.Score.ScoreInfo.User; CornerRadius.BindValueChanged(e => avatar.CornerRadius = e.NewValue * default_size, true); } From 55467fcbe35cc6c8c7a94740c372b665eaa77519 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 18:00:37 +0900 Subject: [PATCH 0280/1400] Update xmldoc for `DangerousActionDialog` to match new behaviour --- osu.Game/Overlays/Dialog/DangerousActionDialog.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/DangerousActionDialog.cs b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs index 85cae5e0d2..c86570386f 100644 --- a/osu.Game/Overlays/Dialog/DangerousActionDialog.cs +++ b/osu.Game/Overlays/Dialog/DangerousActionDialog.cs @@ -8,10 +8,14 @@ using osu.Game.Localisation; namespace osu.Game.Overlays.Dialog { /// - /// Base class for various confirmation dialogs that concern deletion actions. + /// A dialog which provides confirmation for actions which result in permanent consequences. /// Differs from in that the confirmation button is a "dangerous" one /// (requires the confirm button to be held). /// + /// + /// The default implementation comes with text for a generic deletion operation. + /// This can be further customised by specifying custom . + /// public abstract partial class DangerousActionDialog : PopupDialog { /// From 26ef7c2637ddde346c65ff6bd853a48c03d5863e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 18:01:13 +0900 Subject: [PATCH 0281/1400] Rename confirmation dialog class to mention `revert` not `reset` --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index a7fe459aa4..c6d190502b 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -153,7 +153,7 @@ namespace osu.Game.Overlays.SkinEditor Items = new[] { new EditorMenuItem(Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), - new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new ResetConfirmDialog(revert))), + new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new RevertConfirmDialog(revert))), new EditorMenuItemSpacer(), new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), }, @@ -630,9 +630,9 @@ namespace osu.Game.Overlays.SkinEditor } } - public partial class ResetConfirmDialog : DangerousActionDialog + public partial class RevertConfirmDialog : DangerousActionDialog { - public ResetConfirmDialog(Action revert) + public RevertConfirmDialog(Action revert) { HeaderText = SkinEditorStrings.RevertToDefaultDescription; BodyText = SkinEditorStrings.ResetDialogue; From 97bee4db89048419265aeb9a1a6c9ffa478cc68a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Mar 2023 18:07:53 +0900 Subject: [PATCH 0282/1400] Fix localisations --- osu.Game/Localisation/SkinEditorStrings.cs | 9 ++------- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game/Localisation/SkinEditorStrings.cs b/osu.Game/Localisation/SkinEditorStrings.cs index a6b59418fd..3c1d1ff40d 100644 --- a/osu.Game/Localisation/SkinEditorStrings.cs +++ b/osu.Game/Localisation/SkinEditorStrings.cs @@ -45,14 +45,9 @@ namespace osu.Game.Localisation public static LocalisableString CurrentlyEditing => new TranslatableString(getKey(@"currently_editing"), @"Currently editing"); /// - /// "Revert to default." + /// "All layout elements for layers in the current screen will be reset to defaults." /// - public static LocalisableString RevertToDefaultDescription => new TranslatableString(getKey(@"revert_to_default"), @"Revert to default."); - - /// - /// "Return the skin to its default state" - /// - public static LocalisableString ResetDialogue => new TranslatableString(getKey(@"return_the_skin_to_its"), @"Return the skin to its default state"); + public static LocalisableString RevertToDefaultDescription => new TranslatableString(getKey(@"revert_to_default_description"), @"All layout elements for layers in the current screen will be reset to defaults."); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index c6d190502b..ac40d1335e 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -634,8 +634,8 @@ namespace osu.Game.Overlays.SkinEditor { public RevertConfirmDialog(Action revert) { - HeaderText = SkinEditorStrings.RevertToDefaultDescription; - BodyText = SkinEditorStrings.ResetDialogue; + HeaderText = CommonStrings.RevertToDefault; + BodyText = SkinEditorStrings.RevertToDefaultDescription; DangerousAction = revert; } } From 54564e05578df03133636cad564becd6b892378f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 7 Mar 2023 21:13:35 +0900 Subject: [PATCH 0283/1400] new design --- .../UserInterface/TestSceneModPresetColumn.cs | 86 ++----------------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 62 ++++++------- 2 files changed, 38 insertions(+), 110 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 8fbc8940c7..d6065374ac 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -296,7 +296,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("clear preset name", () => popover.ChildrenOfType().First().Current.Value = ""); AddStep("attempt preset edit", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); @@ -306,7 +306,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); @@ -345,91 +345,15 @@ namespace osu.Game.Tests.Visual.UserInterface OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddStep("enable switch", () => popover.ChildrenOfType().Single().Current.Value = true); - AddStep("attempt preset edit", () => + AddStep("click use current mods", () => { - InputManager.MoveMouseTo(popover.ChildrenOfType().Single()); + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); } - [Test] - public void TestEditModSwitchDisableWithNoModSelest() - { - ModPresetColumn modPresetColumn = null!; - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddStep("click edit", () => - { - var editItem = this.ChildrenOfType().ElementAt(0); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - - OsuPopover? popover = null; - AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - } - - [Test] - public void TestEditModSwitchDisableWithPresetSelest() - { - ModPresetColumn modPresetColumn = null!; - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); - AddStep("select first preset mod", () => - SelectedMods.Value = this.ChildrenOfType().First().Preset.Value.Mods.ToList()); - - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddStep("click edit", () => - { - var editItem = this.ChildrenOfType().ElementAt(0); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - - OsuPopover? popover = null; - AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); - AddAssert("use current mod is enabled", () => popover.ChildrenOfType().Single().Current.Value); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddAssert("use current mod is disblaed", () => popover.ChildrenOfType().Single().Current.Value == false); - AddAssert("use current mod switch cannot be switch", () => popover.ChildrenOfType().Single().Current.Disabled); - } - private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 270b6f43d9..4eaf5e19db 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; - private readonly LabelledSwitchButton useCurrentSwitch; + private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; [Resolved] @@ -42,6 +42,7 @@ namespace osu.Game.Overlays.Mods Width = 300, AutoSizeAxes = Axes.Y, Spacing = new Vector2(7), + Direction = FillDirection.Vertical, Children = new Drawable[] { nameTextBox = new LabelledTextBox @@ -58,18 +59,30 @@ namespace osu.Game.Overlays.Mods Label = CommonStrings.Description, TabbableContentContainer = this }, - useCurrentSwitch = new LabelledSwitchButton + new FillFlowContainer { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Label = "Use Current Mod select", - }, - createButton = new ShearedButton - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = CommonStrings.MenuBarEdit, - Action = tryEditPreset + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(7), + Children = new Drawable[] + { + useCurrentModButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Use Current Mods", + Action = trySaveCurrentMod + }, + createButton = new ShearedButton + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, + Action = tryEditPreset + }, + } } } }; @@ -84,28 +97,24 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - selectedMods.BindValueChanged(_ => updateMods(), true); - createButton.DarkerColour = colours.Orange1; createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; + + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; } - private void updateMods() + private void trySaveCurrentMod() { - useCurrentSwitch.Current.Disabled = false; + if (button.Active.Value || !selectedMods.Value.Any()) + return; - // disable the switch when mod is equal. - if (button.Active.Value) + button.Preset.PerformWrite(s => { - useCurrentSwitch.Current.Value = true; - useCurrentSwitch.Current.Disabled = true; - } - else - { - useCurrentSwitch.Current.Value = false; - useCurrentSwitch.Current.Disabled = !selectedMods.Value.Any(); - } + s.Mods = selectedMods.Value.ToArray(); + }); } protected override void LoadComplete() @@ -127,11 +136,6 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - - if (useCurrentSwitch.Current.Value) - { - s.Mods = selectedMods.Value.ToArray(); - } }); this.HidePopover(); From 5191204569241e0e92c93b51681a9384d711a019 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Mar 2023 15:39:43 +0300 Subject: [PATCH 0284/1400] Bring truncating logic back to `Export` method --- osu.Game/Database/LegacyExporter.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 0fa7b9e03c..9981e08442 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -48,15 +48,7 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } - protected virtual string GetFilename(TModel item) - { - string filename = item.GetDisplayString(); - - if (filename.Length > MAX_FILENAME_LENGTH - FileExtension.Length) - return filename.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); - - return filename; - } + protected virtual string GetFilename(TModel item) => item.GetDisplayString(); /// /// Exports an item to a legacy (.zip based) package. @@ -73,6 +65,14 @@ namespace osu.Game.Database string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); + if (filename.Length > MAX_FILENAME_LENGTH) + { + string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); + + filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); + filename = $"{filenameWithoutExtension}{FileExtension}"; + } + using (var stream = exportStorage.CreateFileSafely(filename)) ExportModelTo(item, stream); From 7107834b9ec297062ff29442fa1a550c03ff5a94 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Mar 2023 15:43:03 +0300 Subject: [PATCH 0285/1400] Fix truncating bug --- osu.Game/Database/LegacyExporter.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 9981e08442..8da285daa3 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -58,6 +58,9 @@ namespace osu.Game.Database { string itemFilename = GetFilename(item).GetValidFilename(); + if (itemFilename.Length > MAX_FILENAME_LENGTH - FileExtension.Length) + itemFilename = itemFilename.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); + IEnumerable existingExports = exportStorage .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") @@ -65,14 +68,6 @@ namespace osu.Game.Database string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - if (filename.Length > MAX_FILENAME_LENGTH) - { - string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); - - filenameWithoutExtension = filenameWithoutExtension.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); - filename = $"{filenameWithoutExtension}{FileExtension}"; - } - using (var stream = exportStorage.CreateFileSafely(filename)) ExportModelTo(item, stream); From bedf4cc2596f9202a8760cbbe731ca2f1f6bf8ed Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 7 Mar 2023 16:03:11 +0100 Subject: [PATCH 0286/1400] Remove extra code --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index a354a22fb7..75efc07d43 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -553,8 +553,6 @@ namespace osu.Game.Tests.Visual.UserInterface waitForColumnLoad(); AddAssert("unimplemented mod panel is filtered", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value); - - AddStep("disable panel filtering", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value = false); } [Test] From 7ade525eef4a3c887de1d50123682140ee9c605a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 7 Mar 2023 19:43:52 +0100 Subject: [PATCH 0287/1400] Display corner radius setting as percentage --- .../Settings/SettingsPercentageSlider.cs | 20 +++++++++++++++++++ .../Rulesets/Mods/ModAccuracyChallenge.cs | 11 +--------- osu.Game/Screens/Play/HUD/PlayerAvatar.cs | 4 +++- 3 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Overlays/Settings/SettingsPercentageSlider.cs diff --git a/osu.Game/Overlays/Settings/SettingsPercentageSlider.cs b/osu.Game/Overlays/Settings/SettingsPercentageSlider.cs new file mode 100644 index 0000000000..fa59d18de1 --- /dev/null +++ b/osu.Game/Overlays/Settings/SettingsPercentageSlider.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Settings +{ + /// + /// A that displays its value as a percentage by default. + /// Mostly provided for convenience of use with . + /// + public partial class SettingsPercentageSlider : SettingsSlider + where TValue : struct, IEquatable, IComparable, IConvertible + { + protected override Drawable CreateControl() => ((RoundedSliderBar)base.CreateControl()).With(sliderBar => sliderBar.DisplayAsPercentage = true); + } +} diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index dc7594f469..d4223a80c2 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Judgements; @@ -33,7 +32,7 @@ namespace osu.Game.Rulesets.Mods public override string SettingDescription => base.SettingDescription.Replace(MinimumAccuracy.ToString(), MinimumAccuracy.Value.ToString("##%", NumberFormatInfo.InvariantInfo)); - [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsSlider))] + [SettingSource("Minimum accuracy", "Trigger a failure if your accuracy goes below this value.", SettingControlType = typeof(SettingsPercentageSlider))] public BindableNumber MinimumAccuracy { get; } = new BindableDouble { MinValue = 0.60, @@ -69,12 +68,4 @@ namespace osu.Game.Rulesets.Mods return scoreProcessor.ComputeAccuracy(score); } } - - public partial class PercentSlider : RoundedSliderBar - { - public PercentSlider() - { - DisplayAsPercentage = true; - } - } } diff --git a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs index e3fab499f3..1d0331593a 100644 --- a/osu.Game/Screens/Play/HUD/PlayerAvatar.cs +++ b/osu.Game/Screens/Play/HUD/PlayerAvatar.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Localisation.SkinComponents; +using osu.Game.Overlays.Settings; using osu.Game.Skinning; using osu.Game.Users.Drawables; using osuTK; @@ -15,7 +16,8 @@ namespace osu.Game.Screens.Play.HUD { public partial class PlayerAvatar : CompositeDrawable, ISerialisableDrawable { - [SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.CornerRadius), nameof(SkinnableComponentStrings.CornerRadiusDescription))] + [SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.CornerRadius), nameof(SkinnableComponentStrings.CornerRadiusDescription), + SettingControlType = typeof(SettingsPercentageSlider))] public new BindableFloat CornerRadius { get; set; } = new BindableFloat(0.25f) { MinValue = 0, From 9ea93e0a9fb7b5a9d629519cd6e257e80acd1510 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 7 Mar 2023 20:38:33 +0100 Subject: [PATCH 0288/1400] Add more tests --- osu.Game.Tests/Mods/ModSettingsTest.cs | 91 +++++++++++++++++++++----- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index 99198f6bae..45e162df1a 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.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 System; using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Localisation; @@ -37,34 +38,92 @@ namespace osu.Game.Tests.Mods } [Test] - public void TestCopySharedSettingsOfDifferentType() + public void TestDifferentTypeSettingsKeptWhenCopied() { - const double setting_change = 2.5; + const double setting_change = 50.4; - var osuMod = new TestNonMatchinSettingTypeOsuMod(); - var maniaMod = new TestNonMatchinSettingTypeManiaMod(); + var modDouble = new TestNonMatchingSettingTypeModDouble(); + var modBool = new TestNonMatchingSettingTypeModBool(); - osuMod.TestSetting.Value = setting_change; - maniaMod.CopySharedSettings(osuMod); - osuMod.CopySharedSettings(maniaMod); + modDouble.TestSetting.Value = setting_change; + modBool.TestSetting.Value = !modBool.TestSetting.Default; + modDouble.CopySharedSettings(modBool); + modBool.CopySharedSettings(modDouble); - Assert.That(maniaMod.TestSetting.IsDefault, "Value has been changed"); - Assert.That(osuMod.TestSetting.Value == setting_change); + Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); + Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); } - private class TestNonMatchinSettingTypeOsuMod : TestNonMatchinSettingTypeMod + [Test] + public void TestCopyDoubleToIntWithDefaultRange() { - public override string Acronym => "NMO"; - public override BindableNumber TestSetting { get; } = new BindableDouble(3.5); + const double setting_change = 50.4; + + var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { Value = setting_change } }; + var modInt = new TestNonMatchingSettingTypeModInt(); + + modInt.CopySharedSettings(modDouble); + + Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change)); } - private class TestNonMatchinSettingTypeManiaMod : TestNonMatchinSettingTypeMod + [Test] + public void TestCopyIntToDoubleWithDefaultRange() { - public override string Acronym => "NMM"; - public override Bindable TestSetting { get; } = new BindableBool(true); + const int setting_change = 50; + + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = setting_change } }; + var modDouble = new TestNonMatchingSettingTypeModDouble(); + + modDouble.CopySharedSettings(modInt); + + Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); } - private abstract class TestNonMatchinSettingTypeMod : Mod + [Test] + public void TestCopyDoubleToIntWithClampedRange() + { + const double setting_change = 50.4; + + var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 100, MinValue = 0, Value = setting_change } }; + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MaxValue = 200, MinValue = 0 } }; + + modInt.CopySharedSettings(modDouble); + + Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change * 2))); + } + + [Test] + public void TestDefaultValueKeptWhenCopied() + { + var modBoolTrue = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = true, Value = false } }; + var modBoolFalse = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; + + modBoolFalse.CopySharedSettings(modBoolTrue); + + Assert.That(modBoolFalse.TestSetting.Default, Is.EqualTo(false)); + Assert.That(modBoolFalse.TestSetting.Value, Is.EqualTo(modBoolTrue.TestSetting.Value)); + } + + private class TestNonMatchingSettingTypeModDouble : TestNonMatchingSettingTypeMod + { + public override string Acronym => "NMD"; + public override BindableNumber TestSetting { get; } = new BindableDouble(); + } + + private class TestNonMatchingSettingTypeModInt : TestNonMatchingSettingTypeMod + { + public override string Acronym => "NMI"; + public override BindableNumber TestSetting { get; } = new BindableInt(); + } + + private class TestNonMatchingSettingTypeModBool : TestNonMatchingSettingTypeMod + { + public override string Acronym => "NMB"; + public override Bindable TestSetting { get; } = new BindableBool(); + } + + private abstract class TestNonMatchingSettingTypeMod : Mod { public override string Name => "Non-matching setting type mod"; public override LocalisableString Description => "Description"; From 8bf84869a5334c14aec47ebeb43470c8a0d808a1 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 7 Mar 2023 20:39:50 +0100 Subject: [PATCH 0289/1400] Fixed errors covered in new tests --- osu.Game/Rulesets/Mods/Mod.cs | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index f6c0e851fd..e630a53045 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -165,6 +165,10 @@ namespace osu.Game.Rulesets.Mods /// The mod to copy properties from. internal void CopySharedSettings(Mod source) { + const string min_value = nameof(BindableNumber.MinValue); + const string max_value = nameof(BindableNumber.MaxValue); + const string value = nameof(Bindable.Value); + Dictionary oldSettings = new Dictionary(); foreach (var (_, property) in source.GetSettingsSourceProperties()) @@ -190,27 +194,47 @@ namespace osu.Game.Rulesets.Mods { if (getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single()) + { // change settings only if the type is the same - CopyAdjustedSetting((IBindable)targetSetting, sourceSetting); + setValue(targetSetting, value, getValue(sourceSetting, value)); + } continue; } - double targetMin = getValue(targetSetting, nameof(IBindableNumber.MinValue)); - double targetMax = getValue(targetSetting, nameof(IBindableNumber.MaxValue)); - double sourceMin = getValue(sourceSetting, nameof(IBindableNumber.MinValue)); - double sourceMax = getValue(sourceSetting, nameof(IBindableNumber.MaxValue)); - double sourceValue = getValue(sourceSetting, nameof(IBindableNumber.Value)); + Type targetGenericType = targetType.GenericTypeArguments.Single(); + Type sourceGenericType = sourceType.GenericTypeArguments.Single(); + + double allowedMin = Math.Max( + Convert.ToDouble(targetGenericType.GetField("MinValue")!.GetValue(null)), + Convert.ToDouble(sourceGenericType.GetField("MinValue")!.GetValue(null)) + ); + + double allowedMax = Math.Min( + Convert.ToDouble(targetGenericType.GetField("MaxValue")!.GetValue(null)), + Convert.ToDouble(sourceGenericType.GetField("MaxValue")!.GetValue(null)) + ); + + double targetMin = getValueDouble(targetSetting, min_value); + double targetMax = getValueDouble(targetSetting, max_value); + double sourceMin = getValueDouble(sourceSetting, min_value); + double sourceMax = getValueDouble(sourceSetting, max_value); + double sourceValue = getValueDouble(sourceSetting, value); // convert value to same ratio double targetValue = (sourceValue - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin; - targetType.GetProperty(nameof(IBindableNumber.Value))!.SetValue(targetSetting, - Convert.ChangeType(targetValue, targetType.GenericTypeArguments.Single())); + setValue(targetSetting, value, Convert.ChangeType(targetValue, targetType.GenericTypeArguments.Single())); + + double getValueDouble(object target, string name) => + Math.Clamp(Convert.ToDouble(getValue(target, name)!), allowedMin, allowedMax); } - double getValue(object target, string name) => - Convert.ToDouble(target.GetType().GetProperty(name)!.GetValue(target)!); + object? getValue(object target, string name) => + target.GetType().GetProperty(name)!.GetValue(target); + + void setValue(object target, string name, object? newValue) => + target.GetType().GetProperty(name)!.SetValue(target, newValue); Type? getGenericBaseType(object target, Type genericType) => target.GetType().GetTypeInheritance().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == genericType); From f711915e5fd89447a98322b7eb8070f218770a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 7 Mar 2023 21:16:30 +0100 Subject: [PATCH 0290/1400] Remove unused using directive --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 4e13bde755..b90081a29f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -21,7 +21,6 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI.Cursor; -using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osu.Game.Tests.Visual; using osuTK; From 98f40b2679bb37f7b15f2ea7a33f6971cda91b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 7 Mar 2023 21:22:59 +0100 Subject: [PATCH 0291/1400] Improve documentation of `InputTrigger` --- osu.Game/Screens/Play/HUD/InputTrigger.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/InputTrigger.cs b/osu.Game/Screens/Play/HUD/InputTrigger.cs index 93b45daab3..b57f2cdf91 100644 --- a/osu.Game/Screens/Play/HUD/InputTrigger.cs +++ b/osu.Game/Screens/Play/HUD/InputTrigger.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; namespace osu.Game.Screens.Play.HUD @@ -11,8 +10,20 @@ namespace osu.Game.Screens.Play.HUD /// public abstract partial class InputTrigger : Component { - public event Action? OnActivate; - public event Action? OnDeactivate; + /// + /// Callback to invoke when the associated input has been activated. + /// + /// Whether gameplay is progressing in the forward direction time-wise. + public delegate void OnActivateCallback(bool forwardPlayback); + + /// + /// Callback to invoke when the associated input has been deactivated. + /// + /// Whether gameplay is progressing in the forward direction time-wise. + public delegate void OnDeactivateCallback(bool forwardPlayback); + + public event OnActivateCallback? OnActivate; + public event OnDeactivateCallback? OnDeactivate; protected InputTrigger(string name) { From 12af002c4d81dcc98b60e4c5058aeccfdd676f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 7 Mar 2023 21:28:42 +0100 Subject: [PATCH 0292/1400] Reorder and add xmldoc to `KeyCounter` members --- osu.Game/Screens/Play/HUD/KeyCounter.cs | 26 ++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/KeyCounter.cs b/osu.Game/Screens/Play/HUD/KeyCounter.cs index 93cc4f908a..2a4ab1993a 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounter.cs @@ -12,21 +12,35 @@ namespace osu.Game.Screens.Play.HUD /// public abstract partial class KeyCounter : Container { + /// + /// The which activates and deactivates this . + /// public readonly InputTrigger Trigger; - private readonly Container content; - - protected override Container Content => content; + /// + /// Whether the actions reported by should be counted. + /// + public Bindable IsCounting { get; } = new BindableBool(true); private readonly Bindable countPresses = new BindableInt { MinValue = 0 }; - public Bindable IsCounting { get; } = new BindableBool(true); - + /// + /// The current count of registered key presses. + /// public IBindable CountPresses => countPresses; + private readonly Container content; + + protected override Container Content => content; + + /// + /// Whether this is currently in the "activated" state because the associated key is currently pressed. + /// + protected readonly Bindable IsActive = new BindableBool(); + protected KeyCounter(InputTrigger trigger) { InternalChildren = new Drawable[] @@ -44,8 +58,6 @@ namespace osu.Game.Screens.Play.HUD Name = trigger.Name; } - protected readonly Bindable IsActive = new BindableBool(); - private void increment() { if (!IsCounting.Value) From 44297a7d0a01e44f24d2860cdd4ce2584988e341 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 8 Mar 2023 00:47:16 +0000 Subject: [PATCH 0293/1400] refactor: make KCD a `CompositeDrawable` --- .../Visual/Gameplay/TestSceneAutoplay.cs | 4 +-- .../Gameplay/TestSceneGameplayRewinding.cs | 4 +-- .../Visual/Gameplay/TestSceneKeyCounter.cs | 4 +-- .../Visual/Gameplay/TestSceneReplay.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 4 +-- .../Play/HUD/DefaultKeyCounterDisplay.cs | 28 ++++--------------- .../Screens/Play/HUD/KeyCounterDisplay.cs | 25 ++++------------- 7 files changed, 20 insertions(+), 51 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 903cd178b7..f3f942b74b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -35,14 +35,14 @@ namespace osu.Game.Tests.Visual.Gameplay var referenceBeatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 2)); + AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Counters.Any(kc => kc.CountPresses.Value > 2)); seekTo(referenceBeatmap.Breaks[0].StartTime); AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting.Value); AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType().Single().AccuracyDisplay.Current.Value == 1); AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000)); - AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses.Value == 0)); + AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Counters.All(kc => kc.CountPresses.Value == 0)); seekTo(referenceBeatmap.HitObjects[^1].GetEndTime()); AddUntilStep("results displayed", () => getResultsScreen()?.IsLoaded == true); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 9f485cd7bf..751aeb4e13 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -31,11 +31,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); - AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Select(kc => kc.CountPresses.Value).Sum() == 15); + AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Counters.Select(kc => kc.CountPresses.Value).Sum() == 15); AddStep("clear results", () => Player.Results.Clear()); addSeekStep(0); AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged)); - AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses.Value == 0)); + AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Counters.All(kc => kc.CountPresses.Value == 0)); AddAssert("no results triggered", () => Player.Results.Count == 0); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 3260ba8e33..6dc07ca9d3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Gameplay new KeyCounterMouseTrigger(MouseButton.Right), }); - var testCounter = (DefaultKeyCounter)kc.Children.First(); + var testCounter = (DefaultKeyCounter)kc.Counters.First(); AddStep("Add random", () => { @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay kc.AddTrigger(new KeyCounterKeyboardTrigger(key)); }); - Key testKey = ((KeyCounterKeyboardTrigger)kc.Children.First().Trigger).Key; + Key testKey = ((KeyCounterKeyboardTrigger)kc.Counters.First().Trigger).Key; void addPressKeyStep() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index 542686f0cd..bf9b13b320 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 0)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Counters.Any(kc => kc.CountPresses.Value > 0)); AddAssert("cannot fail", () => !((ScoreAccessibleReplayPlayer)Player).AllowFail); } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index c2f0b1a951..ea9dc3fb01 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -176,14 +176,14 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(KeyBindingPressEvent e) => Target.Children.Where(c => c.Trigger is KeyCounterActionTrigger) + public bool OnPressed(KeyBindingPressEvent e) => Target.Counters.Where(c => c.Trigger is KeyCounterActionTrigger) .Select(c => (KeyCounterActionTrigger)c.Trigger) .Any(c => c.OnPressed(e.Action, Clock.Rate >= 0)); public void OnReleased(KeyBindingReleaseEvent e) { foreach (var c - in Target.Children.Where(c => c.Trigger is KeyCounterActionTrigger).Select(c => (KeyCounterActionTrigger)c.Trigger)) + in Target.Counters.Where(c => c.Trigger is KeyCounterActionTrigger).Select(c => (KeyCounterActionTrigger)c.Trigger)) c.OnReleased(e.Action, Clock.Rate >= 0); } } diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 1d79b2d27a..9499263474 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -13,18 +13,11 @@ namespace osu.Game.Screens.Play.HUD private const int duration = 100; private const double key_fade_time = 80; - private readonly FillFlowContainer keyFlow = new FillFlowContainer(); + private readonly FillFlowContainer keyFlow = new FillFlowContainer(); - protected override Container Content => keyFlow; - - public new IReadOnlyList Children - { - get => (IReadOnlyList)base.Children; - set => base.Children = value; - } + public override IEnumerable Counters => keyFlow; public DefaultKeyCounterDisplay() - : base(typeof(DefaultKeyCounter)) { keyFlow.Direction = FillDirection.Horizontal; keyFlow.AutoSizeAxes = Axes.Both; @@ -45,23 +38,12 @@ namespace osu.Game.Screens.Play.HUD public override void AddTrigger(InputTrigger trigger) { DefaultKeyCounter key = new DefaultKeyCounter(trigger); - Add(key); + keyFlow.Add(key); key.FadeTime = key_fade_time; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; } - public override void Add(KeyCounter key) - { - base.Add(key); - - DefaultKeyCounter defaultKey = (DefaultKeyCounter)key; - - defaultKey.FadeTime = key_fade_time; - defaultKey.KeyDownTextColor = KeyDownTextColor; - defaultKey.KeyUpTextColor = KeyUpTextColor; - } - protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. keyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); @@ -76,7 +58,7 @@ namespace osu.Game.Screens.Play.HUD if (value != keyDownTextColor) { keyDownTextColor = value; - foreach (var child in Children) + foreach (var child in keyFlow) child.KeyDownTextColor = value; } } @@ -92,7 +74,7 @@ namespace osu.Game.Screens.Play.HUD if (value != keyUpTextColor) { keyUpTextColor = value; - foreach (var child in Children) + foreach (var child in keyFlow) child.KeyUpTextColor = value; } } diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 4080e561cd..9a28d40418 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Play.HUD /// /// A flowing display of all gameplay keys. Individual keys can be added using implementations. /// - public abstract partial class KeyCounterDisplay : Container + public abstract partial class KeyCounterDisplay : CompositeDrawable { /// /// Whether the key counter should be visible regardless of the configuration value. @@ -26,6 +26,11 @@ namespace osu.Game.Screens.Play.HUD /// public Bindable AlwaysVisible { get; } = new Bindable(true); + /// + /// The s contained in this . + /// + public abstract IEnumerable Counters { get; } + public Bindable IsCounting { get; } = new BindableBool(true); protected readonly Bindable ConfigVisibility = new Bindable(); @@ -34,13 +39,6 @@ namespace osu.Game.Screens.Play.HUD private Receptor? receptor; - private readonly Type[] acceptedTypes; - - protected KeyCounterDisplay(params Type[] acceptedTypes) - { - this.acceptedTypes = acceptedTypes; - } - public void SetReceptor(Receptor receptor) { if (this.receptor != null) @@ -53,17 +51,6 @@ namespace osu.Game.Screens.Play.HUD public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); - public override void Add(KeyCounter counter) - { - if (!checkType(counter)) - throw new InvalidOperationException($"{counter.GetType()} is not a supported counter type. (hint: you may want to use {nameof(AddTrigger)} instead.)"); - - base.Add(counter); - counter.IsCounting.BindTo(IsCounting); - } - - private bool checkType(KeyCounter counter) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(counter)); - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 5b0db94a242a8e5896806a4e76831d399b33010a Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 8 Mar 2023 00:58:54 +0000 Subject: [PATCH 0294/1400] docs: add XMLDoc for methods in KCD --- osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 9a28d40418..0e0f8a1190 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -31,6 +31,9 @@ namespace osu.Game.Screens.Play.HUD /// public abstract IEnumerable Counters { get; } + /// + /// Whether the actions reported by all s within this should be counted. + /// public Bindable IsCounting { get; } = new BindableBool(true); protected readonly Bindable ConfigVisibility = new Bindable(); @@ -47,8 +50,16 @@ namespace osu.Game.Screens.Play.HUD this.receptor = receptor; } + /// + /// Adds a new to this . + /// + /// The the resulting will react to. public abstract void AddTrigger(InputTrigger trigger); + /// + /// Adds a range of new s to this . + /// + /// The s the resulting s will react to. public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); [BackgroundDependencyLoader] From 5d15426c275084144d68e8790f0275d985c52269 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 8 Mar 2023 01:52:12 +0000 Subject: [PATCH 0295/1400] refactor: make `Counters` return a `Container` --- osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs | 9 ++++----- osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 9499263474..dce0be9cde 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK.Graphics; @@ -13,9 +12,9 @@ namespace osu.Game.Screens.Play.HUD private const int duration = 100; private const double key_fade_time = 80; - private readonly FillFlowContainer keyFlow = new FillFlowContainer(); + private readonly FillFlowContainer keyFlow = new FillFlowContainer(); - public override IEnumerable Counters => keyFlow; + public override Container Counters => keyFlow; public DefaultKeyCounterDisplay() { @@ -59,7 +58,7 @@ namespace osu.Game.Screens.Play.HUD { keyDownTextColor = value; foreach (var child in keyFlow) - child.KeyDownTextColor = value; + ((DefaultKeyCounter)child).KeyDownTextColor = value; } } } @@ -75,7 +74,7 @@ namespace osu.Game.Screens.Play.HUD { keyUpTextColor = value; foreach (var child in keyFlow) - child.KeyUpTextColor = value; + ((DefaultKeyCounter)child).KeyUpTextColor = value; } } } diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 0e0f8a1190..2c90d1474d 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Play.HUD /// /// The s contained in this . /// - public abstract IEnumerable Counters { get; } + public abstract Container Counters { get; } /// /// Whether the actions reported by all s within this should be counted. From 245c3c025c9fa2dd4e75c279fa41b2281b3abfdb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Mar 2023 19:23:32 +0900 Subject: [PATCH 0296/1400] Refactor `endClickSelection` to reduce nesting --- .../Compose/Components/BlueprintContainer.cs | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 87cee59d83..3bf9f42957 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -382,52 +382,48 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Whether a click selection was active. private bool endClickSelection(MouseButtonEvent e) { - if (!clickSelectionHandled && !isDraggingBlueprint) + // If already handled a selection or drag, we don't want to perform a mouse up / click action. + if (clickSelectionHandled || isDraggingBlueprint) return true; + + if (e.Button != MouseButton.Left) return false; + + if (e.ControlPressed) { - if (e.Button == MouseButton.Left) - { - if (e.ControlPressed) - { - // if a selection didn't occur, we may want to trigger a deselection. + // if a selection didn't occur, we may want to trigger a deselection. - // Iterate from the top of the input stack (blueprints closest to the front of the screen first). - // Priority is given to already-selected blueprints. - foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren.OrderByDescending(b => b.IsSelected)) - { - if (!blueprint.IsHovered) continue; - - return clickSelectionHandled = SelectionHandler.MouseUpSelectionRequested(blueprint, e); - } - } - else if (selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) - { - // If a click occurred and was handled by the currently selected blueprint but didn't result in a drag, - // cycle between other blueprints which are also under the cursor. - - // The depth of blueprints is constantly changing (see above where selected blueprints are brought to the front). - // For this logic, we want a stable sort order so we can correctly cycle, thus using the blueprintMap instead. - IEnumerable> cyclingSelectionBlueprints = blueprintMap.Values; - - // If there's already a selection, let's start from the blueprint after the selection. - cyclingSelectionBlueprints = cyclingSelectionBlueprints.SkipWhile(b => !b.IsSelected).Skip(1); - - // Add the blueprints from before the selection to the end of the enumerable to allow for cyclic selection. - cyclingSelectionBlueprints = cyclingSelectionBlueprints.Concat(blueprintMap.Values.TakeWhile(b => !b.IsSelected)); - - foreach (SelectionBlueprint blueprint in cyclingSelectionBlueprints) - { - if (!blueprint.IsHovered) continue; - - // We are performing a mouse up, but selection handlers perform selection on mouse down, so we need to call that instead. - return clickSelectionHandled = SelectionHandler.MouseDownSelectionRequested(blueprint, e); - } - } - } + // Iterate from the top of the input stack (blueprints closest to the front of the screen first). + // Priority is given to already-selected blueprints. + foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren.Where(b => b.IsHovered).OrderByDescending(b => b.IsSelected)) + return clickSelectionHandled = SelectionHandler.MouseUpSelectionRequested(blueprint, e); return false; } - return true; + if (selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) + { + // If a click occurred and was handled by the currently selected blueprint but didn't result in a drag, + // cycle between other blueprints which are also under the cursor. + + // The depth of blueprints is constantly changing (see above where selected blueprints are brought to the front). + // For this logic, we want a stable sort order so we can correctly cycle, thus using the blueprintMap instead. + IEnumerable> cyclingSelectionBlueprints = blueprintMap.Values; + + // If there's already a selection, let's start from the blueprint after the selection. + cyclingSelectionBlueprints = cyclingSelectionBlueprints.SkipWhile(b => !b.IsSelected).Skip(1); + + // Add the blueprints from before the selection to the end of the enumerable to allow for cyclic selection. + cyclingSelectionBlueprints = cyclingSelectionBlueprints.Concat(blueprintMap.Values.TakeWhile(b => !b.IsSelected)); + + foreach (SelectionBlueprint blueprint in cyclingSelectionBlueprints) + { + if (!blueprint.IsHovered) continue; + + // We are performing a mouse up, but selection handlers perform selection on mouse down, so we need to call that instead. + return clickSelectionHandled = SelectionHandler.MouseDownSelectionRequested(blueprint, e); + } + } + + return false; } /// From 4f7be332f3736fc14fd02008fee3239fa2beb657 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Mar 2023 19:24:03 +0900 Subject: [PATCH 0297/1400] Revert `isDraggingBlueprint` to field --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 3bf9f42957..3ba71cebe6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -483,7 +483,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Whether a blueprint is currently being dragged. /// - private bool isDraggingBlueprint { get; set; } + private bool isDraggingBlueprint; /// /// Attempts to begin the movement of any selected blueprints. From b8e87e3a08d0cc92363a24d7bf32127509a67311 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Mar 2023 19:58:05 +0900 Subject: [PATCH 0298/1400] Update osu!mania argon colours to match new proposal --- .../Argon/ManiaArgonSkinTransformer.cs | 249 +++++++++++++++--- 1 file changed, 207 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 057b7eb0d9..75ecd53cd1 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -69,6 +69,17 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon return base.GetDrawableComponent(lookup); } + private static readonly Color4 colour_special_column = new Color4(169, 106, 255, 255); + + private const int total_colours = 6; + + private static readonly Color4 colour_yellow = new Color4(255, 197, 40, 255); + private static readonly Color4 colour_orange = new Color4(252, 109, 1, 255); + private static readonly Color4 colour_pink = new Color4(213, 35, 90, 255); + private static readonly Color4 colour_purple = new Color4(203, 60, 236, 255); + private static readonly Color4 colour_cyan = new Color4(72, 198, 255, 255); + private static readonly Color4 colour_green = new Color4(100, 192, 92, 255); + public override IBindable? GetConfig(TLookup lookup) { if (lookup is ManiaSkinConfigurationLookup maniaLookup) @@ -92,48 +103,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour: - Color4 colour; - - const int total_colours = 7; - - if (stage.IsSpecialColumn(column)) - colour = new Color4(159, 101, 255, 255); - else - { - switch (column % total_colours) - { - case 0: - colour = new Color4(240, 216, 0, 255); - break; - - case 1: - colour = new Color4(240, 101, 0, 255); - break; - - case 2: - colour = new Color4(240, 0, 130, 255); - break; - - case 3: - colour = new Color4(192, 0, 240, 255); - break; - - case 4: - colour = new Color4(0, 96, 240, 255); - break; - - case 5: - colour = new Color4(0, 226, 240, 255); - break; - - case 6: - colour = new Color4(0, 240, 96, 255); - break; - - default: - throw new ArgumentOutOfRangeException(); - } - } + var colour = getColourForLayout(column, stage); return SkinUtils.As(new Bindable(colour)); } @@ -141,5 +111,200 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon return base.GetConfig(lookup); } + + private Color4 getColourForLayout(int column, StageDefinition stage) + { + // For now, these are defined per column count as per https://user-images.githubusercontent.com/50823728/218038463-b450f46c-ef21-4551-b133-f866be59970c.png + // See https://github.com/ppy/osu/discussions/21996 for discussion. + switch (stage.Columns) + { + case 1: + return colour_yellow; + + case 2: + switch (column) + { + case 0: return colour_green; + + case 1: return colour_cyan; + + default: throw new ArgumentOutOfRangeException(); + } + + case 3: + switch (column) + { + case 0: return colour_pink; + + case 1: return colour_purple; + + case 2: return colour_special_column; + + default: throw new ArgumentOutOfRangeException(); + } + + case 4: + switch (column) + { + case 0: return colour_yellow; + + case 1: return colour_orange; + + case 2: return colour_pink; + + case 3: return colour_purple; + + default: throw new ArgumentOutOfRangeException(); + } + + case 5: + switch (column) + { + case 0: return colour_pink; + + case 1: return colour_orange; + + case 2: return colour_yellow; + + case 3: return colour_green; + + case 4: return colour_cyan; + + default: throw new ArgumentOutOfRangeException(); + } + + case 6: + switch (column) + { + case 0: return colour_pink; + + case 1: return colour_orange; + + case 2: return colour_yellow; + + case 3: return colour_cyan; + + case 4: return colour_purple; + + case 5: return colour_pink; + + default: throw new ArgumentOutOfRangeException(); + } + + case 7: + switch (column) + { + case 0: return colour_pink; + + case 1: return colour_cyan; + + case 2: return colour_pink; + + case 3: return colour_special_column; + + case 4: return colour_green; + + case 5: return colour_cyan; + + case 6: return colour_green; + + default: throw new ArgumentOutOfRangeException(); + } + + case 8: + switch (column) + { + case 0: return colour_purple; + + case 1: return colour_pink; + + case 2: return colour_orange; + + case 3: return colour_yellow; + + case 4: return colour_yellow; + + case 5: return colour_orange; + + case 6: return colour_pink; + + case 7: return colour_purple; + + default: throw new ArgumentOutOfRangeException(); + } + + case 9: + switch (column) + { + case 0: return colour_purple; + + case 1: return colour_pink; + + case 2: return colour_orange; + + case 3: return colour_yellow; + + case 4: return colour_special_column; + + case 5: return colour_yellow; + + case 6: return colour_orange; + + case 7: return colour_pink; + + case 8: return colour_purple; + + default: throw new ArgumentOutOfRangeException(); + } + + case 10: + switch (column) + { + case 0: return colour_purple; + + case 1: return colour_pink; + + case 2: return colour_orange; + + case 3: return colour_yellow; + + case 4: return colour_cyan; + + case 5: return colour_green; + + case 6: return colour_yellow; + + case 7: return colour_orange; + + case 8: return colour_pink; + + case 9: return colour_purple; + + default: throw new ArgumentOutOfRangeException(); + } + } + + // fallback for unhandled scenarios + + if (stage.IsSpecialColumn(column)) + return colour_special_column; + + switch (column % total_colours) + { + case 0: return new Color4(255, 197, 40, 255); + + case 1: return new Color4(252, 109, 1, 255); + + case 2: return new Color4(213, 35, 90, 255); + + case 3: return new Color4(203, 60, 236, 255); + + case 4: return new Color4(72, 198, 255, 255); + + case 5: return new Color4(100, 192, 92, 255); + + default: throw new ArgumentOutOfRangeException(); + } + } } } From 686259a33c62aed9ce227001f8cedccdf3031f56 Mon Sep 17 00:00:00 2001 From: EXtremeExploit Date: Wed, 8 Mar 2023 13:57:20 -0300 Subject: [PATCH 0299/1400] Make support badge in list match groups --- osu.Game/Users/UserListPanel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index 9b5b0e9f6d..3047e70a1a 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.cs @@ -67,6 +67,7 @@ namespace osu.Game.Users { username.Anchor = Anchor.CentreLeft; username.Origin = Anchor.CentreLeft; + username.UseFullGlyphHeight = false; }) } }, @@ -111,7 +112,7 @@ namespace osu.Game.Users { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Height = 20, + Height = 16, SupportLevel = User.SupportLevel }); } From 430b09acb211f1b8ab44c7e889d7b2d22cc7ea0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 8 Mar 2023 22:52:06 +0100 Subject: [PATCH 0300/1400] Expose taiko input manager in same manner as osu! --- osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs | 2 +- osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs index fa876555e1..a5cffca06f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { ruleset = (DrawableTaikoRuleset)drawableRuleset; - ruleset.InputManager.Add(new InputInterceptor(this)); + ruleset.KeyBindingInputManager.Add(new InputInterceptor(this)); playfield = (TaikoPlayfield)ruleset.Playfield; var periods = new List(); diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 5390d3b138..a08877e2dd 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.UI public readonly BindableBool LockPlayfieldMaxAspect = new BindableBool(true); - public TaikoInputManager InputManager { get; private set; } + public new TaikoInputManager KeyBindingInputManager => (TaikoInputManager)base.KeyBindingInputManager; protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Taiko.UI LockPlayfieldMaxAspect = { BindTarget = LockPlayfieldMaxAspect } }; - protected override PassThroughInputManager CreateInputManager() => InputManager = new TaikoInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(); From e2467848679538557c64608152dc4ad3872223d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 18:25:30 +0900 Subject: [PATCH 0301/1400] Fix dual stage column colours not being looked up correctly --- .../Argon/ManiaArgonSkinTransformer.cs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 75ecd53cd1..0beca815b2 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -84,8 +84,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { if (lookup is ManiaSkinConfigurationLookup maniaLookup) { - int column = maniaLookup.ColumnIndex ?? 0; - var stage = beatmap.GetStageForColumnIndex(column); + int columnIndex = maniaLookup.ColumnIndex ?? 0; + var stage = beatmap.GetStageForColumnIndex(columnIndex); switch (maniaLookup.Lookup) { @@ -98,12 +98,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case LegacyManiaSkinConfigurationLookups.ColumnWidth: return SkinUtils.As(new Bindable( - stage.IsSpecialColumn(column) ? 120 : 60 + stage.IsSpecialColumn(columnIndex) ? 120 : 60 )); case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour: - var colour = getColourForLayout(column, stage); + var colour = getColourForLayout(columnIndex, stage); return SkinUtils.As(new Bindable(colour)); } @@ -112,8 +112,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon return base.GetConfig(lookup); } - private Color4 getColourForLayout(int column, StageDefinition stage) + private Color4 getColourForLayout(int columnIndex, StageDefinition stage) { + // Account for cases like dual-stage (assume that all stages have the same column count for now). + columnIndex %= stage.Columns; + // For now, these are defined per column count as per https://user-images.githubusercontent.com/50823728/218038463-b450f46c-ef21-4551-b133-f866be59970c.png // See https://github.com/ppy/osu/discussions/21996 for discussion. switch (stage.Columns) @@ -122,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon return colour_yellow; case 2: - switch (column) + switch (columnIndex) { case 0: return colour_green; @@ -132,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 3: - switch (column) + switch (columnIndex) { case 0: return colour_pink; @@ -144,7 +147,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 4: - switch (column) + switch (columnIndex) { case 0: return colour_yellow; @@ -158,7 +161,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 5: - switch (column) + switch (columnIndex) { case 0: return colour_pink; @@ -174,7 +177,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 6: - switch (column) + switch (columnIndex) { case 0: return colour_pink; @@ -192,7 +195,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 7: - switch (column) + switch (columnIndex) { case 0: return colour_pink; @@ -212,7 +215,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 8: - switch (column) + switch (columnIndex) { case 0: return colour_purple; @@ -234,7 +237,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 9: - switch (column) + switch (columnIndex) { case 0: return colour_purple; @@ -258,7 +261,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } case 10: - switch (column) + switch (columnIndex) { case 0: return colour_purple; @@ -286,10 +289,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon // fallback for unhandled scenarios - if (stage.IsSpecialColumn(column)) + if (stage.IsSpecialColumn(columnIndex)) return colour_special_column; - switch (column % total_colours) + switch (columnIndex % total_colours) { case 0: return new Color4(255, 197, 40, 255); From 030742c64820fcaffb4dc58b06946489e165849c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 19:02:15 +0900 Subject: [PATCH 0302/1400] Use different icon style on hold note heads --- .../Skinning/Argon/ArgonHoldNoteHeadPiece.cs | 19 +++++++++++++++ .../Skinning/Argon/ArgonNotePiece.cs | 24 +++++++++++-------- .../Argon/ManiaArgonSkinTransformer.cs | 2 ++ 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs new file mode 100644 index 0000000000..16381a6dec --- /dev/null +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osuTK; + +namespace osu.Game.Rulesets.Mania.Skinning.Argon +{ + internal partial class ArgonHoldNoteHeadPiece : ArgonNotePiece + { + protected override Drawable CreateIcon() => new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20, 5), + }; + } +} diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs index 2a5bce255c..49d9cebc2e 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon CornerRadius = CORNER_RADIUS; Masking = true; - InternalChildren = new Drawable[] + InternalChildren = new[] { shadow = new Box { @@ -65,18 +65,22 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon RelativeSizeAxes = Axes.X, Height = CORNER_RADIUS * 2, }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = 4, - Icon = FontAwesome.Solid.AngleDown, - Size = new Vector2(20), - Scale = new Vector2(1, 0.7f) - } + CreateIcon(), }; } + protected virtual Drawable CreateIcon() => new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 4, + // TODO: replace with a non-squashed version. + // The 0.7f height scale should be removed. + Icon = FontAwesome.Solid.AngleDown, + Size = new Vector2(20), + Scale = new Vector2(1, 0.7f) + }; + [BackgroundDependencyLoader(true)] private void load(IScrollingInfo scrollingInfo, DrawableHitObject? drawableObject) { diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 057b7eb0d9..faf55c15fe 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -50,6 +50,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon return new ArgonHoldNoteTailPiece(); case ManiaSkinComponents.HoldNoteHead: + return new ArgonHoldNoteHeadPiece(); + case ManiaSkinComponents.Note: return new ArgonNotePiece(); From d806b85a30ca59d2515b29bc18b7362ae7931902 Mon Sep 17 00:00:00 2001 From: tsrk Date: Wed, 8 Mar 2023 21:10:34 +0000 Subject: [PATCH 0303/1400] revert: make `counters` an `IEnumerable` again As suggested by bdach as this would make the last two commits useless Refs: 5d15426 --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 3 +-- .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 4 +--- osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs | 9 +++++---- osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index aeb7aa7dbe..42683a3eec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -8,7 +8,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Configuration; @@ -45,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); + private Drawable keyCounterFlow => (Drawable)hudOverlay.KeyCounter.Counters; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 808241729b..3eda80719a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -10,8 +10,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -44,7 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private FillFlowContainer keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().First(); + private Drawable keyCounterFlow => (Drawable)hudOverlay.KeyCounter.Counters; [Test] public void TestComboCounterIncrementing() diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index dce0be9cde..9499263474 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.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 System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK.Graphics; @@ -12,9 +13,9 @@ namespace osu.Game.Screens.Play.HUD private const int duration = 100; private const double key_fade_time = 80; - private readonly FillFlowContainer keyFlow = new FillFlowContainer(); + private readonly FillFlowContainer keyFlow = new FillFlowContainer(); - public override Container Counters => keyFlow; + public override IEnumerable Counters => keyFlow; public DefaultKeyCounterDisplay() { @@ -58,7 +59,7 @@ namespace osu.Game.Screens.Play.HUD { keyDownTextColor = value; foreach (var child in keyFlow) - ((DefaultKeyCounter)child).KeyDownTextColor = value; + child.KeyDownTextColor = value; } } } @@ -74,7 +75,7 @@ namespace osu.Game.Screens.Play.HUD { keyUpTextColor = value; foreach (var child in keyFlow) - ((DefaultKeyCounter)child).KeyUpTextColor = value; + child.KeyUpTextColor = value; } } } diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 2c90d1474d..0e0f8a1190 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Play.HUD /// /// The s contained in this . /// - public abstract Container Counters { get; } + public abstract IEnumerable Counters { get; } /// /// Whether the actions reported by all s within this should be counted. From bfc0b946fbbdc0943b1a9c2d52df0382db261f97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:26:35 +0900 Subject: [PATCH 0304/1400] Remove additive blending from argon body piece --- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs index 1f52f5f15f..39a030d621 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs @@ -32,7 +32,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon // Without this, the width of the body will be slightly larger than the head/tail. Masking = true; CornerRadius = ArgonNotePiece.CORNER_RADIUS; - Blending = BlendingParameters.Additive; } [BackgroundDependencyLoader(true)] From ed3ff62e4f9b9042fccef2f05dd757cfa5c4e762 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:26:48 +0900 Subject: [PATCH 0305/1400] Add note about why `bodyPiece` sizing is done as it is I think we're going to have to change this as it's quite limiting in what you can do with osu!mania skin implementation, but for now I want to leave a note as to why this is done, because each time I have to trial and error check what breaks when adjusting it. --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 25d0573a82..6e1c6cf80f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -236,6 +236,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }; // Position and resize the body to lie half-way under the head and the tail notes. + // The rationale for this is account for heads/tails with corner radius. bodyPiece.Y = (Direction.Value == ScrollingDirection.Up ? 1 : -1) * Head.Height / 2; bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; From 526eeedec2d81b10931235fd55637c184a08d108 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:27:43 +0900 Subject: [PATCH 0306/1400] Adjust explosion and hit target to not include shadow portion in height calculation --- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs | 5 +++-- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs index e32de6f3f3..8e27b4abd7 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs @@ -43,9 +43,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { largeFaint = new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, + Height = ArgonNotePiece.NOTE_ACCENT_RATIO, Masking = true, CornerRadius = ArgonNotePiece.CORNER_RADIUS, Blending = BlendingParameters.Additive, diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs index 4ffb4a435b..cf5931231c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitTarget.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private void load(IScrollingInfo scrollingInfo) { RelativeSizeAxes = Axes.X; - Height = ArgonNotePiece.NOTE_HEIGHT; + Height = ArgonNotePiece.NOTE_HEIGHT * ArgonNotePiece.NOTE_ACCENT_RATIO; Masking = true; CornerRadius = ArgonNotePiece.CORNER_RADIUS; From 2ad531f263ad20386e9ab57724c9a9e39c36d547 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:27:58 +0900 Subject: [PATCH 0307/1400] Adjust argon note shadows and body to be closer in line with new design proposal --- .../Skinning/Argon/ArgonHoldNoteTailPiece.cs | 45 ++++++++++++------- .../Skinning/Argon/ArgonNotePiece.cs | 3 +- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs index 428439d52c..abfd9c4dc8 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects.Drawables; @@ -19,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private readonly IBindable direction = new Bindable(); private readonly IBindable accentColour = new Bindable(); - private readonly Box shadeBackground; + private readonly Box shadow; private readonly Box shadeForeground; public ArgonHoldNoteTailPiece() @@ -27,30 +28,40 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon RelativeSizeAxes = Axes.X; Height = ArgonNotePiece.NOTE_HEIGHT; - CornerRadius = ArgonNotePiece.CORNER_RADIUS; - Masking = true; - InternalChildren = new Drawable[] { - shadeBackground = new Box - { - RelativeSizeAxes = Axes.Both, - }, new Container { - RelativeSizeAxes = Axes.Both, - Height = ArgonNotePiece.NOTE_ACCENT_RATIO, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = ArgonNotePiece.NOTE_HEIGHT, CornerRadius = ArgonNotePiece.CORNER_RADIUS, Masking = true, Children = new Drawable[] { - shadeForeground = new Box + shadow = new Box { RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Colour4.Black), + // Avoid ugly single pixel overlap. + Height = 0.9f, }, - }, + new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Height = ArgonNotePiece.NOTE_ACCENT_RATIO, + CornerRadius = ArgonNotePiece.CORNER_RADIUS, + Masking = true, + Children = new Drawable[] + { + shadeForeground = new Box + { + RelativeSizeAxes = Axes.Both, + }, + }, + }, + } }, }; } @@ -75,8 +86,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private void onAccentChanged(ValueChangedEvent accent) { - shadeBackground.Colour = accent.NewValue.Darken(1.7f); - shadeForeground.Colour = accent.NewValue.Darken(1.1f); + shadeForeground.Colour = ColourInfo.GradientVertical( + accent.NewValue.Darken(0.2f), + accent.NewValue.Darken(1.2f) // matches body + ); } } } diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs index 49d9cebc2e..24ce22eccc 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs @@ -41,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon shadow = new Box { RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Colour4.Black) }, new Container { @@ -109,8 +110,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon accent.NewValue.Lighten(0.1f), accent.NewValue ); - - shadow.Colour = accent.NewValue.Darken(0.5f); } } } From e12ab165b87adc0ed63b72b5de01d02de52cfcaa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:42:59 +0900 Subject: [PATCH 0308/1400] Adjust colours a bit to make hold note bodies more accented --- .../Skinning/Argon/ArgonHoldBodyPiece.cs | 2 +- .../Skinning/Argon/ArgonHoldNoteTailPiece.cs | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs index 39a030d621..91eda57c8f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon AccentColour.BindValueChanged(colour => { - background.Colour = colour.NewValue.Darken(1.2f); + background.Colour = colour.NewValue.Darken(0.6f); foreground.Colour = colour.NewValue.Opacity(0.2f); }, true); diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs index abfd9c4dc8..140c3d5ecc 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private readonly IBindable accentColour = new Bindable(); private readonly Box shadow; - private readonly Box shadeForeground; + private readonly Box foreground; + private readonly Box foregroundAdditive; public ArgonHoldNoteTailPiece() { @@ -55,10 +56,16 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon Masking = true, Children = new Drawable[] { - shadeForeground = new Box + foreground = new Box { RelativeSizeAxes = Axes.Both, }, + foregroundAdditive = new Box + { + RelativeSizeAxes = Axes.Both, + Blending = BlendingParameters.Additive, + Height = 0.5f, + }, }, }, } @@ -86,9 +93,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private void onAccentChanged(ValueChangedEvent accent) { - shadeForeground.Colour = ColourInfo.GradientVertical( - accent.NewValue.Darken(0.2f), - accent.NewValue.Darken(1.2f) // matches body + foreground.Colour = accent.NewValue.Darken(0.6f); // matches body + + foregroundAdditive.Colour = ColourInfo.GradientVertical( + accent.NewValue.Opacity(0.4f), + accent.NewValue.Opacity(0) ); } } From 08b88ed6395835de3bede8d4e028aa42a4238b59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 9 Mar 2023 20:43:42 +0900 Subject: [PATCH 0309/1400] Adjust hold note head icon to be more centered --- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs index 16381a6dec..b9cc73c75c 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHeadPiece.cs @@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { Anchor = Anchor.Centre, Origin = Anchor.Centre, + Y = 2, Size = new Vector2(20, 5), }; } From 5a1316f0e5eb0d7acd8c813e84849cef5c584dbb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:23:13 +0900 Subject: [PATCH 0310/1400] split save logic --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 8 ++------ osu.Game/Overlays/Mods/ModPresetPanel.cs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 4eaf5e19db..32d4aeae76 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -108,13 +107,10 @@ namespace osu.Game.Overlays.Mods private void trySaveCurrentMod() { - if (button.Active.Value || !selectedMods.Value.Any()) + if (button.SaveCurrentMod()) return; - button.Preset.PerformWrite(s => - { - s.Mods = selectedMods.Value.ToArray(); - }); + Body.Shake(); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f4f1af50df..f861245007 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,6 +98,20 @@ namespace osu.Game.Overlays.Mods #endregion + public bool SaveCurrentMod() + { + if (!checkCurrentModCanBeSave()) + return false; + + Preset.PerformWrite(s => + { + s.Mods = selectedMods.Value.ToArray(); + }); + return true; + } + + private bool checkCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From 3d746e8dfbb6cfbd7a08a480eda3d56a3262ed67 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:43:11 +0900 Subject: [PATCH 0311/1400] content Menu --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f861245007..f3fb5b5bb0 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -90,11 +90,24 @@ namespace osu.Game.Overlays.Mods #region IHasContextMenu - public MenuItem[] ContextMenuItems => new MenuItem[] + public MenuItem[] ContextMenuItems { - new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), - }; + get + { + var menu = new List + { + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), + }; + + if (checkCurrentModCanBeSave()) + { + menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); + } + + return menu.ToArray(); + } + } #endregion From d009cd8422780247f035bb586851790bac37f6b5 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:45:33 +0900 Subject: [PATCH 0312/1400] test --- .../UserInterface/TestSceneModPresetColumn.cs | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index d6065374ac..b67f67db2b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -327,6 +327,32 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddStep("click edit", () => + { + var editItem = this.ChildrenOfType().ElementAt(0); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); + + OsuPopover? popover = null; + AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); + AddStep("click use current mods", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); + InputManager.Click(MouseButton.Left); + }); + AddWaitStep("wait some", 3); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); + AddAssert("present mod not changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 1); + AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => { @@ -343,14 +369,57 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - OsuPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().FirstOrDefault()) != null); AddStep("click use current mods", () => { InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); + AddWaitStep("wait some", 3); + AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + } + + [Test] + public void TestEditPresetModInContextMenu() + { + ModPresetColumn modPresetColumn = null!; + var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); + + AddStep("select mods", () => SelectedMods.Value = mods); + AddStep("right click first panel", () => + { + var panel = this.ChildrenOfType().First(); + InputManager.MoveMouseTo(panel); + InputManager.Click(MouseButton.Right); + }); + + AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); + AddAssert("Have Use Current Mods", () => this.ChildrenOfType().Count() == 3); + AddStep("Click Use Current Mods", () => + { + var editItem = this.ChildrenOfType().ElementAt(1); + InputManager.MoveMouseTo(editItem); + InputManager.Click(MouseButton.Left); + }); AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); } From ca416175bb6e168c3c8fa469b296d059a8991541 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 9 Mar 2023 22:58:44 +0900 Subject: [PATCH 0313/1400] remove useless property --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 32d4aeae76..3043f4a544 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -26,9 +26,6 @@ namespace osu.Game.Overlays.Mods private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; - [Resolved] - private Bindable> selectedMods { get; set; } = null!; - private readonly ModPreset preset; public EditPresetPopover(ModPresetPanel modPresetPanel) From f4e262040275e4466f4e43def09980a6a1b6d432 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 10 Mar 2023 00:56:22 +0900 Subject: [PATCH 0314/1400] fix test --- .../UserInterface/TestSceneModPresetColumn.cs | 22 +++++++++++-------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 2 -- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index b67f67db2b..eaa3664623 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -266,6 +266,7 @@ namespace osu.Game.Tests.Visual.UserInterface { ModPresetColumn modPresetColumn = null!; string presetName = null!; + ModPresetPanel panel = null!; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -277,7 +278,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); AddStep("right click first panel", () => { - var panel = this.ChildrenOfType().First(); + panel = this.ChildrenOfType().First(); presetName = panel.Preset.Value.Name; InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); @@ -301,7 +302,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); - AddAssert("present is not changed", () => this.ChildrenOfType().First().Preset.Value.Name == presetName); + AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => @@ -310,7 +311,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present is changed", () => this.ChildrenOfType().First().Preset.Value.Name != presetName); + AddAssert("present is changed", () => panel.Preset.Value.Name != presetName); } [Test] @@ -351,7 +352,8 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); - AddAssert("present mod not changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 1); + AddAssert("present mod not changed", () => + !new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -377,14 +379,15 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddWaitStep("wait some", 3); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } [Test] public void TestEditPresetModInContextMenu() { ModPresetColumn modPresetColumn = null!; - var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + var mods = new Mod[] { new OsuModHidden() }; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -405,9 +408,9 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); AddStep("select mods", () => SelectedMods.Value = mods); - AddStep("right click first panel", () => + AddStep("right click second panel", () => { - var panel = this.ChildrenOfType().First(); + var panel = this.ChildrenOfType().ElementAt(1); InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); }); @@ -420,7 +423,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(editItem); InputManager.Click(MouseButton.Left); }); - AddAssert("present mod is changed", () => this.ChildrenOfType().First().Preset.Value.Mods.Count == 2); + AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().ElementAt(1).Preset.Value.Mods).SetEquals(mods)); } private ICollection createTestPresets() => new[] diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 3043f4a544..a5c562914b 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -1,9 +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 System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; From 6b2a70b1126b3fc07a97f02ca35d4c7536ff4e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 9 Mar 2023 19:14:08 +0100 Subject: [PATCH 0315/1400] Remove unused fields --- .../Skinning/Argon/ArgonHoldNoteTailPiece.cs | 3 +-- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs index 140c3d5ecc..085e0630fb 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs @@ -20,7 +20,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private readonly IBindable direction = new Bindable(); private readonly IBindable accentColour = new Bindable(); - private readonly Box shadow; private readonly Box foreground; private readonly Box foregroundAdditive; @@ -39,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon Masking = true, Children = new Drawable[] { - shadow = new Box + new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Colour4.Black), diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs index 24ce22eccc..3a519283f1 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonNotePiece.cs @@ -26,7 +26,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private readonly IBindable accentColour = new Bindable(); private readonly Box colouredBox; - private readonly Box shadow; public ArgonNotePiece() { @@ -38,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon InternalChildren = new[] { - shadow = new Box + new Box { RelativeSizeAxes = Axes.Both, Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Colour4.Black) From b51c41a8043ae04fdc57aad461beb9f74b2320b5 Mon Sep 17 00:00:00 2001 From: Terochi Date: Thu, 9 Mar 2023 20:14:58 +0100 Subject: [PATCH 0316/1400] Addressed changes --- osu.Game.Tests/Mods/ModSettingsTest.cs | 92 ++++++++++++++++++-------- osu.Game/Rulesets/Mods/Mod.cs | 69 ++++++++++++------- 2 files changed, 109 insertions(+), 52 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index 45e162df1a..e2e050870e 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Mods public class ModSettingsTest { [Test] - public void TestModSettingsUnboundWhenCopied() + public void TestModSettingsUnboundWhenCloned() { var original = new OsuModDoubleTime(); var copy = (OsuModDoubleTime)original.DeepClone(); @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Mods } [Test] - public void TestMultiModSettingsUnboundWhenCopied() + public void TestMultiModSettingsUnboundWhenCloned() { var original = new MultiMod(new OsuModDoubleTime()); var copy = (MultiMod)original.DeepClone(); @@ -54,6 +54,42 @@ namespace osu.Game.Tests.Mods Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); } + [Test] + public void TestDefaultValueKeptWhenCopied() + { + var modBoolTrue = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = true, Value = false } }; + var modBoolFalse = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; + + modBoolFalse.CopySharedSettings(modBoolTrue); + + Assert.That(modBoolFalse.TestSetting.Default, Is.EqualTo(false)); + Assert.That(modBoolFalse.TestSetting.Value, Is.EqualTo(modBoolTrue.TestSetting.Value)); + } + + [Test] + public void TestValueResetsToDefaultWhenCopied() + { + var modDouble = new TestNonMatchingSettingTypeModDouble(); + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = 1 } }; + + modInt.CopySharedSettings(modDouble); + + Assert.That(modInt.TestSetting.Value, Is.EqualTo(modInt.TestSetting.Default)); + } + + [Test] + public void TestRelativelyScaleWithClampedRangeWhenCopied() + { + const double setting_change = 50.4; + + var modDouble100 = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 100, MinValue = 0, Value = setting_change } }; + var modDouble200 = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 200, MinValue = 0 } }; + + modDouble200.CopySharedSettings(modDouble100); + + Assert.That(modDouble200.TestSetting.Value, Is.EqualTo(setting_change * 2)); + } + [Test] public void TestCopyDoubleToIntWithDefaultRange() { @@ -64,7 +100,32 @@ namespace osu.Game.Tests.Mods modInt.CopySharedSettings(modDouble); - Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change)); + Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change))); + } + + [Test] + public void TestCopyDoubleToIntWithOutOfBoundsRange() + { + const double setting_change = 50.4; + + var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MinValue = int.MinValue - 1d, Value = setting_change } }; + // make RangeConstrainedBindable.HasDefinedRange return true + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MinValue = int.MinValue + 1 } }; + + modInt.CopySharedSettings(modDouble); + + Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change))); + } + + [Test] + public void TestCopyDoubleToIntWithOutOfBoundsValue() + { + var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MinValue = int.MinValue + 1, Value = int.MaxValue + 1d } }; + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MinValue = int.MinValue + 1 } }; + + modInt.CopySharedSettings(modDouble); + + Assert.That(modInt.TestSetting.Value, Is.EqualTo(int.MaxValue)); } [Test] @@ -80,31 +141,6 @@ namespace osu.Game.Tests.Mods Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); } - [Test] - public void TestCopyDoubleToIntWithClampedRange() - { - const double setting_change = 50.4; - - var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 100, MinValue = 0, Value = setting_change } }; - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MaxValue = 200, MinValue = 0 } }; - - modInt.CopySharedSettings(modDouble); - - Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change * 2))); - } - - [Test] - public void TestDefaultValueKeptWhenCopied() - { - var modBoolTrue = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = true, Value = false } }; - var modBoolFalse = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - - modBoolFalse.CopySharedSettings(modBoolTrue); - - Assert.That(modBoolFalse.TestSetting.Default, Is.EqualTo(false)); - Assert.That(modBoolFalse.TestSetting.Value, Is.EqualTo(modBoolTrue.TestSetting.Value)); - } - private class TestNonMatchingSettingTypeModDouble : TestNonMatchingSettingTypeMod { public override string Acronym => "NMD"; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index e630a53045..85014d555d 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -169,28 +169,31 @@ namespace osu.Game.Rulesets.Mods const string max_value = nameof(BindableNumber.MaxValue); const string value = nameof(Bindable.Value); - Dictionary oldSettings = new Dictionary(); + Dictionary sourceSettings = new Dictionary(); - foreach (var (_, property) in source.GetSettingsSourceProperties()) + foreach (var (_, sourceProperty) in source.GetSettingsSourceProperties()) { - oldSettings.Add(property.Name.ToSnakeCase(), property.GetValue(source)!); + sourceSettings.Add(sourceProperty.Name.ToSnakeCase(), sourceProperty.GetValue(source)!); } - foreach (var (_, property) in this.GetSettingsSourceProperties()) + foreach (var (_, targetProperty) in this.GetSettingsSourceProperties()) { - object targetSetting = property.GetValue(this)!; + object targetSetting = targetProperty.GetValue(this)!; - if (!oldSettings.TryGetValue(property.Name.ToSnakeCase(), out object? sourceSetting)) + if (!sourceSettings.TryGetValue(targetProperty.Name.ToSnakeCase(), out object? sourceSetting)) continue; if (((IBindable)sourceSetting).IsDefault) - // keep at default value if the source is default + { + // reset to default value if the source is default + targetSetting.GetType().GetMethod(nameof(Bindable.SetDefault))!.Invoke(targetSetting, null); continue; + } - Type? targetType = getGenericBaseType(targetSetting, typeof(BindableNumber<>)); - Type? sourceType = getGenericBaseType(sourceSetting, typeof(BindableNumber<>)); + Type? targetBindableNumberType = getGenericBaseType(targetSetting, typeof(BindableNumber<>)); + Type? sourceBindableNumberType = getGenericBaseType(sourceSetting, typeof(BindableNumber<>)); - if (targetType == null || sourceType == null) + if (targetBindableNumberType == null || sourceBindableNumberType == null) { if (getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single()) @@ -202,8 +205,16 @@ namespace osu.Game.Rulesets.Mods continue; } - Type targetGenericType = targetType.GenericTypeArguments.Single(); - Type sourceGenericType = sourceType.GenericTypeArguments.Single(); + bool rangeOutOfBounds = false; + + Type targetGenericType = targetBindableNumberType.GenericTypeArguments.Single(); + Type sourceGenericType = sourceBindableNumberType.GenericTypeArguments.Single(); + + if (!Convert.ToBoolean(getValue(targetSetting, nameof(RangeConstrainedBindable.HasDefinedRange))) || + !Convert.ToBoolean(getValue(sourceSetting, nameof(RangeConstrainedBindable.HasDefinedRange)))) + // check if we have a range to rescale from and a range to rescale to + // if not, copy the raw value + rangeOutOfBounds = true; double allowedMin = Math.Max( Convert.ToDouble(targetGenericType.GetField("MinValue")!.GetValue(null)), @@ -219,25 +230,35 @@ namespace osu.Game.Rulesets.Mods double targetMax = getValueDouble(targetSetting, max_value); double sourceMin = getValueDouble(sourceSetting, min_value); double sourceMax = getValueDouble(sourceSetting, max_value); - double sourceValue = getValueDouble(sourceSetting, value); + double sourceValue = Math.Clamp(getValueDouble(sourceSetting, value), allowedMin, allowedMax); - // convert value to same ratio - double targetValue = (sourceValue - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin; + double targetValue = rangeOutOfBounds + // keep raw value + ? sourceValue + // convert value to same ratio + : (sourceValue - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin; - setValue(targetSetting, value, Convert.ChangeType(targetValue, targetType.GenericTypeArguments.Single())); + setValue(targetSetting, value, Convert.ChangeType(targetValue, targetBindableNumberType.GenericTypeArguments.Single())); - double getValueDouble(object target, string name) => - Math.Clamp(Convert.ToDouble(getValue(target, name)!), allowedMin, allowedMax); + double getValueDouble(object setting, string name) + { + double settingValue = Convert.ToDouble(getValue(setting, name)!); + + if (settingValue < allowedMin || settingValue > allowedMax) + rangeOutOfBounds = true; + + return settingValue; + } } - object? getValue(object target, string name) => - target.GetType().GetProperty(name)!.GetValue(target); + object? getValue(object setting, string name) => + setting.GetType().GetProperty(name)!.GetValue(setting); - void setValue(object target, string name, object? newValue) => - target.GetType().GetProperty(name)!.SetValue(target, newValue); + void setValue(object setting, string name, object? newValue) => + setting.GetType().GetProperty(name)!.SetValue(setting, newValue); - Type? getGenericBaseType(object target, Type genericType) => - target.GetType().GetTypeInheritance().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == genericType); + Type? getGenericBaseType(object setting, Type genericType) => + setting.GetType().GetTypeInheritance().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == genericType); } /// From 8b0f127ff2a652cb2d8381d4c500c6cd040b878e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 11:25:52 +0900 Subject: [PATCH 0317/1400] split ModPresetRow --- osu.Game/Overlays/Mods/ModPresetRow.cs | 64 ++++++++++++++++++++++ osu.Game/Overlays/Mods/ModPresetTooltip.cs | 54 ------------------ 2 files changed, 64 insertions(+), 54 deletions(-) create mode 100644 osu.Game/Overlays/Mods/ModPresetRow.cs diff --git a/osu.Game/Overlays/Mods/ModPresetRow.cs b/osu.Game/Overlays/Mods/ModPresetRow.cs new file mode 100644 index 0000000000..4829e93b87 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModPresetRow.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; +using osuTK; + +namespace osu.Game.Overlays.Mods +{ + public partial class ModPresetRow : FillFlowContainer + { + public ModPresetRow(Mod mod) + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Direction = FillDirection.Vertical; + Spacing = new Vector2(4); + InternalChildren = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7), + Children = new Drawable[] + { + new ModSwitchTiny(mod) + { + Active = { Value = true }, + Scale = new Vector2(0.6f), + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new OsuSpriteText + { + Text = mod.Name, + Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold), + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Margin = new MarginPadding { Bottom = 2 } + } + } + } + }; + + if (!string.IsNullOrEmpty(mod.SettingDescription)) + { + AddInternal(new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 14 }, + Text = mod.SettingDescription + }); + } + } + } +} diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index ff4f00da69..8e8259de45 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.cs @@ -6,11 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; using osuTK; namespace osu.Game.Overlays.Mods @@ -61,55 +57,5 @@ namespace osu.Game.Overlays.Mods protected override void PopOut() => this.FadeOut(transition_duration, Easing.OutQuint); public void Move(Vector2 pos) => Position = pos; - - private partial class ModPresetRow : FillFlowContainer - { - public ModPresetRow(Mod mod) - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(4); - InternalChildren = new Drawable[] - { - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7), - Children = new Drawable[] - { - new ModSwitchTiny(mod) - { - Active = { Value = true }, - Scale = new Vector2(0.6f), - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - new OsuSpriteText - { - Text = mod.Name, - Font = OsuFont.Default.With(size: 16, weight: FontWeight.SemiBold), - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Margin = new MarginPadding { Bottom = 2 } - } - } - } - }; - - if (!string.IsNullOrEmpty(mod.SettingDescription)) - { - AddInternal(new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 14 }, - Text = mod.SettingDescription - }); - } - } - } } } From 1cd565193e3a546e0e6d8e603e4eebc09688a0fd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 11:39:35 +0900 Subject: [PATCH 0318/1400] public CheckCurrentModCanBeSave --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index f3fb5b5bb0..d01981d18c 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.Mods new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), }; - if (checkCurrentModCanBeSave()) + if (CheckCurrentModCanBeSave()) { menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); } @@ -113,7 +113,7 @@ namespace osu.Game.Overlays.Mods public bool SaveCurrentMod() { - if (!checkCurrentModCanBeSave()) + if (!CheckCurrentModCanBeSave()) return false; Preset.PerformWrite(s => @@ -123,7 +123,7 @@ namespace osu.Game.Overlays.Mods return true; } - private bool checkCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); + public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); protected override void Dispose(bool isDisposing) { From 15f11bb1e8ff7ea4d5ed8defa45ea0069fbd303f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 11 Mar 2023 12:31:33 +0900 Subject: [PATCH 0319/1400] scorll container and save mod after popover hidden Requires manual handling of many visual effects --- .../UserInterface/TestSceneModPresetColumn.cs | 12 ++- osu.Game/Overlays/Mods/EditPresetPopover.cs | 76 +++++++++++++++++-- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ++- osu.Game/Overlays/Mods/ModPresetTooltip.cs | 13 ++-- 4 files changed, 95 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index eaa3664623..68efb2a5f4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -353,7 +353,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddWaitStep("wait some", 3); AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod not changed", () => - !new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); + !new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -378,8 +378,16 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddWaitStep("wait some", 3); - AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod is changed", () => + new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); + + AddStep("click edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); + InputManager.Click(MouseButton.Left); + }); + AddAssert("present mod in realm is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index a5c562914b..92860e96a6 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -1,12 +1,16 @@ // 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 System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Extensions; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Localisation; @@ -23,8 +27,19 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox descriptionTextBox; private readonly ShearedButton useCurrentModButton; private readonly ShearedButton createButton; + private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; + private List saveModAfterClosed = new List(); + + [Resolved] + private Bindable> selectedMods { get; set; } = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; public EditPresetPopover(ModPresetPanel modPresetPanel) { @@ -53,6 +68,19 @@ namespace osu.Game.Overlays.Mods Label = CommonStrings.Description, TabbableContentContainer = this }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.X, + Height = 100, + Padding = new MarginPadding(7), + Child = scrollContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding(7), + Spacing = new Vector2(7), + } + }, new FillFlowContainer { Anchor = Anchor.TopCentre, @@ -83,7 +111,7 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, OsuColour colours) + private void load() { Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; @@ -95,17 +123,40 @@ namespace osu.Game.Overlays.Mods createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; + selectedMods.BindValueChanged(_ => updateActiveState(), true); + + scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } private void trySaveCurrentMod() { - if (button.SaveCurrentMod()) + if (!button.CheckCurrentModCanBeSave()) + { + Body.Shake(); return; + } - Body.Shake(); + saveModAfterClosed = selectedMods.Value.ToList(); + scrollContent.Clear(); + scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); + button.Mods.Value = saveModAfterClosed; + updateActiveState(); + } + + private void updateActiveState() + { + if (button.CheckCurrentModCanBeSave()) + { + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; + } + else + { + useCurrentModButton.DarkerColour = colours.Blue3; + useCurrentModButton.LighterColour = colours.Blue4; + useCurrentModButton.TextColour = colourProvider.Background2; + } } protected override void LoadComplete() @@ -131,5 +182,18 @@ namespace osu.Game.Overlays.Mods this.HidePopover(); } + + protected override void UpdateState(ValueChangedEvent state) + { + base.UpdateState(state); + + if (state.NewValue == Visibility.Hidden && saveModAfterClosed.Any()) + { + button.Preset.PerformWrite(s => + { + s.Mods = saveModAfterClosed; + }); + } + } } } diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index d01981d18c..49437c5bb1 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -18,10 +18,12 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip>, IHasContextMenu, IHasPopover { public readonly Live Preset; + public readonly Bindable> Mods = new Bindable>(); + public override BindableBool Active { get; } = new BindableBool(); [Resolved] @@ -35,6 +37,7 @@ namespace osu.Game.Overlays.Mods public ModPresetPanel(Live preset) { Preset = preset; + Mods.Value = preset.Value.Mods.ToList(); Title = preset.Value.Name; Description = preset.Value.Description; @@ -51,6 +54,7 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); selectedMods.BindValueChanged(_ => selectedModsChanged(), true); + Mods.BindValueChanged(_ => updateActiveState(), true); } protected override void Select() @@ -78,13 +82,13 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - Active.Value = new HashSet(Preset.Value.Mods).SetEquals(selectedMods.Value); + Active.Value = new HashSet(Mods.Value).SetEquals(selectedMods.Value); } #region IHasCustomTooltip - public ModPreset TooltipContent => Preset.Value; - public ITooltip GetCustomTooltip() => new ModPresetTooltip(ColourProvider); + public List TooltipContent => Mods.Value; + public ITooltip> GetCustomTooltip() => new ModPresetTooltip(ColourProvider); #endregion diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index 8e8259de45..0b31a97064 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.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 System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -11,7 +12,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPresetTooltip : VisibilityContainer, ITooltip + public partial class ModPresetTooltip : VisibilityContainer, ITooltip> { protected override Container Content { get; } @@ -42,15 +43,15 @@ namespace osu.Game.Overlays.Mods }; } - private ModPreset? lastPreset; + private List? lastPreset; - public void SetContent(ModPreset preset) + public void SetContent(List mods) { - if (ReferenceEquals(preset, lastPreset)) + if (ReferenceEquals(mods, lastPreset)) return; - lastPreset = preset; - Content.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + lastPreset = mods; + Content.ChildrenEnumerable = mods.Select(mod => new ModPresetRow(mod)); } protected override void PopIn() => this.FadeIn(transition_duration, Easing.OutQuint); From 8e8dda3ac0ad1d49043198681fcac2b092c9cdda Mon Sep 17 00:00:00 2001 From: Terochi Date: Sat, 11 Mar 2023 23:29:36 +0100 Subject: [PATCH 0320/1400] Big simplifying --- osu.Game.Tests/Mods/ModSettingsTest.cs | 83 +++---------------- .../TestSceneModSelectOverlay.cs | 42 ---------- osu.Game/Rulesets/Mods/Mod.cs | 61 ++------------ 3 files changed, 19 insertions(+), 167 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index e2e050870e..d943f0ffb1 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Localisation; @@ -42,16 +41,20 @@ namespace osu.Game.Tests.Mods { const double setting_change = 50.4; - var modDouble = new TestNonMatchingSettingTypeModDouble(); - var modBool = new TestNonMatchingSettingTypeModBool(); + var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { Value = setting_change } }; + var modBool = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = (int)setting_change } }; - modDouble.TestSetting.Value = setting_change; - modBool.TestSetting.Value = !modBool.TestSetting.Default; modDouble.CopySharedSettings(modBool); + modDouble.CopySharedSettings(modInt); modBool.CopySharedSettings(modDouble); + modBool.CopySharedSettings(modInt); + modInt.CopySharedSettings(modDouble); + modInt.CopySharedSettings(modBool); Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); + Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change)); } [Test] @@ -70,75 +73,11 @@ namespace osu.Game.Tests.Mods public void TestValueResetsToDefaultWhenCopied() { var modDouble = new TestNonMatchingSettingTypeModDouble(); - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = 1 } }; + var modBool = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - modInt.CopySharedSettings(modDouble); + modBool.CopySharedSettings(modDouble); - Assert.That(modInt.TestSetting.Value, Is.EqualTo(modInt.TestSetting.Default)); - } - - [Test] - public void TestRelativelyScaleWithClampedRangeWhenCopied() - { - const double setting_change = 50.4; - - var modDouble100 = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 100, MinValue = 0, Value = setting_change } }; - var modDouble200 = new TestNonMatchingSettingTypeModDouble { TestSetting = { MaxValue = 200, MinValue = 0 } }; - - modDouble200.CopySharedSettings(modDouble100); - - Assert.That(modDouble200.TestSetting.Value, Is.EqualTo(setting_change * 2)); - } - - [Test] - public void TestCopyDoubleToIntWithDefaultRange() - { - const double setting_change = 50.4; - - var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { Value = setting_change } }; - var modInt = new TestNonMatchingSettingTypeModInt(); - - modInt.CopySharedSettings(modDouble); - - Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change))); - } - - [Test] - public void TestCopyDoubleToIntWithOutOfBoundsRange() - { - const double setting_change = 50.4; - - var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MinValue = int.MinValue - 1d, Value = setting_change } }; - // make RangeConstrainedBindable.HasDefinedRange return true - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MinValue = int.MinValue + 1 } }; - - modInt.CopySharedSettings(modDouble); - - Assert.That(modInt.TestSetting.Value, Is.EqualTo(Convert.ToInt32(setting_change))); - } - - [Test] - public void TestCopyDoubleToIntWithOutOfBoundsValue() - { - var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { MinValue = int.MinValue + 1, Value = int.MaxValue + 1d } }; - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { MinValue = int.MinValue + 1 } }; - - modInt.CopySharedSettings(modDouble); - - Assert.That(modInt.TestSetting.Value, Is.EqualTo(int.MaxValue)); - } - - [Test] - public void TestCopyIntToDoubleWithDefaultRange() - { - const int setting_change = 50; - - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = setting_change } }; - var modDouble = new TestNonMatchingSettingTypeModDouble(); - - modDouble.CopySharedSettings(modInt); - - Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); + Assert.That(modBool.TestSetting.Value, Is.EqualTo(modBool.TestSetting.Default)); } private class TestNonMatchingSettingTypeModDouble : TestNonMatchingSettingTypeMod diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 75efc07d43..b4b5052f23 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -18,7 +18,6 @@ using osu.Game.Overlays.Mods; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch.Mods; -using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; @@ -417,47 +416,6 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - [Test] - public void TestKeepSharedSettingsRatio() - { - const float setting_change = 1.8f; - - createScreen(); - changeRuleset(0); - - AddStep("select flashlight mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod()! }); - - changeRuleset(0); - AddAssert("ensure mod still selected", () => SelectedMods.Value.SingleOrDefault() is OsuModFlashlight); - - AddStep("change mod settings", () => - { - var osuMod = getMod(); - - // range <0.5 - 2> - osuMod.SizeMultiplier.Value = setting_change; - }); - - changeRuleset(3); - AddAssert("mania variant selected", () => SelectedMods.Value.SingleOrDefault() is ManiaModFlashlight); - - AddAssert("shared settings changed to closest ratio", () => - { - var maniaMod = getMod(); - - // range <0.5 - 3> - // converted value based on ratio = (setting_change - 0.5) / (2 - 0.5) * (3 - 0.5) + 0.5 = 2.66 - return maniaMod.SizeMultiplier.Value == 2.7f; // taking precision into account - }); - - AddAssert("other settings unchanged", () => - { - var maniaMod = getMod(); - - return maniaMod.ComboBasedSize.IsDefault; - }); - } - [Test] public void TestExternallySetCustomizedMod() { diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 85014d555d..623a734b82 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -165,8 +165,6 @@ namespace osu.Game.Rulesets.Mods /// The mod to copy properties from. internal void CopySharedSettings(Mod source) { - const string min_value = nameof(BindableNumber.MinValue); - const string max_value = nameof(BindableNumber.MaxValue); const string value = nameof(Bindable.Value); Dictionary sourceSettings = new Dictionary(); @@ -190,65 +188,22 @@ namespace osu.Game.Rulesets.Mods continue; } + bool hasSameGenericArgument = getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == + getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single(); + + if (!hasSameGenericArgument) + continue; + Type? targetBindableNumberType = getGenericBaseType(targetSetting, typeof(BindableNumber<>)); Type? sourceBindableNumberType = getGenericBaseType(sourceSetting, typeof(BindableNumber<>)); if (targetBindableNumberType == null || sourceBindableNumberType == null) { - if (getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == - getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single()) - { - // change settings only if the type is the same - setValue(targetSetting, value, getValue(sourceSetting, value)); - } - + setValue(targetSetting, value, getValue(sourceSetting, value)); continue; } - bool rangeOutOfBounds = false; - - Type targetGenericType = targetBindableNumberType.GenericTypeArguments.Single(); - Type sourceGenericType = sourceBindableNumberType.GenericTypeArguments.Single(); - - if (!Convert.ToBoolean(getValue(targetSetting, nameof(RangeConstrainedBindable.HasDefinedRange))) || - !Convert.ToBoolean(getValue(sourceSetting, nameof(RangeConstrainedBindable.HasDefinedRange)))) - // check if we have a range to rescale from and a range to rescale to - // if not, copy the raw value - rangeOutOfBounds = true; - - double allowedMin = Math.Max( - Convert.ToDouble(targetGenericType.GetField("MinValue")!.GetValue(null)), - Convert.ToDouble(sourceGenericType.GetField("MinValue")!.GetValue(null)) - ); - - double allowedMax = Math.Min( - Convert.ToDouble(targetGenericType.GetField("MaxValue")!.GetValue(null)), - Convert.ToDouble(sourceGenericType.GetField("MaxValue")!.GetValue(null)) - ); - - double targetMin = getValueDouble(targetSetting, min_value); - double targetMax = getValueDouble(targetSetting, max_value); - double sourceMin = getValueDouble(sourceSetting, min_value); - double sourceMax = getValueDouble(sourceSetting, max_value); - double sourceValue = Math.Clamp(getValueDouble(sourceSetting, value), allowedMin, allowedMax); - - double targetValue = rangeOutOfBounds - // keep raw value - ? sourceValue - // convert value to same ratio - : (sourceValue - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin; - - setValue(targetSetting, value, Convert.ChangeType(targetValue, targetBindableNumberType.GenericTypeArguments.Single())); - - double getValueDouble(object setting, string name) - { - double settingValue = Convert.ToDouble(getValue(setting, name)!); - - if (settingValue < allowedMin || settingValue > allowedMax) - rangeOutOfBounds = true; - - return settingValue; - } + setValue(targetSetting, value, Convert.ChangeType(getValue(sourceSetting, value), targetBindableNumberType.GenericTypeArguments.Single())); } object? getValue(object setting, string name) => From febdca45470f34a7cdfc493cddc13f371593099c Mon Sep 17 00:00:00 2001 From: Derrick Timmermans Date: Sun, 12 Mar 2023 02:08:00 +0100 Subject: [PATCH 0321/1400] Fix argon progress bar fill being oversized --- osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index 6db1072fbb..dd6e10ba5d 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -242,7 +242,6 @@ namespace osu.Game.Screens.Play.HUD { length = value; mask.Width = value * DrawWidth; - fill.Width = value * DrawWidth; } } From 0cf69a10846b59934a837d3a39b43c812092f848 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 11 Mar 2023 21:35:52 -0800 Subject: [PATCH 0322/1400] Make yaml line strings verbatim --- osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index 5f8bee7558..8dc058bd69 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -30,11 +30,11 @@ namespace osu.Game.Overlays.Wiki.Markdown { switch (line.ToString()) { - case "outdated: true": + case @"outdated: true": isOutdated = true; break; - case "needs_cleanup: true": + case @"needs_cleanup: true": needsCleanup = true; break; } From ea88aee41f27491d4022c5bb38a4661f55661e3c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 11 Mar 2023 21:36:15 -0800 Subject: [PATCH 0323/1400] Display stub notice in marked wiki articles --- .../Overlays/Wiki/Markdown/WikiNoticeContainer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index 8dc058bd69..df800f47b1 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -19,6 +19,7 @@ namespace osu.Game.Overlays.Wiki.Markdown { private readonly bool isOutdated; private readonly bool needsCleanup; + private readonly bool isStub; public WikiNoticeContainer(YamlFrontMatterBlock yamlFrontMatterBlock) { @@ -37,6 +38,10 @@ namespace osu.Game.Overlays.Wiki.Markdown case @"needs_cleanup: true": needsCleanup = true; break; + + case @"stub: true": + isStub = true; + break; } } } @@ -60,6 +65,14 @@ namespace osu.Game.Overlays.Wiki.Markdown Text = WikiStrings.ShowNeedsCleanupOrRewrite, }); } + + if (isStub) + { + Add(new NoticeBox + { + Text = WikiStrings.ShowStub, + }); + } } private partial class NoticeBox : Container From 6e5b1280b7261d37e89a494b973f35905099d630 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 11 Mar 2023 21:18:56 -0800 Subject: [PATCH 0324/1400] Fix multiple notice boxes having no spacing --- osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index df800f47b1..a40bd14878 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Resources.Localisation.Web; +using osuTK; namespace osu.Game.Overlays.Wiki.Markdown { @@ -26,6 +27,7 @@ namespace osu.Game.Overlays.Wiki.Markdown RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; + Spacing = new Vector2(10); foreach (object line in yamlFrontMatterBlock.Lines) { From c1618a7a16f923cf57f891150d19fd9afde06aa7 Mon Sep 17 00:00:00 2001 From: Rovearix Date: Sun, 12 Mar 2023 10:57:53 -0400 Subject: [PATCH 0325/1400] Prevent elements that are anchored in the center from blocking loading --- osu.Game/Graphics/UserInterface/LoadingLayer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 9059b61a33..7cd54304b7 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -69,6 +69,10 @@ namespace osu.Game.Graphics.UserInterface // note that this will not work well if touch handling elements are beneath this loading layer (something to consider for the future). case TouchEvent: return false; + + // blocking drag events to prevent unintended ui pausing while loading a beat map (see https://github.com/ppy/osu/issues/22657) + case DragEvent: + return false; } return true; From 12f240e11ad13b2bcc3a348135a78194bb130919 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Mar 2023 18:23:28 +0900 Subject: [PATCH 0326/1400] Apply simple NRT changes to touched test scenes --- .../Formats/LegacyBeatmapDecoderTest.cs | 33 ++++++++++--------- .../Formats/LegacyStoryboardDecoderTest.cs | 14 ++++---- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 85d304da9c..e2a8062569 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; +using System.Diagnostics; using System.IO; using System.Linq; using NUnit.Framework; @@ -320,6 +319,8 @@ namespace osu.Game.Tests.Beatmaps.Formats { var comboColors = decoder.Decode(stream).ComboColours; + Debug.Assert(comboColors != null); + Color4[] expectedColors = { new Color4(142, 199, 255, 255), @@ -330,7 +331,7 @@ namespace osu.Game.Tests.Beatmaps.Formats new Color4(255, 177, 140, 255), new Color4(100, 100, 100, 255), // alpha is specified as 100, but should be ignored. }; - Assert.AreEqual(expectedColors.Length, comboColors?.Count); + Assert.AreEqual(expectedColors.Length, comboColors.Count); for (int i = 0; i < expectedColors.Length; i++) Assert.AreEqual(expectedColors[i], comboColors[i]); } @@ -415,14 +416,14 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsNotNull(positionData); Assert.IsNotNull(curveData); - Assert.AreEqual(new Vector2(192, 168), positionData.Position); + Assert.AreEqual(new Vector2(192, 168), positionData!.Position); Assert.AreEqual(956, hitObjects[0].StartTime); Assert.IsTrue(hitObjects[0].Samples.Any(s => s.Name == HitSampleInfo.HIT_NORMAL)); positionData = hitObjects[1] as IHasPosition; Assert.IsNotNull(positionData); - Assert.AreEqual(new Vector2(304, 56), positionData.Position); + Assert.AreEqual(new Vector2(304, 56), positionData!.Position); Assert.AreEqual(1285, hitObjects[1].StartTime); Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == HitSampleInfo.HIT_CLAP)); } @@ -578,8 +579,8 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestFallbackDecoderForCorruptedHeader() { - Decoder decoder = null; - Beatmap beatmap = null; + Decoder decoder = null!; + Beatmap beatmap = null!; using (var resStream = TestResources.OpenResource("corrupted-header.osu")) using (var stream = new LineBufferedReader(resStream)) @@ -596,8 +597,8 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestFallbackDecoderForMissingHeader() { - Decoder decoder = null; - Beatmap beatmap = null; + Decoder decoder = null!; + Beatmap beatmap = null!; using (var resStream = TestResources.OpenResource("missing-header.osu")) using (var stream = new LineBufferedReader(resStream)) @@ -614,8 +615,8 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestDecodeFileWithEmptyLinesAtStart() { - Decoder decoder = null; - Beatmap beatmap = null; + Decoder decoder = null!; + Beatmap beatmap = null!; using (var resStream = TestResources.OpenResource("empty-lines-at-start.osu")) using (var stream = new LineBufferedReader(resStream)) @@ -632,8 +633,8 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestDecodeFileWithEmptyLinesAndNoHeader() { - Decoder decoder = null; - Beatmap beatmap = null; + Decoder decoder = null!; + Beatmap beatmap = null!; using (var resStream = TestResources.OpenResource("empty-line-instead-of-header.osu")) using (var stream = new LineBufferedReader(resStream)) @@ -650,8 +651,8 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestDecodeFileWithContentImmediatelyAfterHeader() { - Decoder decoder = null; - Beatmap beatmap = null; + Decoder decoder = null!; + Beatmap beatmap = null!; using (var resStream = TestResources.OpenResource("no-empty-line-after-header.osu")) using (var stream = new LineBufferedReader(resStream)) @@ -678,7 +679,7 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestAllowFallbackDecoderOverwrite() { - Decoder decoder = null; + Decoder decoder = null!; using (var resStream = TestResources.OpenResource("corrupted-header.osu")) using (var stream = new LineBufferedReader(resStream)) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 281ea4e4ff..577ae3fe95 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osuTK; @@ -30,35 +28,35 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsTrue(storyboard.HasDrawable); Assert.AreEqual(6, storyboard.Layers.Count()); - StoryboardLayer background = storyboard.Layers.FirstOrDefault(l => l.Depth == 3); + StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3); Assert.IsNotNull(background); Assert.AreEqual(16, background.Elements.Count); Assert.IsTrue(background.VisibleWhenFailing); Assert.IsTrue(background.VisibleWhenPassing); Assert.AreEqual("Background", background.Name); - StoryboardLayer fail = storyboard.Layers.FirstOrDefault(l => l.Depth == 2); + StoryboardLayer fail = storyboard.Layers.Single(l => l.Depth == 2); Assert.IsNotNull(fail); Assert.AreEqual(0, fail.Elements.Count); Assert.IsTrue(fail.VisibleWhenFailing); Assert.IsFalse(fail.VisibleWhenPassing); Assert.AreEqual("Fail", fail.Name); - StoryboardLayer pass = storyboard.Layers.FirstOrDefault(l => l.Depth == 1); + StoryboardLayer pass = storyboard.Layers.Single(l => l.Depth == 1); Assert.IsNotNull(pass); Assert.AreEqual(0, pass.Elements.Count); Assert.IsFalse(pass.VisibleWhenFailing); Assert.IsTrue(pass.VisibleWhenPassing); Assert.AreEqual("Pass", pass.Name); - StoryboardLayer foreground = storyboard.Layers.FirstOrDefault(l => l.Depth == 0); + StoryboardLayer foreground = storyboard.Layers.Single(l => l.Depth == 0); Assert.IsNotNull(foreground); Assert.AreEqual(151, foreground.Elements.Count); Assert.IsTrue(foreground.VisibleWhenFailing); Assert.IsTrue(foreground.VisibleWhenPassing); Assert.AreEqual("Foreground", foreground.Name); - StoryboardLayer overlay = storyboard.Layers.FirstOrDefault(l => l.Depth == int.MinValue); + StoryboardLayer overlay = storyboard.Layers.Single(l => l.Depth == int.MinValue); Assert.IsNotNull(overlay); Assert.IsEmpty(overlay.Elements); Assert.IsTrue(overlay.VisibleWhenFailing); @@ -76,7 +74,7 @@ namespace osu.Game.Tests.Beatmaps.Formats var sprite = background.Elements.ElementAt(0) as StoryboardSprite; Assert.NotNull(sprite); - Assert.IsTrue(sprite.HasCommands); + Assert.IsTrue(sprite!.HasCommands); Assert.AreEqual(new Vector2(320, 240), sprite.InitialPosition); Assert.IsTrue(sprite.IsDrawable); Assert.AreEqual(Anchor.Centre, sprite.Origin); From 3aea058c98e07bcc4435dcb94ed49aa0c82aff8f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Mar 2023 18:15:17 +0900 Subject: [PATCH 0327/1400] Add test coverage ensuring images are not read as videos --- .../Formats/LegacyStoryboardDecoderTest.cs | 15 +++++++++++++++ .../Resources/image-specified-as-video.osb | 4 ++++ 2 files changed, 19 insertions(+) create mode 100644 osu.Game.Tests/Resources/image-specified-as-video.osb diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 577ae3fe95..3a776ac225 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -169,6 +169,21 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeImageSpecifiedAsVideo() + { + var decoder = new LegacyStoryboardDecoder(); + + using (var resStream = TestResources.OpenResource("image-specified-as-video.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var storyboard = decoder.Decode(stream); + + StoryboardLayer foreground = storyboard.Layers.Single(l => l.Name == "Video"); + Assert.That(foreground.Elements.Count, Is.Zero); + } + } + [Test] public void TestDecodeOutOfRangeLoopAnimationType() { diff --git a/osu.Game.Tests/Resources/image-specified-as-video.osb b/osu.Game.Tests/Resources/image-specified-as-video.osb new file mode 100644 index 0000000000..9cea7dd4e7 --- /dev/null +++ b/osu.Game.Tests/Resources/image-specified-as-video.osb @@ -0,0 +1,4 @@ +osu file format v14 + +[Events] +Video,0,"BG.jpg",0,0 From c35c81293a149d00d6c497829a15797ef562c489 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Mar 2023 18:19:18 +0900 Subject: [PATCH 0328/1400] Add test coverage ensuring images specified as videos are used as background image instead --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index e2a8062569..518981980b 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -160,6 +160,21 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeImageSpecifiedAsVideo() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("image-specified-as-video.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var beatmap = decoder.Decode(stream); + var metadata = beatmap.Metadata; + + Assert.AreEqual("BG.jpg", metadata.BackgroundFile); + } + } + [Test] public void TestDecodeBeatmapTimingPoints() { From eb37d740b13b3cafb346a7a0dfb13a8371ebe076 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Mar 2023 17:40:23 +0900 Subject: [PATCH 0329/1400] Update supported video filetypes to match osu-stable --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index cf58d07b9e..8f27e5dc53 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached(typeof(OsuGameBase))] public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; + public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" }; public const string OSU_PROTOCOL = "osu://"; From da947d86613ffe99f19f4d49a6535810ba752c59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 Mar 2023 18:10:16 +0900 Subject: [PATCH 0330/1400] Gracefully handle beatmaps specifying images using the video storyboard type --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 13 +++++++++++++ .../Beatmaps/Formats/LegacyStoryboardDecoder.cs | 11 ++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index eabc63b341..a9bdd21b64 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -363,6 +363,19 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.Metadata.BackgroundFile = CleanFilename(split[3]); break; + case LegacyEventType.Video: + string filename = CleanFilename(split[2]); + + // Some very old beatmaps had incorrect type specifications for their backgrounds (ie. using 1 for VIDEO + // instead of 0 for BACKGROUND). To handle this gracefully, check the file extension against known supported + // video extensions and handle similar to a background if it doesn't match. + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(filename))) + { + beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; + } + + break; + case LegacyEventType.Background: beatmap.BeatmapInfo.Metadata.BackgroundFile = CleanFilename(split[2]); break; diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 44dbb3cc9f..f8308fe431 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -109,6 +109,14 @@ namespace osu.Game.Beatmaps.Formats int offset = Parsing.ParseInt(split[1]); string path = CleanFilename(split[2]); + // See handling in LegacyBeatmapDecoder for the special case where a video type is used but + // the file extension is not a valid video. + // + // This avoids potential weird crashes when ffmpeg attempts to parse an image file as a video + // (see https://github.com/ppy/osu/issues/22829#issuecomment-1465552451). + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(path))) + break; + storyboard.GetLayer("Video").Add(new StoryboardVideo(path, offset)); break; } @@ -276,7 +284,8 @@ namespace osu.Game.Beatmaps.Formats switch (type) { case "A": - timelineGroup?.BlendingParameters.Add(easing, startTime, endTime, BlendingParameters.Additive, startTime == endTime ? BlendingParameters.Additive : BlendingParameters.Inherit); + timelineGroup?.BlendingParameters.Add(easing, startTime, endTime, BlendingParameters.Additive, + startTime == endTime ? BlendingParameters.Additive : BlendingParameters.Inherit); break; case "H": From 1f7721786b02d628d2b2c7c1d16c83b2d1a4a170 Mon Sep 17 00:00:00 2001 From: rozukke Date: Mon, 13 Mar 2023 22:01:26 +1100 Subject: [PATCH 0331/1400] Perform check to account for non-ASCII characters --- osu.Game/Skinning/SkinImporter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinImporter.cs b/osu.Game/Skinning/SkinImporter.cs index 9e2e02876d..43760c4a19 100644 --- a/osu.Game/Skinning/SkinImporter.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -101,7 +101,8 @@ namespace osu.Game.Skinning // In both of these cases, the expectation from the user is that the filename or folder name is displayed somewhere to identify the skin. if (archiveName != item.Name // lazer exports use this format - && archiveName != item.GetDisplayString()) + // GetValidFilename accounts for skins with non-ASCII characters in the name that have been exported by lazer. + && archiveName != item.GetDisplayString().GetValidFilename()) item.Name = @$"{item.Name} [{archiveName}]"; } From ba728bdab1b4662366e3737fd4f84cf413e2d0e1 Mon Sep 17 00:00:00 2001 From: Rovearix Date: Mon, 13 Mar 2023 07:49:51 -0400 Subject: [PATCH 0332/1400] Changed the event to be the more correct one to block --- osu.Game/Graphics/UserInterface/LoadingLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 7cd54304b7..3f9856eddd 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -71,7 +71,7 @@ namespace osu.Game.Graphics.UserInterface return false; // blocking drag events to prevent unintended ui pausing while loading a beat map (see https://github.com/ppy/osu/issues/22657) - case DragEvent: + case DragStartEvent: return false; } From 9ac9287dbd89051a685d9821cbbf951bdef37d7d Mon Sep 17 00:00:00 2001 From: Rovearix Date: Mon, 13 Mar 2023 08:07:55 -0400 Subject: [PATCH 0333/1400] Switched the implementation to set the blockInput flag for the BeatmapMetadataDisplay's LoadingLayer. This prevents the UIEvents from being being handled in this case without modifying the class --- osu.Game/Graphics/UserInterface/LoadingLayer.cs | 4 ---- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 3f9856eddd..9059b61a33 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -69,10 +69,6 @@ namespace osu.Game.Graphics.UserInterface // note that this will not work well if touch handling elements are beneath this loading layer (something to consider for the future). case TouchEvent: return false; - - // blocking drag events to prevent unintended ui pausing while loading a beat map (see https://github.com/ppy/osu/issues/22657) - case DragStartEvent: - return false; } return true; diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 06509b6465..a152f4be19 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, FillMode = FillMode.Fill, }, - loading = new LoadingLayer(true) + loading = new LoadingLayer(dimBackground: true, blockInput: false) } }, versionFlow = new FillFlowContainer From 4570c0030f1211bc166eff6be86ced372c1e0907 Mon Sep 17 00:00:00 2001 From: rozukke Date: Mon, 13 Mar 2023 23:37:45 +1100 Subject: [PATCH 0334/1400] Add test to check for import of exported skin with non-ASCII name --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 0bd40e9962..81ebc59729 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -133,6 +133,25 @@ namespace osu.Game.Tests.Skins.IO assertImportedOnce(import1, import2); }); + [Test] + public Task TestImportExportedNonAsciiSkinFilename() => runSkinTest(async osu => + { + MemoryStream exportStream = new MemoryStream(); + + var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 『1』", "author 1"), "custom.osk")); + assertCorrectMetadata(import1, "name 『1』 [custom]", "author 1", osu); + + import1.PerformRead(s => + { + new LegacySkinExporter(osu.Dependencies.Get()).ExportModelTo(s, exportStream); + }); + + string exportFilename = import1.GetDisplayString().GetValidFilename(); + + var import2 = await loadSkinIntoOsu(osu, new ImportTask(exportStream, $"{exportFilename}.osk")); + assertCorrectMetadata(import2, "name 『1』 [custom]", "author 1", osu); + }); + [Test] public Task TestSameMetadataNameSameFolderName([Values] bool batchImport) => runSkinTest(async osu => { From 300d81c46ba58f7fc8867fcfa99396d3ba04d1c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 16:59:18 +0900 Subject: [PATCH 0335/1400] Add hitting layer to fix hit lighting not being applied to tail piece Taken from https://github.com/ppy/osu/pull/22820#issuecomment-1462626898. --- .../Objects/Drawables/DrawableHoldNoteTail.cs | 2 +- .../Skinning/Argon/ArgonHoldBodyPiece.cs | 41 ++---------- .../Argon/ArgonHoldNoteHittingLayer.cs | 64 +++++++++++++++++++ .../Skinning/Argon/ArgonHoldNoteTailPiece.cs | 31 ++++++++- 4 files changed, 100 insertions(+), 38 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs index 20ea962994..e7326df07d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteTail; - protected DrawableHoldNote HoldNote => (DrawableHoldNote)ParentHitObject; + protected internal DrawableHoldNote HoldNote => (DrawableHoldNote)ParentHitObject; public DrawableHoldNoteTail() : this(null) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs index 91eda57c8f..57fa1c10ae 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldBodyPiece.cs @@ -20,10 +20,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon public partial class ArgonHoldBodyPiece : CompositeDrawable, IHoldNoteBody { protected readonly Bindable AccentColour = new Bindable(); - protected readonly IBindable IsHitting = new Bindable(); private Drawable background = null!; - private Box foreground = null!; + private ArgonHoldNoteHittingLayer hittingLayer = null!; public ArgonHoldBodyPiece() { @@ -40,12 +39,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon InternalChildren = new[] { background = new Box { RelativeSizeAxes = Axes.Both }, - foreground = new Box - { - RelativeSizeAxes = Axes.Both, - Blending = BlendingParameters.Additive, - Alpha = 0, - }, + hittingLayer = new ArgonHoldNoteHittingLayer() }; if (drawableObject != null) @@ -53,44 +47,19 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon var holdNote = (DrawableHoldNote)drawableObject; AccentColour.BindTo(holdNote.AccentColour); - IsHitting.BindTo(holdNote.IsHitting); + hittingLayer.AccentColour.BindTo(holdNote.AccentColour); + ((IBindable)hittingLayer.IsHitting).BindTo(holdNote.IsHitting); } AccentColour.BindValueChanged(colour => { background.Colour = colour.NewValue.Darken(0.6f); - foreground.Colour = colour.NewValue.Opacity(0.2f); }, true); - - IsHitting.BindValueChanged(hitting => - { - const float animation_length = 50; - - foreground.ClearTransforms(); - - if (hitting.NewValue) - { - // wait for the next sync point - double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2); - - using (foreground.BeginDelayedSequence(synchronisedOffset)) - { - foreground.FadeTo(1, animation_length).Then() - .FadeTo(0.5f, animation_length) - .Loop(); - } - } - else - { - foreground.FadeOut(animation_length); - } - }); } public void Recycle() { - foreground.ClearTransforms(); - foreground.Alpha = 0; + hittingLayer.Recycle(); } } } diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs new file mode 100644 index 0000000000..9df7e06a4b --- /dev/null +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osuTK.Graphics; +using Box = osu.Framework.Graphics.Shapes.Box; + +namespace osu.Game.Rulesets.Mania.Skinning.Argon +{ + public partial class ArgonHoldNoteHittingLayer : Box + { + public readonly Bindable AccentColour = new Bindable(); + public readonly Bindable IsHitting = new Bindable(); + + public ArgonHoldNoteHittingLayer() + { + RelativeSizeAxes = Axes.Both; + Blending = BlendingParameters.Additive; + Alpha = 0; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + AccentColour.BindValueChanged(colour => + { + Colour = colour.NewValue.Opacity(0.2f); + }, true); + + IsHitting.BindValueChanged(hitting => + { + const float animation_length = 50; + + ClearTransforms(); + + if (hitting.NewValue) + { + // wait for the next sync point + double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2); + + using (BeginDelayedSequence(synchronisedOffset)) + { + this.FadeTo(1, animation_length).Then() + .FadeTo(0.5f, animation_length) + .Loop(); + } + } + else + { + this.FadeOut(animation_length); + } + }); + } + + public void Recycle() + { + ClearTransforms(); + Alpha = 0; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs index 085e0630fb..efd7f4f280 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -17,10 +18,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { internal partial class ArgonHoldNoteTailPiece : CompositeDrawable { + [Resolved] + private DrawableHitObject? drawableObject { get; set; } + private readonly IBindable direction = new Bindable(); private readonly IBindable accentColour = new Bindable(); private readonly Box foreground; + private readonly ArgonHoldNoteHittingLayer hittingLayer; private readonly Box foregroundAdditive; public ArgonHoldNoteTailPiece() @@ -59,6 +64,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { RelativeSizeAxes = Axes.Both, }, + hittingLayer = new ArgonHoldNoteHittingLayer(), foregroundAdditive = new Box { RelativeSizeAxes = Axes.Both, @@ -73,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon } [BackgroundDependencyLoader(true)] - private void load(IScrollingInfo scrollingInfo, DrawableHitObject? drawableObject) + private void load(IScrollingInfo scrollingInfo) { direction.BindTo(scrollingInfo.Direction); direction.BindValueChanged(onDirectionChanged, true); @@ -82,9 +88,24 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { accentColour.BindTo(drawableObject.AccentColour); accentColour.BindValueChanged(onAccentChanged, true); + + drawableObject.HitObjectApplied += hitObjectApplied; } } + private void hitObjectApplied(DrawableHitObject drawableHitObject) + { + var holdNoteTail = (DrawableHoldNoteTail)drawableHitObject; + + hittingLayer.Recycle(); + + hittingLayer.AccentColour.UnbindBindings(); + hittingLayer.AccentColour.BindTo(holdNoteTail.HoldNote.AccentColour); + + hittingLayer.IsHitting.UnbindBindings(); + ((IBindable)hittingLayer.IsHitting).BindTo(holdNoteTail.HoldNote.IsHitting); + } + private void onDirectionChanged(ValueChangedEvent direction) { Scale = new Vector2(1, direction.NewValue == ScrollingDirection.Up ? -1 : 1); @@ -99,5 +120,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon accent.NewValue.Opacity(0) ); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (drawableObject != null) + drawableObject.HitObjectApplied -= hitObjectApplied; + } } } From 48d11610b344ac23dd0ff3628b90ee4b4b40402d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 17:44:51 +0900 Subject: [PATCH 0336/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 234575fc62..4e580a6919 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 103ac99172..a84b42d9a4 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index fde45817cf..8738979c57 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 0b23809585d73617942c7f5a0edebfcab2ca02ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 17:52:17 +0900 Subject: [PATCH 0337/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a84b42d9a4..c08dc9ed8f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From f40a4b591fe30341289619ca83fc4e3459ee392a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 17:29:54 +0900 Subject: [PATCH 0338/1400] Adjust animation length and colouring of hitting layer --- .../Skinning/Argon/ArgonHoldNoteHittingLayer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs index 9df7e06a4b..9e7afa8b9e 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteHittingLayer.cs @@ -27,12 +27,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon AccentColour.BindValueChanged(colour => { - Colour = colour.NewValue.Opacity(0.2f); + Colour = colour.NewValue.Lighten(0.2f).Opacity(0.3f); }, true); IsHitting.BindValueChanged(hitting => { - const float animation_length = 50; + const float animation_length = 80; ClearTransforms(); @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon using (BeginDelayedSequence(synchronisedOffset)) { - this.FadeTo(1, animation_length).Then() - .FadeTo(0.5f, animation_length) + this.FadeTo(1, animation_length, Easing.OutSine).Then() + .FadeTo(0.5f, animation_length, Easing.InSine) .Loop(); } } @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { this.FadeOut(animation_length); } - }); + }, true); } public void Recycle() From 5aebbac6c5e8377f265404139c7630b9da834464 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 18:15:18 +0900 Subject: [PATCH 0339/1400] Fix osu!mania hold note animations not correctly re-applying after rewind There's early exit logic in `OnPressed`/`OnReleased` for the sake of keeping order correct, but this doesn't account for the fact that `DrawableHitObject` resets all animations when the hit state changes. A bit of an ugly workaround, but seems to work as expected. --- .../Objects/Drawables/DrawableHoldNote.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 25d0573a82..3bf3aec9c3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -323,7 +323,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // do not run any of this logic when rewinding, as it inverts order of presses/releases. if (Time.Elapsed < 0) + { + // Except for the IsHitting state, as this handles animations that need to be reapplied + // after rewind. + isHitting.Value = false; return; + } // Make sure a hold was started if (HoldStartTime == null) From 4cea29402bfae7a537bd27a11df3b338b5b9f350 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 18:32:24 +0900 Subject: [PATCH 0340/1400] Don't show epilepsy warning when storyboards are disabled I have more thoughts on this warning in general (which will likely see it removed or moved in the future) but this seems like a quick QOL fix for now. As mentioned in https://github.com/ppy/osu/discussions/22861. --- osu.Game/Screens/Play/PlayerLoader.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 4f7e4add32..be4229ade9 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -67,6 +67,8 @@ namespace osu.Game.Screens.Play private OsuScrollContainer settingsScroll = null!; + private Bindable showStoryboards = null!; + private bool backgroundBrightnessReduction; private readonly BindableDouble volumeAdjustment = new BindableDouble(1); @@ -149,10 +151,11 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(SessionStatics sessionStatics, AudioManager audio) + private void load(SessionStatics sessionStatics, AudioManager audio, OsuConfigManager config) { muteWarningShownOnce = sessionStatics.GetBindable(Static.MutedAudioNotificationShownOnce); batteryWarningShownOnce = sessionStatics.GetBindable(Static.LowBatteryNotificationShownOnce); + showStoryboards = config.GetBindable(OsuSetting.ShowStoryboard); const float padding = 25; @@ -463,7 +466,10 @@ namespace osu.Game.Screens.Play // only show if the warning was created (i.e. the beatmap needs it) // and this is not a restart of the map (the warning expires after first load). - if (epilepsyWarning?.IsAlive == true) + // + // note the late check of storyboard enable as the user may have just changed it + // from the settings on the loader screen. + if (epilepsyWarning?.IsAlive == true && showStoryboards.Value) { const double epilepsy_display_length = 3000; From d65d09e45f9c02186bec88fcb9ab01867ead71b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 20:24:39 +0900 Subject: [PATCH 0341/1400] Change field to `const` --- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 5b7b94ff4c..28a715ca0b 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -252,7 +252,7 @@ namespace osu.Game.Graphics.Backgrounds private class TrianglesDrawNode : DrawNode { - private float fill = 1f; + private const float fill = 1f; protected new Triangles Source => (Triangles)base.Source; From b5ea855b6cf8ff9faa5659c1a2e6f4e41b5f5739 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 20:37:50 +0900 Subject: [PATCH 0342/1400] Fix failing `DrawableRulesetDependencies` test --- .../Rulesets/TestSceneDrawableRulesetDependencies.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs index 5cfcca303f..f8248e88bb 100644 --- a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs +++ b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs @@ -80,7 +80,7 @@ namespace osu.Game.Tests.Rulesets dependencies.CacheAs(ParentTextureStore = new TestTextureStore(parent.Get().Renderer)); dependencies.CacheAs(ParentSampleStore = new TestSampleStore()); - dependencies.CacheAs(ParentShaderManager = new TestShaderManager(parent.Get().Renderer)); + dependencies.CacheAs(ParentShaderManager = new TestShaderManager(parent.Get().Renderer, parent.Get())); return new DrawableRulesetDependencies(new OsuRuleset(), dependencies); } @@ -156,12 +156,15 @@ namespace osu.Game.Tests.Rulesets private class TestShaderManager : ShaderManager { - public TestShaderManager(IRenderer renderer) + private readonly ShaderManager parentManager; + + public TestShaderManager(IRenderer renderer, ShaderManager parentManager) : base(renderer, new ResourceStore()) { + this.parentManager = parentManager; } - public override byte[] LoadRaw(string name) => null; + public override byte[] LoadRaw(string name) => parentManager.LoadRaw(name); public bool IsDisposed { get; private set; } From 3c4e2d8700163f8647717643ba6e5575dc3401ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Mar 2023 21:04:51 +0900 Subject: [PATCH 0343/1400] Add tests covering drag selection --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 7af2b7d6fe..a999a9b4fc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -54,6 +54,72 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for loaded", () => skinEditor.IsLoaded); } + [Test] + public void TestDragSelection() + { + BigBlackBox box1 = null!; + BigBlackBox box2 = null!; + BigBlackBox box3 = null!; + + AddStep("Add big black boxes", () => + { + var target = Player.ChildrenOfType().First(); + target.Add(box1 = new BigBlackBox + { + Position = new Vector2(-90), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + target.Add(box2 = new BigBlackBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + target.Add(box3 = new BigBlackBox + { + Position = new Vector2(90), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + }); + + AddStep("Begin drag top left", () => + { + InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.TopLeft - new Vector2(box1.ScreenSpaceDrawQuad.Width / 4)); + InputManager.PressButton(MouseButton.Left); + }); + + AddStep("Drag to bottom right", () => + { + InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre + new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); + }); + + AddStep("Release button", () => + { + InputManager.ReleaseButton(MouseButton.Left); + }); + + AddAssert("First two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box1, box2 })); + + AddStep("Begin drag bottom right", () => + { + InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.BottomRight + new Vector2(box3.ScreenSpaceDrawQuad.Width / 4)); + InputManager.PressButton(MouseButton.Left); + }); + + AddStep("Drag to top left", () => + { + InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); + }); + + AddStep("Release button", () => + { + InputManager.ReleaseButton(MouseButton.Left); + }); + + AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); + } + [Test] public void TestCyclicSelection() { From 1d5e5966153e5fbacb206518bdeb7c70b88955b7 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 14 Mar 2023 20:44:30 +0100 Subject: [PATCH 0344/1400] Update `FailAnimation` to use `SkinnableSound` --- osu.Game/Screens/Play/FailAnimation.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs index 0214d33549..57bdad079e 100644 --- a/osu.Game/Screens/Play/FailAnimation.cs +++ b/osu.Game/Screens/Play/FailAnimation.cs @@ -1,15 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Audio; -using osu.Framework.Bindables; -using osu.Game.Rulesets.UI; using System; using System.Collections.Generic; using ManagedBass.Fx; using osu.Framework.Allocation; -using osu.Framework.Audio.Sample; +using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,6 +19,7 @@ using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -50,8 +49,7 @@ namespace osu.Game.Screens.Play private const float duration = 2500; - private ISample? failSample; - private SampleChannel? failSampleChannel; + private SkinnableSound failSample = null!; [Resolved] private OsuConfigManager config { get; set; } = null!; @@ -76,10 +74,10 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(AudioManager audio, ISkinSource skin, IBindable beatmap) + private void load(AudioManager audio, IBindable beatmap) { track = beatmap.Value.Track; - failSample = skin.GetSample(new SampleInfo(@"Gameplay/failsound")); + AddInternal(failSample = new SkinnableSound(new SampleInfo("Gameplay/failsound"))); AddRangeInternal(new Drawable[] { @@ -126,7 +124,7 @@ namespace osu.Game.Screens.Play failHighPassFilter.CutoffTo(300); failLowPassFilter.CutoffTo(300, duration, Easing.OutCubic); - failSampleChannel = failSample?.Play(); + failSample.Play(); track.AddAdjustment(AdjustableProperty.Frequency, trackFreq); track.AddAdjustment(AdjustableProperty.Volume, volumeAdjustment); @@ -159,7 +157,7 @@ namespace osu.Game.Screens.Play /// public void Stop() { - failSampleChannel?.Stop(); + failSample.Stop(); removeFilters(); } From 390ad335d0aa8c1cb7f5a8bb99af0d905c0de034 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 14 Mar 2023 21:35:52 +0100 Subject: [PATCH 0345/1400] Reloading samples before playing then when skin change occurs --- osu.Game/Skinning/SkinnableSound.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 475b79053a..43e16f4930 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -115,6 +115,10 @@ namespace osu.Game.Skinning /// public virtual void Play() { + if (Scheduler.HasPendingTasks) + // update samples queued due to skin change before playing them + UpdateSubTree(); + samplesContainer.ForEach(c => { if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) From 1cf870d956289393abbdcc2578070b90fe9f8fc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 15:16:48 +0900 Subject: [PATCH 0346/1400] Add test coverage and fix fail case where a drag selection ends incorrectly with cyclic selection --- osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs | 10 +++++++++- .../Edit/Compose/Components/BlueprintContainer.cs | 9 ++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index a999a9b4fc..35ba363f4b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -83,6 +83,14 @@ namespace osu.Game.Tests.Visual.Gameplay }); }); + // This step is specifically added to reproduce an edge case which was found during cyclic selection development. + // If everything is working as expected it should not affect the subsequent drag selections. + AddRepeatStep("Select top left", () => + { + InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.TopLeft + new Vector2(box1.ScreenSpaceDrawQuad.Width / 8)); + InputManager.Click(MouseButton.Left); + }, 2); + AddStep("Begin drag top left", () => { InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.TopLeft - new Vector2(box1.ScreenSpaceDrawQuad.Width / 4)); @@ -91,7 +99,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Drag to bottom right", () => { - InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre + new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); + InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); }); AddStep("Release button", () => diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 3ba71cebe6..143f343c7d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -178,6 +178,7 @@ namespace osu.Game.Screens.Edit.Compose.Components endClickSelection(e); clickSelectionHandled = false; isDraggingBlueprint = false; + wasDragStarted = false; }); finishSelectionMovement(); @@ -191,6 +192,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; lastDragEvent = e; + wasDragStarted = true; if (movementBlueprints != null) { @@ -399,7 +401,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - if (selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) + if (!wasDragStarted && selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) { // If a click occurred and was handled by the currently selected blueprint but didn't result in a drag, // cycle between other blueprints which are also under the cursor. @@ -485,6 +487,11 @@ namespace osu.Game.Screens.Edit.Compose.Components /// private bool isDraggingBlueprint; + /// + /// Whether a drag operation was started at all. + /// + private bool wasDragStarted; + /// /// Attempts to begin the movement of any selected blueprints. /// From 6c4f596a9a1a2c0321f0ba1f231d8dc23ae41836 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 16:26:36 +0900 Subject: [PATCH 0347/1400] Make osu! touch input aware of the distance travelled of a non-direct touch --- .../TestSceneOsuTouchInput.cs | 28 +++++++++++++++++++ .../UI/OsuTouchInputMapper.cs | 18 ++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index 72bcec6045..bd32d820d1 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -150,6 +150,34 @@ namespace osu.Game.Rulesets.Osu.Tests assertKeyCounter(1, 1); } + [Test] + public void TestPositionalTrackingAfterLongDistanceTravelled() + { + // When a single touch has already travelled enough distance on screen, it should remain as the positional + // tracking touch until released (unless a direct touch occurs). + + beginTouch(TouchSource.Touch1); + + assertKeyCounter(1, 0); + checkPressed(OsuAction.LeftButton); + checkPosition(TouchSource.Touch1); + + // cover some distance + beginTouch(TouchSource.Touch1, new Vector2(0)); + beginTouch(TouchSource.Touch1, new Vector2(9999)); + beginTouch(TouchSource.Touch1, new Vector2(0)); + beginTouch(TouchSource.Touch1, new Vector2(9999)); + beginTouch(TouchSource.Touch1); + + beginTouch(TouchSource.Touch2); + + assertKeyCounter(1, 1); + checkPressed(OsuAction.LeftButton); + checkPressed(OsuAction.RightButton); + // in this case, touch 2 should not become the positional tracking touch. + checkPosition(TouchSource.Touch1); + } + [Test] public void TestPositionalInputUpdatesOnlyFromMostRecentTouch() { diff --git a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs index 8df1c35b5c..76cb388949 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs @@ -97,8 +97,8 @@ namespace osu.Game.Rulesets.Osu.UI return; } - // ..or if the current position tracking touch was not a direct touch (this one is debatable and may be change in the future, but it's the simplest way to handle) - if (!positionTrackingTouch.DirectTouch) + // ..or if the current position tracking touch was not a direct touch (and didn't travel across the screen too far). + if (!positionTrackingTouch.DirectTouch && positionTrackingTouch.DistanceTravelled < 200) { positionTrackingTouch = newTouch; return; @@ -117,6 +117,12 @@ namespace osu.Game.Rulesets.Osu.UI private void handleTouchMovement(TouchEvent touchEvent) { + if (touchEvent is TouchMoveEvent moveEvent) + { + var trackedTouch = trackedTouches.Single(t => t.Source == touchEvent.Touch.Source); + trackedTouch.DistanceTravelled += moveEvent.Delta.Length; + } + // Movement should only be tracked for the most recent touch. if (touchEvent.Touch.Source != positionTrackingTouch?.Source) return; @@ -148,8 +154,16 @@ namespace osu.Game.Rulesets.Osu.UI public OsuAction? Action; + /// + /// Whether the touch was on a hit circle receptor. + /// public readonly bool DirectTouch; + /// + /// The total distance on screen travelled by this touch. + /// + public double DistanceTravelled; + public TrackedTouch(TouchSource source, OsuAction? action, bool directTouch) { Source = source; From 42359a9754d0884b97f3c0ca459f22d8358494b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 16:38:26 +0900 Subject: [PATCH 0348/1400] Fix previous touch action not being released when it's not a direct touch --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index bd32d820d1..d1880d7552 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -172,7 +172,7 @@ namespace osu.Game.Rulesets.Osu.Tests beginTouch(TouchSource.Touch2); assertKeyCounter(1, 1); - checkPressed(OsuAction.LeftButton); + checkNotPressed(OsuAction.LeftButton); checkPressed(OsuAction.RightButton); // in this case, touch 2 should not become the positional tracking touch. checkPosition(TouchSource.Touch1); diff --git a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs index 76cb388949..8cec65f515 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs @@ -105,12 +105,12 @@ namespace osu.Game.Rulesets.Osu.UI } // In the case the new touch was not used for position tracking, we should also check the previous position tracking touch. - // If it was a direct touch and still has its action pressed, that action should be released. + // If it still has its action pressed, that action should be released. // // This is done to allow tracking with the initial touch while still having both Left/Right actions available for alternating with two more touches. - if (positionTrackingTouch.DirectTouch && positionTrackingTouch.Action is OsuAction directTouchAction) + if (positionTrackingTouch.Action is OsuAction touchAction) { - osuInputManager.KeyBindingContainer.TriggerReleased(directTouchAction); + osuInputManager.KeyBindingContainer.TriggerReleased(touchAction); positionTrackingTouch.Action = null; } } From a9c349fa6db682c9c2cdfa961f2821e84bac57d4 Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 15 Mar 2023 09:00:34 +0100 Subject: [PATCH 0349/1400] Cache any skin changes in `SkinReloadableDrawable` to `ScheduledDelegate` --- osu.Game/Skinning/SkinReloadableDrawable.cs | 19 +++++++++++++++++-- osu.Game/Skinning/SkinnableSound.cs | 6 +++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index cef1db4bc0..757ca8de83 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics.Pooling; +using osu.Framework.Threading; namespace osu.Game.Skinning { @@ -14,6 +15,8 @@ namespace osu.Game.Skinning /// public abstract partial class SkinReloadableDrawable : PoolableDrawable { + private ScheduledDelegate? pendingSkinChange; + /// /// Invoked when has changed. /// @@ -31,10 +34,22 @@ namespace osu.Game.Skinning CurrentSkin.SourceChanged += onChange; } - private void onChange() => + private void onChange() + { // schedule required to avoid calls after disposed. // note that this has the side-effect of components only performing a skin change when they are alive. - Scheduler.AddOnce(skinChanged); + pendingSkinChange?.Cancel(); + pendingSkinChange = Scheduler.Add(skinChanged); + } + + public void FlushPendingSkinChanges() + { + if (pendingSkinChange == null) + return; + + pendingSkinChange.RunTask(); + pendingSkinChange = null; + } protected override void LoadAsyncComplete() { diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 43e16f4930..052b1e5b9f 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -115,12 +115,12 @@ namespace osu.Game.Skinning /// public virtual void Play() { - if (Scheduler.HasPendingTasks) - // update samples queued due to skin change before playing them - UpdateSubTree(); + FlushPendingSkinChanges(); samplesContainer.ForEach(c => { + c.FlushPendingSkinChanges(); + if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) { c.Stop(); From b0f1a6952393c6035614d791be6a5a6dd494bbbd Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 15 Mar 2023 09:05:34 +0100 Subject: [PATCH 0350/1400] Update the pauseLoop sample instantly on skin change --- osu.Game/Screens/Play/PauseOverlay.cs | 1 + osu.Game/Screens/Play/Player.cs | 5 +++++ osu.Game/Skinning/SkinReloadableDrawable.cs | 2 +- osu.Game/Skinning/SkinnableSound.cs | 9 +++++++-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index db42998c45..452e170cc6 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -28,6 +28,7 @@ namespace osu.Game.Screens.Play private SkinnableSound pauseLoop; + public void FlushPendingSkinChanges() => pauseLoop.FlushPendingSkinChanges(); protected override Action BackAction => () => InternalButtons.First().TriggerClick(); [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bc453d2151..d4180068d3 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -316,6 +316,11 @@ namespace osu.Game.Screens.Play // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. failAnimationLayer.Add(createOverlayComponents(Beatmap.Value)); + rulesetSkinProvider.SourceChanged += () => + { + PauseOverlay.FlushPendingSkinChanges(); + }; + if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 757ca8de83..ff51eb6dce 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -42,7 +42,7 @@ namespace osu.Game.Skinning pendingSkinChange = Scheduler.Add(skinChanged); } - public void FlushPendingSkinChanges() + public virtual void FlushPendingSkinChanges() { if (pendingSkinChange == null) return; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 052b1e5b9f..f80b1f52fa 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -110,6 +110,13 @@ namespace osu.Game.Skinning } } + public override void FlushPendingSkinChanges() + { + base.FlushPendingSkinChanges(); + + samplesContainer.ForEach(c => c.FlushPendingSkinChanges()); + } + /// /// Plays the samples. /// @@ -119,8 +126,6 @@ namespace osu.Game.Skinning samplesContainer.ForEach(c => { - c.FlushPendingSkinChanges(); - if (PlayWhenZeroVolume || c.AggregateVolume.Value > 0) { c.Stop(); From d87f0557cef3288a72eb0ba9d21610a2433c2124 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 17:18:45 +0900 Subject: [PATCH 0351/1400] Update colours for 3k to not use double-purples --- .../Skinning/Argon/ManiaArgonSkinTransformer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 0beca815b2..ca9cd83a63 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -139,9 +139,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { case 0: return colour_pink; - case 1: return colour_purple; + case 1: return colour_orange; - case 2: return colour_special_column; + case 2: return colour_yellow; default: throw new ArgumentOutOfRangeException(); } From 8908648f97b5397261ffaa8036ec493a96ce36d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 18:01:22 +0900 Subject: [PATCH 0352/1400] Fix super-dodgy cast of `IEnumerable` to `Drawable` --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 42683a3eec..44fa555149 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private Drawable keyCounterFlow => (Drawable)hudOverlay.KeyCounter.Counters; + private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 3eda80719a..dd1b37341f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private Drawable keyCounterFlow => (Drawable)hudOverlay.KeyCounter.Counters; + private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); [Test] public void TestComboCounterIncrementing() From 9e444af380ed0d3e96a17c3f83b3cf35d5a7ae4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 18:02:12 +0900 Subject: [PATCH 0353/1400] Use object initialisers and fix order of initialisation vs add --- .../Play/HUD/DefaultKeyCounterDisplay.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 9499263474..8b910d56f6 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -13,17 +13,18 @@ namespace osu.Game.Screens.Play.HUD private const int duration = 100; private const double key_fade_time = 80; - private readonly FillFlowContainer keyFlow = new FillFlowContainer(); + private readonly FillFlowContainer keyFlow; public override IEnumerable Counters => keyFlow; public DefaultKeyCounterDisplay() { - keyFlow.Direction = FillDirection.Horizontal; - keyFlow.AutoSizeAxes = Axes.Both; - keyFlow.Alpha = 0; - - InternalChild = keyFlow; + InternalChild = keyFlow = new FillFlowContainer + { + Direction = FillDirection.Horizontal, + AutoSizeAxes = Axes.Both, + Alpha = 0, + }; } protected override void Update() @@ -36,13 +37,12 @@ namespace osu.Game.Screens.Play.HUD } public override void AddTrigger(InputTrigger trigger) - { - DefaultKeyCounter key = new DefaultKeyCounter(trigger); - keyFlow.Add(key); - key.FadeTime = key_fade_time; - key.KeyDownTextColor = KeyDownTextColor; - key.KeyUpTextColor = KeyUpTextColor; - } + keyFlow.Add(new DefaultKeyCounter(trigger) + { + FadeTime = key_fade_time, + KeyDownTextColor = KeyDownTextColor, + KeyUpTextColor = KeyUpTextColor, + }); protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. From 5f9b13a77513df7797581eb8f758d0b5fc37f2d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2023 18:02:41 +0900 Subject: [PATCH 0354/1400] Rename `Add`/`AddRange` methods as they are no longer conflicting with `Container` --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 4 ++-- .../Gameplay/TestSceneSkinEditorMultipleSkins.cs | 2 +- .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- osu.Game/Rulesets/UI/RulesetInputManager.cs | 2 +- osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs | 2 +- osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 10 ++++------ 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 44fa555149..7bc789ecc4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -266,7 +266,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); + hudOverlay.KeyCounter.Add(new KeyCounterKeyboardTrigger(Key.Space)); scoreProcessor.Combo.Value = 1; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 6dc07ca9d3..46d5e6c4d2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Gameplay Anchor = Anchor.Centre, }; - kc.AddTriggerRange(new InputTrigger[] + kc.AddRange(new InputTrigger[] { new KeyCounterKeyboardTrigger(Key.X), new KeyCounterKeyboardTrigger(Key.X), @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); - kc.AddTrigger(new KeyCounterKeyboardTrigger(key)); + kc.Add(new KeyCounterKeyboardTrigger(key)); }); Key testKey = ((KeyCounterKeyboardTrigger)kc.Counters.First().Trigger).Key; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index aa7119829a..93fec60de4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); + hudOverlay.KeyCounter.Add(new KeyCounterKeyboardTrigger(Key.Space)); scoreProcessor.Combo.Value = 1; return new Container diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index dd1b37341f..9d8d82108d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual.Gameplay hudOverlay = new HUDOverlay(null, Array.Empty()); // Add any key just to display the key counter visually. - hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space)); + hudOverlay.KeyCounter.Add(new KeyCounterKeyboardTrigger(Key.Space)); action?.Invoke(hudOverlay); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index ea9dc3fb01..ce3ee8cc7a 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.UI KeyBindingContainer.Add(receptor); keyCounter.SetReceptor(receptor); - keyCounter.AddTriggerRange(KeyBindingContainer.DefaultKeyBindings + keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings .Select(b => b.GetAction()) .Distinct() .OrderBy(action => action) diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 8b910d56f6..14d7f56093 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Play.HUD Size = keyFlow.Size; } - public override void AddTrigger(InputTrigger trigger) + public override void Add(InputTrigger trigger) => keyFlow.Add(new DefaultKeyCounter(trigger) { FadeTime = key_fade_time, diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 0e0f8a1190..49c0da6793 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -51,16 +51,14 @@ namespace osu.Game.Screens.Play.HUD } /// - /// Adds a new to this . + /// Add a to this display. /// - /// The the resulting will react to. - public abstract void AddTrigger(InputTrigger trigger); + public abstract void Add(InputTrigger trigger); /// - /// Adds a range of new s to this . + /// Add a range of to this display. /// - /// The s the resulting s will react to. - public void AddTriggerRange(IEnumerable triggers) => triggers.ForEach(AddTrigger); + public void AddRange(IEnumerable triggers) => triggers.ForEach(Add); [BackgroundDependencyLoader] private void load(OsuConfigManager config) From edc63146344a81f6ff3c993d11690e99579dbd6b Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 15 Mar 2023 10:49:59 +0100 Subject: [PATCH 0355/1400] Drank some coffee and figured out the fix --- osu.Game/Screens/Play/PauseOverlay.cs | 1 - osu.Game/Screens/Play/Player.cs | 5 ----- osu.Game/Skinning/PoolableSkinnableSample.cs | 2 ++ osu.Game/Skinning/SkinReloadableDrawable.cs | 20 +++++++++++--------- osu.Game/Skinning/SkinnableSound.cs | 7 ------- 5 files changed, 13 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 452e170cc6..db42998c45 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -28,7 +28,6 @@ namespace osu.Game.Screens.Play private SkinnableSound pauseLoop; - public void FlushPendingSkinChanges() => pauseLoop.FlushPendingSkinChanges(); protected override Action BackAction => () => InternalButtons.First().TriggerClick(); [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d4180068d3..bc453d2151 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -316,11 +316,6 @@ namespace osu.Game.Screens.Play // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. failAnimationLayer.Add(createOverlayComponents(Beatmap.Value)); - rulesetSkinProvider.SourceChanged += () => - { - PauseOverlay.FlushPendingSkinChanges(); - }; - if (!DrawableRuleset.AllowGameplayOverlays) { HUDOverlay.ShowHud.Value = false; diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index 0158c47ea3..c8b0955db2 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -132,6 +132,8 @@ namespace osu.Game.Skinning if (Sample == null) return; + FlushPendingSkinChanges(); + activeChannel = Sample.GetChannel(); activeChannel.Looping = Looping; activeChannel.Play(); diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index ff51eb6dce..b6b9650048 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -27,6 +27,15 @@ namespace osu.Game.Skinning /// protected ISkinSource CurrentSkin { get; private set; } = null!; + protected void FlushPendingSkinChanges() + { + if (pendingSkinChange == null) + return; + + pendingSkinChange.RunTask(); + pendingSkinChange = null; + } + [BackgroundDependencyLoader] private void load(ISkinSource source) { @@ -42,15 +51,6 @@ namespace osu.Game.Skinning pendingSkinChange = Scheduler.Add(skinChanged); } - public virtual void FlushPendingSkinChanges() - { - if (pendingSkinChange == null) - return; - - pendingSkinChange.RunTask(); - pendingSkinChange = null; - } - protected override void LoadAsyncComplete() { base.LoadAsyncComplete(); @@ -61,6 +61,8 @@ namespace osu.Game.Skinning { SkinChanged(CurrentSkin); OnSkinChanged?.Invoke(); + + pendingSkinChange = null; } /// diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index f80b1f52fa..59b3799e0a 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -110,13 +110,6 @@ namespace osu.Game.Skinning } } - public override void FlushPendingSkinChanges() - { - base.FlushPendingSkinChanges(); - - samplesContainer.ForEach(c => c.FlushPendingSkinChanges()); - } - /// /// Plays the samples. /// From 89b42ddd98f239ca605bf68311b4bc75a42babdc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 15:02:38 +0900 Subject: [PATCH 0356/1400] Don't localise beatmap count string for now --- osu.Game/Localisation/SongSelectStrings.cs | 5 ----- osu.Game/Screens/Select/SongSelect.cs | 11 +++++++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/SongSelectStrings.cs b/osu.Game/Localisation/SongSelectStrings.cs index 046aec6bcf..e1ac328420 100644 --- a/osu.Game/Localisation/SongSelectStrings.cs +++ b/osu.Game/Localisation/SongSelectStrings.cs @@ -19,11 +19,6 @@ namespace osu.Game.Localisation /// public static LocalisableString LocallyModifiedTooltip => new TranslatableString(getKey(@"locally_modified_tooltip"), @"Has been locally modified"); - /// - /// "{0} beatmaps displayed" - /// - public static LocalisableString BeatmapsDisplayed(int arg0) => new TranslatableString(getKey(@"beatmaps_displayed"), @"{0:#,0} beatmaps displayed", arg0); - private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 9f8c3f1a2c..a3521337ee 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -40,7 +40,6 @@ using osu.Game.Skinning; using osuTK; using osuTK.Graphics; using osuTK.Input; -using osu.Game.Localisation; namespace osu.Game.Screens.Select { @@ -163,7 +162,15 @@ namespace osu.Game.Screens.Select BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, - FilterApplied = () => FilterControl.InformationalText = SongSelectStrings.BeatmapsDisplayed(Carousel.CountDisplayed), + FilterApplied = () => + { + FilterControl.InformationalText = + Carousel.CountDisplayed == 1 + // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 + // but also in this case we want support for formatting a number within a string). + ? $"{Carousel.CountDisplayed:#,0} beatmap displayed" + : $"{Carousel.CountDisplayed:#,0} beatmaps displayed"; + }, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); From 5378cdff20845d4bfa6cea7cea9f02cdf09b8345 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 15:10:35 +0900 Subject: [PATCH 0357/1400] Apply NRT to `TestSceneSkinnableSound` --- .../Gameplay/TestSceneSkinnableSound.cs | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 5c69062e67..40bfe975bc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -22,8 +20,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneSkinnableSound : OsuTestScene { - private TestSkinSourceContainer skinSource; - private PausableSkinnableSound skinnableSound; + private TestSkinSourceContainer skinSource = null!; + private PausableSkinnableSound skinnableSound = null!; [SetUpSteps] public void SetUpSteps() @@ -102,7 +100,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestSkinChangeDoesntPlayOnPause() { - DrawableSample sample = null; + DrawableSample? sample = null; AddStep("start sample", () => { skinnableSound.Play(); @@ -118,7 +116,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("retrieve and ensure current sample is different", () => { - DrawableSample oldSample = sample; + DrawableSample? oldSample = sample; sample = skinnableSound.ChildrenOfType().Single(); return sample != oldSample; }); @@ -134,20 +132,27 @@ namespace osu.Game.Tests.Visual.Gameplay private partial class TestSkinSourceContainer : Container, ISkinSource, ISamplePlaybackDisabler { [Resolved] - private ISkinSource source { get; set; } + private ISkinSource source { get; set; } = null!; - public event Action SourceChanged; + public event Action? SourceChanged; public Bindable SamplePlaybackDisabled { get; } = new Bindable(); IBindable ISamplePlaybackDisabler.SamplePlaybackDisabled => SamplePlaybackDisabled; - public Drawable GetDrawableComponent(ISkinComponentLookup lookup) => source?.GetDrawableComponent(lookup); - public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source?.GetTexture(componentName, wrapModeS, wrapModeT); - public ISample GetSample(ISampleInfo sampleInfo) => source?.GetSample(sampleInfo); - public IBindable GetConfig(TLookup lookup) => source?.GetConfig(lookup); - public ISkin FindProvider(Func lookupFunction) => lookupFunction(this) ? this : source?.FindProvider(lookupFunction); - public IEnumerable AllSources => new[] { this }.Concat(source?.AllSources ?? Enumerable.Empty()); + public Drawable? GetDrawableComponent(ISkinComponentLookup lookup) => source.GetDrawableComponent(lookup); + public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source.GetTexture(componentName, wrapModeS, wrapModeT); + public ISample? GetSample(ISampleInfo sampleInfo) => source.GetSample(sampleInfo); + + public IBindable? GetConfig(TLookup lookup) + where TLookup : notnull + where TValue : notnull + { + return source.GetConfig(lookup); + } + + public ISkin? FindProvider(Func lookupFunction) => lookupFunction(this) ? this : source.FindProvider(lookupFunction); + public IEnumerable AllSources => new[] { this }.Concat(source.AllSources); public void TriggerSourceChanged() { From 297e7d654239ecc02b6516cf80fafb2a34c23afa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 15:33:30 +0900 Subject: [PATCH 0358/1400] Fix `Flush` call being run too late in `PoolableSkinnableSample` --- osu.Game/Skinning/PoolableSkinnableSample.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index c8b0955db2..361c8688e7 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -129,11 +129,11 @@ namespace osu.Game.Skinning /// public void Play() { + FlushPendingSkinChanges(); + if (Sample == null) return; - FlushPendingSkinChanges(); - activeChannel = Sample.GetChannel(); activeChannel.Looping = Looping; activeChannel.Play(); From 159c8833c7e2506feed18ba05d1ec51df3a54860 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 15:41:05 +0900 Subject: [PATCH 0359/1400] Add test coverage of `SkinnableSound` not updating in time when not present --- .../Gameplay/TestSceneSkinnableSound.cs | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index 40bfe975bc..cc82ffed2b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -23,6 +23,8 @@ namespace osu.Game.Tests.Visual.Gameplay private TestSkinSourceContainer skinSource = null!; private PausableSkinnableSound skinnableSound = null!; + private const string sample_lookup = "Gameplay/normal-sliderslide"; + [SetUpSteps] public void SetUpSteps() { @@ -34,7 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; // has to be added after the hierarchy above else the `ISkinSource` dependency won't be cached. - skinSource.Add(skinnableSound = new PausableSkinnableSound(new SampleInfo("Gameplay/normal-sliderslide"))); + skinSource.Add(skinnableSound = new PausableSkinnableSound(new SampleInfo(sample_lookup))); }); } @@ -97,6 +99,27 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("sample not playing", () => !skinnableSound.IsPlaying); } + [Test] + public void TestSampleUpdatedBeforePlaybackWhenNotPresent() + { + AddStep("make sample non-present", () => skinnableSound.Hide()); + AddUntilStep("ensure not present", () => skinnableSound.IsPresent, () => Is.False); + + AddUntilStep("ensure sample loaded", () => skinnableSound.ChildrenOfType().Single().Name, () => Is.EqualTo(sample_lookup)); + + AddStep("Change source", () => + { + skinSource.OverridingSample = new SampleVirtual("new skin"); + skinSource.TriggerSourceChanged(); + }); + + // Samples are nulled on source change immediately + AddUntilStep("wait for sample null", () => skinnableSound.ChildrenOfType().Count(), () => Is.Zero); + + AddStep("start sample", () => skinnableSound.Play()); + AddUntilStep("sample updated", () => skinnableSound.ChildrenOfType().Single().Name, () => Is.EqualTo("new skin")); + } + [Test] public void TestSkinChangeDoesntPlayOnPause() { @@ -138,11 +161,13 @@ namespace osu.Game.Tests.Visual.Gameplay public Bindable SamplePlaybackDisabled { get; } = new Bindable(); + public ISample? OverridingSample; + IBindable ISamplePlaybackDisabler.SamplePlaybackDisabled => SamplePlaybackDisabled; public Drawable? GetDrawableComponent(ISkinComponentLookup lookup) => source.GetDrawableComponent(lookup); public Texture? GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => source.GetTexture(componentName, wrapModeS, wrapModeT); - public ISample? GetSample(ISampleInfo sampleInfo) => source.GetSample(sampleInfo); + public ISample? GetSample(ISampleInfo sampleInfo) => OverridingSample ?? source.GetSample(sampleInfo); public IBindable? GetConfig(TLookup lookup) where TLookup : notnull From 8e6a4559e3ae8c9892866cf9cf8d4e8d1b72afd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 15:58:42 +0900 Subject: [PATCH 0360/1400] Add xmldoc for new method and reorder methods in `SkinReloadableDrawable` --- osu.Game/Skinning/SkinReloadableDrawable.cs | 47 +++++++++++++-------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index b6b9650048..c7b33dc539 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -27,6 +27,30 @@ namespace osu.Game.Skinning /// protected ISkinSource CurrentSkin { get; private set; } = null!; + [BackgroundDependencyLoader] + private void load(ISkinSource source) + { + CurrentSkin = source; + CurrentSkin.SourceChanged += onChange; + } + + protected override void LoadAsyncComplete() + { + base.LoadAsyncComplete(); + skinChanged(); + } + + /// + /// Force any pending calls to be performed immediately. + /// + /// + /// When a skin change occurs, the handling provided by this class is scheduled. + /// In some cases, such a sample playback, this can result in the sample being played + /// just before it is updated to a potentially different sample. + /// + /// Calling this method will ensure any pending update operations are run immediately. + /// It is recommended to call this before consuming the result of skin changes for anything non-drawable. + /// protected void FlushPendingSkinChanges() { if (pendingSkinChange == null) @@ -36,11 +60,12 @@ namespace osu.Game.Skinning pendingSkinChange = null; } - [BackgroundDependencyLoader] - private void load(ISkinSource source) + /// + /// Called when a change is made to the skin. + /// + /// The new skin. + protected virtual void SkinChanged(ISkinSource skin) { - CurrentSkin = source; - CurrentSkin.SourceChanged += onChange; } private void onChange() @@ -51,12 +76,6 @@ namespace osu.Game.Skinning pendingSkinChange = Scheduler.Add(skinChanged); } - protected override void LoadAsyncComplete() - { - base.LoadAsyncComplete(); - skinChanged(); - } - private void skinChanged() { SkinChanged(CurrentSkin); @@ -65,14 +84,6 @@ namespace osu.Game.Skinning pendingSkinChange = null; } - /// - /// Called when a change is made to the skin. - /// - /// The new skin. - protected virtual void SkinChanged(ISkinSource skin) - { - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From cd102da3af06d06486ea20daa319f143ab13632c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 16:34:31 +0900 Subject: [PATCH 0361/1400] Move matches string inside text box --- osu.Game/Screens/Select/FilterControl.cs | 50 +++++++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 4 +- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b5469abffe..1bcc042f72 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -38,8 +38,8 @@ namespace osu.Game.Screens.Select public LocalisableString InformationalText { - get => filterText.Text; - set => filterText.Text = value; + get => searchTextBox.FilterText.Text; + set => searchTextBox.FilterText.Text = value; } private OsuTabControl sortTabs; @@ -48,12 +48,10 @@ namespace osu.Game.Screens.Select private Bindable groupMode; - private SeekLimitedSearchTextBox searchTextBox; + private FilterControlTextBox searchTextBox; private CollectionDropdown collectionDropdown; - private OsuSpriteText filterText; - public FilterCriteria CreateCriteria() { string query = searchTextBox.Text; @@ -111,22 +109,9 @@ namespace osu.Game.Screens.Select Spacing = new Vector2(0, 5), Children = new Drawable[] { - searchTextBox = new SeekLimitedSearchTextBox { RelativeSizeAxes = Axes.X }, - new Container + searchTextBox = new FilterControlTextBox { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - AutoSizeDuration = 200, - AutoSizeEasing = Easing.OutQuint, - Children = new Drawable[] - { - filterText = new OsuSpriteText - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Font = OsuFont.Default.With(size: 12), - }, - } }, new Box { @@ -262,5 +247,32 @@ namespace osu.Game.Screens.Select protected override bool OnClick(ClickEvent e) => true; protected override bool OnHover(HoverEvent e) => true; + + private partial class FilterControlTextBox : SeekLimitedSearchTextBox + { + private const float filter_text_size = 12; + + public OsuSpriteText FilterText; + + public FilterControlTextBox() + { + Height += filter_text_size; + TextContainer.Margin = new MarginPadding { Bottom = filter_text_size }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + TextContainer.Add(FilterText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.TopLeft, + Depth = float.MinValue, + Font = OsuFont.Default.With(size: filter_text_size, weight: FontWeight.SemiBold), + Margin = new MarginPadding { Top = 2, Left = 2 }, + Colour = colours.Yellow + }); + } + } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index a3521337ee..722119f82e 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -168,8 +168,8 @@ namespace osu.Game.Screens.Select Carousel.CountDisplayed == 1 // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // but also in this case we want support for formatting a number within a string). - ? $"{Carousel.CountDisplayed:#,0} beatmap displayed" - : $"{Carousel.CountDisplayed:#,0} beatmaps displayed"; + ? $"{Carousel.CountDisplayed:#,0} matching beatmap" + : $"{Carousel.CountDisplayed:#,0} matching beatmaps"; }, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); From a81408ca0626edc77c36060d0bf574dd1a47cdd5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 17:12:46 +0900 Subject: [PATCH 0362/1400] Add failing test coverage showing that replay will fail on exiting gameplay --- .../Visual/Gameplay/TestSceneReplayPlayer.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs index 3e415af86e..ae10207de0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayPlayer.cs @@ -8,6 +8,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; +using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Tests.Beatmaps; using osuTK.Input; @@ -45,6 +46,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Time still stopped", () => lastTime == Player.GameplayClockContainer.CurrentTime); } + [Test] + public void TestDoesNotFailOnExit() + { + loadPlayerWithBeatmap(); + + AddUntilStep("wait for first hit", () => Player.ScoreProcessor.TotalScore.Value > 0); + AddAssert("ensure rank is not fail", () => Player.ScoreProcessor.Rank.Value, () => Is.Not.EqualTo(ScoreRank.F)); + AddStep("exit player", () => Player.Exit()); + AddUntilStep("wait for exit", () => Player.Parent == null); + AddAssert("ensure rank is not fail", () => Player.ScoreProcessor.Rank.Value, () => Is.Not.EqualTo(ScoreRank.F)); + } + [Test] public void TestPauseViaSpaceWithSkip() { From 3b62f87b64f966bd277323d9afc7e256e1dea5e0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 17:14:20 +0900 Subject: [PATCH 0363/1400] Ensure `Player` does not fail a score on exit if a replay is currently loaded --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index bc453d2151..8d0da8c44f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1111,7 +1111,7 @@ namespace osu.Game.Screens.Play GameplayState.HasQuit = true; // if arriving here and the results screen preparation task hasn't run, it's safe to say the user has not completed the beatmap. - if (prepareScoreForDisplayTask == null) + if (prepareScoreForDisplayTask == null && DrawableRuleset.ReplayScore == null) ScoreProcessor.FailScore(Score.ScoreInfo); } From 42bcc8bafc01005ad91035dde8d80d027b3552f5 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 16 Mar 2023 19:15:50 +0900 Subject: [PATCH 0364/1400] revert mod store --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ++++-------- osu.Game/Overlays/Mods/ModPresetTooltip.cs | 13 ++++++------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 49437c5bb1..d01981d18c 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -18,12 +18,10 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip>, IHasContextMenu, IHasPopover + public partial class ModPresetPanel : ModSelectPanel, IHasCustomTooltip, IHasContextMenu, IHasPopover { public readonly Live Preset; - public readonly Bindable> Mods = new Bindable>(); - public override BindableBool Active { get; } = new BindableBool(); [Resolved] @@ -37,7 +35,6 @@ namespace osu.Game.Overlays.Mods public ModPresetPanel(Live preset) { Preset = preset; - Mods.Value = preset.Value.Mods.ToList(); Title = preset.Value.Name; Description = preset.Value.Description; @@ -54,7 +51,6 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); selectedMods.BindValueChanged(_ => selectedModsChanged(), true); - Mods.BindValueChanged(_ => updateActiveState(), true); } protected override void Select() @@ -82,13 +78,13 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - Active.Value = new HashSet(Mods.Value).SetEquals(selectedMods.Value); + Active.Value = new HashSet(Preset.Value.Mods).SetEquals(selectedMods.Value); } #region IHasCustomTooltip - public List TooltipContent => Mods.Value; - public ITooltip> GetCustomTooltip() => new ModPresetTooltip(ColourProvider); + public ModPreset TooltipContent => Preset.Value; + public ITooltip GetCustomTooltip() => new ModPresetTooltip(ColourProvider); #endregion diff --git a/osu.Game/Overlays/Mods/ModPresetTooltip.cs b/osu.Game/Overlays/Mods/ModPresetTooltip.cs index 0b31a97064..8e8259de45 100644 --- a/osu.Game/Overlays/Mods/ModPresetTooltip.cs +++ b/osu.Game/Overlays/Mods/ModPresetTooltip.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +11,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPresetTooltip : VisibilityContainer, ITooltip> + public partial class ModPresetTooltip : VisibilityContainer, ITooltip { protected override Container Content { get; } @@ -43,15 +42,15 @@ namespace osu.Game.Overlays.Mods }; } - private List? lastPreset; + private ModPreset? lastPreset; - public void SetContent(List mods) + public void SetContent(ModPreset preset) { - if (ReferenceEquals(mods, lastPreset)) + if (ReferenceEquals(preset, lastPreset)) return; - lastPreset = mods; - Content.ChildrenEnumerable = mods.Select(mod => new ModPresetRow(mod)); + lastPreset = preset; + Content.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } protected override void PopIn() => this.FadeIn(transition_duration, Easing.OutQuint); From cb9b14b30fd8c3620d5b45aadb9152a9b29f3617 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Mar 2023 19:48:36 +0900 Subject: [PATCH 0365/1400] Revert "Merge pull request #22741 from cdwcgt/do-not-fetch-deletePending" This reverts commit 15c44a281725189671c29fb569949f7c8be66cbe, reversing changes made to de2ab05e785dfaf2fb108c68c4c7424c8db417a5. --- osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs index 8ee2cc6241..8908163646 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreDecoder.cs @@ -24,6 +24,6 @@ namespace osu.Game.Scoring.Legacy } protected override Ruleset GetRuleset(int rulesetId) => rulesets.GetRuleset(rulesetId)?.CreateInstance(); - protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash && !b.BeatmapSet.DeletePending)); + protected override WorkingBeatmap GetBeatmap(string md5Hash) => beatmaps.GetWorkingBeatmap(beatmaps.QueryBeatmap(b => b.MD5Hash == md5Hash)); } } From d025c441ca2249489b6d0c523d55b44ef1da6108 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 16 Mar 2023 19:38:52 +0900 Subject: [PATCH 0366/1400] delay mod save after click save or not popover hidden --- .../UserInterface/TestSceneModPresetColumn.cs | 20 ++++++----- osu.Game/Overlays/Mods/EditPresetPopover.cs | 36 ++++++++++--------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 68efb2a5f4..c4c5584c5e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -319,6 +319,7 @@ namespace osu.Game.Tests.Visual.UserInterface { ModPresetColumn modPresetColumn = null!; var mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() }; + List previousMod = null!; AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn @@ -332,6 +333,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("right click first panel", () => { var panel = this.ChildrenOfType().First(); + previousMod = panel.Preset.Value.Mods.ToList(); InputManager.MoveMouseTo(panel); InputManager.Click(MouseButton.Right); }); @@ -350,10 +352,14 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); + AddStep("attempt preset edit", () => + { + InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); + InputManager.Click(MouseButton.Left); + }); AddWaitStep("wait some", 3); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); AddAssert("present mod not changed", () => - !new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); + new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); AddStep("right click first panel", () => @@ -377,17 +383,13 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(0)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddUntilStep("popover not closed", () => this.ChildrenOfType().Any()); - AddAssert("present mod is changed", () => - new HashSet(this.ChildrenOfType().First().Mods.Value).SetEquals(mods)); - - AddStep("click edit", () => + AddStep("attempt preset edit", () => { InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddAssert("present mod in realm is changed", () => + AddWaitStep("wait some", 3); + AddAssert("present mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 92860e96a6..0e21260493 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.Mods private void trySaveCurrentMod() { - if (!button.CheckCurrentModCanBeSave()) + if (!checkCanBeSave()) { Body.Shake(); return; @@ -139,13 +139,12 @@ namespace osu.Game.Overlays.Mods saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); - button.Mods.Value = saveModAfterClosed; updateActiveState(); } private void updateActiveState() { - if (button.CheckCurrentModCanBeSave()) + if (checkCanBeSave()) { useCurrentModButton.DarkerColour = colours.Blue1; useCurrentModButton.LighterColour = colours.Blue0; @@ -159,6 +158,19 @@ namespace osu.Game.Overlays.Mods } } + private bool checkCanBeSave() + { + if (!selectedMods.Value.Any()) + return false; + + if (saveModAfterClosed.Any()) + { + return !new HashSet(saveModAfterClosed).SetEquals(selectedMods.Value); + } + + return button.CheckCurrentModCanBeSave(); + } + protected override void LoadComplete() { base.LoadComplete(); @@ -178,22 +190,14 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; + + if (saveModAfterClosed.Any()) + { + s.Mods = saveModAfterClosed; + } }); this.HidePopover(); } - - protected override void UpdateState(ValueChangedEvent state) - { - base.UpdateState(state); - - if (state.NewValue == Visibility.Hidden && saveModAfterClosed.Any()) - { - button.Preset.PerformWrite(s => - { - s.Mods = saveModAfterClosed; - }); - } - } } } From 678e8ed736b4b89617988300888997fab85d4373 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 16 Mar 2023 14:06:35 +0300 Subject: [PATCH 0367/1400] Update UBO usages inline with framework changes --- osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs | 5 +++-- .../Visual/Background/TestSceneTriangleBorderShader.cs | 8 ++++---- osu.Game/Graphics/Backgrounds/Triangles.cs | 2 +- osu.Game/Graphics/Backgrounds/TrianglesV2.cs | 2 +- osu.Game/Graphics/Sprites/LogoAnimation.cs | 8 ++++---- osu.Game/Rulesets/Mods/ModFlashlight.cs | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs index a824f202ec..9d64c354e2 100644 --- a/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs +++ b/osu.Game.Rulesets.Osu/Skinning/SmokeSegment.cs @@ -252,13 +252,14 @@ namespace osu.Game.Rulesets.Osu.Skinning renderer.SetBlend(BlendingParameters.Additive); renderer.PushLocalMatrix(DrawInfo.Matrix); - TextureShader.Bind(); + BindTextureShader(renderer); + texture.Bind(); for (int i = 0; i < points.Count; i++) drawPointQuad(points[i], textureRect, i + firstVisiblePointIndex); - TextureShader.Unbind(); + UnbindTextureShader(renderer); renderer.PopLocalMatrix(); } diff --git a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs index 07427c242f..711d9ab5ea 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneTriangleBorderShader.cs @@ -100,8 +100,10 @@ namespace osu.Game.Tests.Visual.Background private IUniformBuffer? borderDataBuffer; - public override void Draw(IRenderer renderer) + protected override void BindUniformResources(IShader shader, IRenderer renderer) { + base.BindUniformResources(shader, renderer); + borderDataBuffer ??= renderer.CreateUniformBuffer(); borderDataBuffer.Data = borderDataBuffer.Data with { @@ -109,9 +111,7 @@ namespace osu.Game.Tests.Visual.Background TexelSize = texelSize }; - TextureShader.BindUniformBlock("m_BorderData", borderDataBuffer); - - base.Draw(renderer); + shader.BindUniformBlock("m_BorderData", borderDataBuffer); } protected override bool CanDrawOpaqueInterior => false; diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 28a715ca0b..0ee42c69d5 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -306,7 +306,7 @@ namespace osu.Game.Graphics.Backgrounds }; shader.Bind(); - shader.BindUniformBlock("m_BorderData", borderDataBuffer); + shader.BindUniformBlock(@"m_BorderData", borderDataBuffer); foreach (TriangleParticle particle in parts) { diff --git a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs index 6a34fefa3a..750e96440d 100644 --- a/osu.Game/Graphics/Backgrounds/TrianglesV2.cs +++ b/osu.Game/Graphics/Backgrounds/TrianglesV2.cs @@ -249,7 +249,7 @@ namespace osu.Game.Graphics.Backgrounds }; shader.Bind(); - shader.BindUniformBlock("m_BorderData", borderDataBuffer); + shader.BindUniformBlock(@"m_BorderData", borderDataBuffer); Vector2 relativeSize = Vector2.Divide(triangleSize, size); diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 220f57e9fa..eb7613a1b2 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -59,14 +59,14 @@ namespace osu.Game.Graphics.Sprites private IUniformBuffer animationDataBuffer; - protected override void Blit(IRenderer renderer) + protected override void BindUniformResources(IShader shader, IRenderer renderer) { + base.BindUniformResources(shader, renderer); + animationDataBuffer ??= renderer.CreateUniformBuffer(); animationDataBuffer.Data = animationDataBuffer.Data with { Progress = progress }; - TextureShader.BindUniformBlock("m_AnimationData", animationDataBuffer); - - base.Blit(renderer); + shader.BindUniformBlock(@"m_AnimationData", animationDataBuffer); } protected override bool CanDrawOpaqueInterior => false; diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index a7889cb98d..f8c3a730f2 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -273,7 +273,7 @@ namespace osu.Game.Rulesets.Mods }; shader.Bind(); - shader.BindUniformBlock("m_FlashlightParameters", flashlightParametersBuffer); + shader.BindUniformBlock(@"m_FlashlightParameters", flashlightParametersBuffer); renderer.DrawQuad(renderer.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: addAction); From 1c3b60b9e6c6d31a2d955fcf0dafe41b20774abf Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 16 Mar 2023 23:56:41 +0900 Subject: [PATCH 0368/1400] Use custom vertex shader for logo animation --- osu.Game/Graphics/Sprites/LogoAnimation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 220f57e9fa..619a28ecad 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.Sprites [BackgroundDependencyLoader] private void load(ShaderManager shaders) { - TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, @"LogoAnimation"); + TextureShader = shaders.Load(@"LogoAnimation", @"LogoAnimation"); } private float animationProgress; From 8bdb89d05dbc779fda0a6b9f924b6e07eca2b63c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Mar 2023 19:12:43 +0900 Subject: [PATCH 0369/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c08dc9ed8f..ce9cf37ec3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From bcd24873d6361992339ca2ef5e1fdd6053419c33 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 17 Mar 2023 20:37:05 +0900 Subject: [PATCH 0370/1400] Use custom vertex type --- osu.Game/Graphics/Sprites/LogoAnimation.cs | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 619a28ecad..3b8b0bfc88 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -3,13 +3,18 @@ #nullable disable +using System; using System.Runtime.InteropServices; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Rendering; +using osu.Framework.Graphics.Rendering.Vertices; using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Shaders.Types; using osu.Framework.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; +using osuTK.Graphics.ES30; namespace osu.Game.Graphics.Sprites { @@ -43,11 +48,22 @@ namespace osu.Game.Graphics.Sprites { private LogoAnimation source => (LogoAnimation)Source; + private readonly Action addVertexAction; + private float progress; public LogoAnimationDrawNode(LogoAnimation source) : base(source) { + addVertexAction = v => + { + animationVertexBatch!.Add(new LogoAnimationVertex + { + Position = v.Position, + Colour = v.Colour, + TexturePosition = v.TexturePosition, + }); + }; } public override void ApplyState() @@ -58,10 +74,13 @@ namespace osu.Game.Graphics.Sprites } private IUniformBuffer animationDataBuffer; + private IVertexBatch animationVertexBatch; protected override void Blit(IRenderer renderer) { animationDataBuffer ??= renderer.CreateUniformBuffer(); + animationVertexBatch ??= renderer.CreateQuadBatch(1, 2); + animationDataBuffer.Data = animationDataBuffer.Data with { Progress = progress }; TextureShader.BindUniformBlock("m_AnimationData", animationDataBuffer); @@ -83,6 +102,24 @@ namespace osu.Game.Graphics.Sprites public UniformFloat Progress; private readonly UniformPadding12 pad1; } + + [StructLayout(LayoutKind.Sequential)] + private struct LogoAnimationVertex : IEquatable, IVertex + { + [VertexMember(2, VertexAttribPointerType.Float)] + public Vector2 Position; + + [VertexMember(4, VertexAttribPointerType.Float)] + public Color4 Colour; + + [VertexMember(2, VertexAttribPointerType.Float)] + public Vector2 TexturePosition; + + public readonly bool Equals(LogoAnimationVertex other) => + Position.Equals(other.Position) + && TexturePosition.Equals(other.TexturePosition) + && Colour.Equals(other.Colour); + } } } } From c08513d59049e78c8151a2b2fbaaa4df1921ccef Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 17 Mar 2023 20:47:11 +0900 Subject: [PATCH 0371/1400] Actually use custom vertex action --- osu.Game/Graphics/Sprites/LogoAnimation.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Sprites/LogoAnimation.cs b/osu.Game/Graphics/Sprites/LogoAnimation.cs index 3b8b0bfc88..fbf8717d3c 100644 --- a/osu.Game/Graphics/Sprites/LogoAnimation.cs +++ b/osu.Game/Graphics/Sprites/LogoAnimation.cs @@ -78,6 +78,9 @@ namespace osu.Game.Graphics.Sprites protected override void Blit(IRenderer renderer) { + if (DrawRectangle.Width == 0 || DrawRectangle.Height == 0) + return; + animationDataBuffer ??= renderer.CreateUniformBuffer(); animationVertexBatch ??= renderer.CreateQuadBatch(1, 2); @@ -85,7 +88,13 @@ namespace osu.Game.Graphics.Sprites TextureShader.BindUniformBlock("m_AnimationData", animationDataBuffer); - base.Blit(renderer); + renderer.DrawQuad( + Texture, + ScreenSpaceDrawQuad, + DrawColourInfo.Colour, + inflationPercentage: new Vector2(InflationAmount.X / DrawRectangle.Width, InflationAmount.Y / DrawRectangle.Height), + textureCoords: TextureCoords, + vertexAction: addVertexAction); } protected override bool CanDrawOpaqueInterior => false; From 970df5d88a09d6d55797739164ce20cb08b9aed4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 12 Mar 2023 18:46:34 -0700 Subject: [PATCH 0372/1400] Update profile kudosu section in line with web --- .../Profile/Sections/Kudosu/KudosuInfo.cs | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index d2f01ef9f7..7b26640e50 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -2,15 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Game.Resources.Localisation.Web; using osu.Framework.Localisation; @@ -52,7 +49,6 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { private readonly OsuSpriteText valueText; protected readonly LinkFlowContainer DescriptionText; - private readonly Box lineBackground; public new int Count { @@ -63,25 +59,14 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Top = 10, Bottom = 20 }; + Padding = new MarginPadding { Bottom = 20 }; Child = new FillFlowContainer { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), Children = new Drawable[] { - new CircularContainer - { - Masking = true, - RelativeSizeAxes = Axes.X, - Height = 2, - Child = lineBackground = new Box - { - RelativeSizeAxes = Axes.Both, - } - }, new OsuSpriteText { Text = header, @@ -91,7 +76,6 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { Text = "0", Font = OsuFont.GetFont(size: 40, weight: FontWeight.Light), - UseFullGlyphHeight = false, }, DescriptionText = new LinkFlowContainer(t => t.Font = t.Font.With(size: 14)) { @@ -101,12 +85,6 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } }; } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) - { - lineBackground.Colour = colourProvider.Highlight1; - } } } } From 48b6e214af56fab60571964a91474c5f8d3ce296 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sun, 19 Mar 2023 17:12:12 +0100 Subject: [PATCH 0373/1400] Fix URL handling on macOS --- osu.Desktop/OsuGameDesktop.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index b3f6370ccb..3fe251cb00 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -139,7 +139,17 @@ namespace osu.Desktop desktopWindow.CursorState |= CursorState.Hidden; desktopWindow.Title = Name; - desktopWindow.DragDrop += f => fileDrop(new[] { f }); + desktopWindow.DragDrop += f => + { + // on macOS, URL associations are handled via SDL_DROPFILE events. + if (f.StartsWith(OSU_PROTOCOL, StringComparison.Ordinal)) + { + HandleLink(f); + return; + } + + fileDrop(new[] { f }); + }; } protected override BatteryInfo CreateBatteryInfo() => new SDL2BatteryInfo(); From b254dbd7ca409e502b9d041f9c0c623ea3afd841 Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sun, 19 Mar 2023 17:37:49 +0100 Subject: [PATCH 0374/1400] Remove arbitrary extension limitation from drag and drop imports `OsuGameBase` already properly handles multiple extensions in the same import. --- osu.Desktop/OsuGameDesktop.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index b3f6370ccb..6b5c5b809b 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -151,10 +151,6 @@ namespace osu.Desktop { lock (importableFiles) { - string firstExtension = Path.GetExtension(filePaths.First()); - - if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return; - importableFiles.AddRange(filePaths); Logger.Log($"Adding {filePaths.Length} files for import"); From 11f52d5bf4440d5012dbaff2167e921d7f2fd49c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Mar 2023 14:01:35 +0900 Subject: [PATCH 0375/1400] Remove unused using statement --- osu.Desktop/OsuGameDesktop.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 6b5c5b809b..f094785a5b 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Threading.Tasks; From 8557589a3542c7bc26969c9c8cbdac5f3a418ec5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Mar 2023 15:28:13 +0900 Subject: [PATCH 0376/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ce9cf37ec3..54d6533713 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 13a32b5246442bed162b1b4cefc873aa48750c78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Mar 2023 15:36:27 +0900 Subject: [PATCH 0377/1400] Move lock-in variable to `const` and document better --- osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs index 8cec65f515..4270a4df58 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs @@ -22,6 +22,13 @@ namespace osu.Game.Rulesets.Osu.UI /// private readonly List trackedTouches = new List(); + /// + /// The distance (in local pixels) that a touch must move before being considered a permanent tracking touch. + /// After this distance is covered, any extra touches on the screen will be considered as button inputs, unless + /// a new touch directly interacts with a hit circle. + /// + private const float distance_before_position_tracking_lock_in = 200; + private TrackedTouch? positionTrackingTouch; private readonly OsuInputManager osuInputManager; @@ -98,7 +105,7 @@ namespace osu.Game.Rulesets.Osu.UI } // ..or if the current position tracking touch was not a direct touch (and didn't travel across the screen too far). - if (!positionTrackingTouch.DirectTouch && positionTrackingTouch.DistanceTravelled < 200) + if (!positionTrackingTouch.DirectTouch && positionTrackingTouch.DistanceTravelled < distance_before_position_tracking_lock_in) { positionTrackingTouch = newTouch; return; @@ -160,9 +167,9 @@ namespace osu.Game.Rulesets.Osu.UI public readonly bool DirectTouch; /// - /// The total distance on screen travelled by this touch. + /// The total distance on screen travelled by this touch (in local pixels). /// - public double DistanceTravelled; + public float DistanceTravelled; public TrackedTouch(TouchSource source, OsuAction? action, bool directTouch) { From c056d5a6fb9f779e958b6eb1731ffa204a166600 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Mar 2023 15:36:58 +0900 Subject: [PATCH 0378/1400] Reduce distance requirement for lock-in behaviour --- osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs index 4270a4df58..5277a1f7d6 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuTouchInputMapper.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.UI /// After this distance is covered, any extra touches on the screen will be considered as button inputs, unless /// a new touch directly interacts with a hit circle. /// - private const float distance_before_position_tracking_lock_in = 200; + private const float distance_before_position_tracking_lock_in = 100; private TrackedTouch? positionTrackingTouch; From fe91f85f6fe9afea0139408fc07c0b21d8dc93d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 20 Mar 2023 18:16:33 +0100 Subject: [PATCH 0379/1400] Reuse colour constants in fallback path --- .../Skinning/Argon/ManiaArgonSkinTransformer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index ca9cd83a63..dbea9c7c88 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -294,17 +294,17 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon switch (columnIndex % total_colours) { - case 0: return new Color4(255, 197, 40, 255); + case 0: return colour_yellow; - case 1: return new Color4(252, 109, 1, 255); + case 1: return colour_orange; - case 2: return new Color4(213, 35, 90, 255); + case 2: return colour_pink; - case 3: return new Color4(203, 60, 236, 255); + case 3: return colour_purple; - case 4: return new Color4(72, 198, 255, 255); + case 4: return colour_cyan; - case 5: return new Color4(100, 192, 92, 255); + case 5: return colour_green; default: throw new ArgumentOutOfRangeException(); } From 695ee39b87644f4bf62a52c41b80805b7b772dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 20 Mar 2023 20:30:54 +0100 Subject: [PATCH 0380/1400] Privatise setter --- osu.Game/Screens/Select/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 1bcc042f72..b44ca8ac04 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -252,7 +252,7 @@ namespace osu.Game.Screens.Select { private const float filter_text_size = 12; - public OsuSpriteText FilterText; + public OsuSpriteText FilterText { get; private set; } public FilterControlTextBox() { From ea8da69263ece422d6119dedc1471a8df4654a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 20 Mar 2023 20:49:47 +0100 Subject: [PATCH 0381/1400] Fix importing beatmaps not changing count of visible beatmaps Reproduction steps: 1. Go to song select 2. Open beatmap listing 3. Import a beatmap that would fit the current filter criteria 4. The count of visible beatmaps does not change Fixed by updating the count on `BeatmapSetsChanged` too. --- osu.Game/Screens/Select/SongSelect.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 722119f82e..c5e914b461 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -162,15 +162,7 @@ namespace osu.Game.Screens.Select BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, - FilterApplied = () => - { - FilterControl.InformationalText = - Carousel.CountDisplayed == 1 - // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 - // but also in this case we want support for formatting a number within a string). - ? $"{Carousel.CountDisplayed:#,0} matching beatmap" - : $"{Carousel.CountDisplayed:#,0} matching beatmaps"; - }, + FilterApplied = updateVisibleBeatmapCount, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); @@ -837,6 +829,7 @@ namespace osu.Game.Screens.Select private void carouselBeatmapsLoaded() { bindBindables(); + updateVisibleBeatmapCount(); Carousel.AllowSelection = true; @@ -866,6 +859,15 @@ namespace osu.Game.Screens.Select } } + private void updateVisibleBeatmapCount() + { + FilterControl.InformationalText = Carousel.CountDisplayed == 1 + // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 + // but also in this case we want support for formatting a number within a string). + ? $"{Carousel.CountDisplayed:#,0} matching beatmap" + : $"{Carousel.CountDisplayed:#,0} matching beatmaps"; + } + private bool boundLocalBindables; private void bindBindables() From cc408470f4bafde7c8571171f0392437cc7d4b92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Mar 2023 14:47:20 +0900 Subject: [PATCH 0382/1400] Add test coverage of second touch moving but not resulting in cursor movement --- osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs index d1880d7552..b2e4e07526 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuTouchInput.cs @@ -176,6 +176,14 @@ namespace osu.Game.Rulesets.Osu.Tests checkPressed(OsuAction.RightButton); // in this case, touch 2 should not become the positional tracking touch. checkPosition(TouchSource.Touch1); + + // even if the second touch moves on the screen, the original tracking touch is retained. + beginTouch(TouchSource.Touch2, new Vector2(0)); + beginTouch(TouchSource.Touch2, new Vector2(9999)); + beginTouch(TouchSource.Touch2, new Vector2(0)); + beginTouch(TouchSource.Touch2, new Vector2(9999)); + + checkPosition(TouchSource.Touch1); } [Test] From fb51221c2bb29e492fc09bb4f549bb3854d61432 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Mar 2023 21:25:50 +0900 Subject: [PATCH 0383/1400] Add test coverage of cyclic selection triggering when more than one item is selected --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 35ba363f4b..119b753d70 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -126,6 +126,10 @@ namespace osu.Game.Tests.Visual.Gameplay }); AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); + + // Test cyclic selection doesn't trigger in this state. + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddAssert("Last two boxes still selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); } [Test] @@ -164,6 +168,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); + + AddStep("select all boxes", () => + { + skinEditor.SelectedComponents.Clear(); + skinEditor.SelectedComponents.AddRange(targetContainer.Components.OfType().Skip(1)); + }); + + AddAssert("all boxes selected", () => skinEditor.SelectedComponents, () => Has.Count.EqualTo(2)); + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddStep("click on black box stack", () => InputManager.Click(MouseButton.Left)); + AddAssert("all boxes still selected", () => skinEditor.SelectedComponents, () => Has.Count.EqualTo(2)); } [TestCase(false)] From e31a90e0432928e487c25d0973d75555db68c262 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Mar 2023 21:21:43 +0900 Subject: [PATCH 0384/1400] Don't cycle selection when more than one items are selected --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 143f343c7d..cb7c083d87 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -401,7 +401,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - if (!wasDragStarted && selectedBlueprintAlreadySelectedOnMouseDown && AllowCyclicSelection) + if (!wasDragStarted && selectedBlueprintAlreadySelectedOnMouseDown && SelectedItems.Count == 1 && AllowCyclicSelection) { // If a click occurred and was handled by the currently selected blueprint but didn't result in a drag, // cycle between other blueprints which are also under the cursor. From df3ccdff9fed5b05188af319f19849656ac58975 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 20 Mar 2023 22:22:28 -0700 Subject: [PATCH 0385/1400] Add failing beatmap listing sort direction on criteria change test --- .../TestSceneBeatmapListingSortTabControl.cs | 26 ++++++++++++++++++- .../BeatmapListingSortTabControl.cs | 2 +- osu.Game/Overlays/OverlaySortTabControl.cs | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs index 316035275f..dd7bf48791 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs @@ -14,10 +14,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osuTK; +using osuTK.Input; namespace osu.Game.Tests.Visual.UserInterface { - public partial class TestSceneBeatmapListingSortTabControl : OsuTestScene + public partial class TestSceneBeatmapListingSortTabControl : OsuManualInputManagerTestScene { private readonly BeatmapListingSortTabControl control; @@ -111,6 +112,29 @@ namespace osu.Game.Tests.Visual.UserInterface resetUsesCriteriaOnCategory(SortCriteria.Updated, SearchCategory.Mine); } + [Test] + public void TestSortDirectionOnCriteriaChange() + { + AddStep("set category to leaderboard", () => control.Reset(SearchCategory.Leaderboard, false)); + AddAssert("sort direction is descending", () => control.SortDirection.Value == SortDirection.Descending); + + AddStep("click ranked sort button", () => + { + InputManager.MoveMouseTo(control.TabControl.ChildrenOfType().Single(s => s.Active.Value)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("sort direction is ascending", () => control.SortDirection.Value == SortDirection.Ascending); + + AddStep("click first inactive sort button", () => + { + InputManager.MoveMouseTo(control.TabControl.ChildrenOfType().First(s => !s.Active.Value)); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("sort direction is descending", () => control.SortDirection.Value == SortDirection.Descending); + } + private void criteriaShowsOnCategory(bool expected, SortCriteria criteria, SearchCategory category) { AddAssert($"{criteria.ToString().ToLowerInvariant()} {(expected ? "shown" : "not shown")} on {category.ToString().ToLowerInvariant()}", () => diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index 025738710f..79a2d01208 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -102,7 +102,7 @@ namespace osu.Game.Overlays.BeatmapListing }; } - private partial class BeatmapTabButton : TabButton + public partial class BeatmapTabButton : TabButton { public readonly Bindable SortDirection = new Bindable(); diff --git a/osu.Game/Overlays/OverlaySortTabControl.cs b/osu.Game/Overlays/OverlaySortTabControl.cs index 8af2ab3823..5c51f5e4d0 100644 --- a/osu.Game/Overlays/OverlaySortTabControl.cs +++ b/osu.Game/Overlays/OverlaySortTabControl.cs @@ -117,7 +117,7 @@ namespace osu.Game.Overlays } } - protected partial class TabButton : HeaderButton + public partial class TabButton : HeaderButton { public readonly BindableBool Active = new BindableBool(); From 3cd01ee621d6df6eda45374ed3765cfe3d074887 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 21 Mar 2023 14:49:39 -0700 Subject: [PATCH 0386/1400] Fix beatmap listing sort direction not resetting when changing criteria --- .../Overlays/BeatmapListing/BeatmapListingSortTabControl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index 79a2d01208..9cc4f8a34b 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -25,6 +25,8 @@ namespace osu.Game.Overlays.BeatmapListing if (currentParameters == null) Reset(SearchCategory.Leaderboard, false); + + Current.BindValueChanged(_ => SortDirection.Value = Overlays.SortDirection.Descending); } public void Reset(SearchCategory category, bool hasQuery) From 1478a26cc03beb5f90f53db1d61352de6cea65b4 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 21 Mar 2023 23:15:49 +0100 Subject: [PATCH 0387/1400] Addressed changes --- .../Gameplay/TestSceneSkinnableSound.cs | 5 +-- osu.Game/Skinning/PoolableSkinnableSample.cs | 45 ++----------------- 2 files changed, 5 insertions(+), 45 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs index cc82ffed2b..3f78dbfd96 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableSound.cs @@ -107,15 +107,12 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("ensure sample loaded", () => skinnableSound.ChildrenOfType().Single().Name, () => Is.EqualTo(sample_lookup)); - AddStep("Change source", () => + AddStep("change source", () => { skinSource.OverridingSample = new SampleVirtual("new skin"); skinSource.TriggerSourceChanged(); }); - // Samples are nulled on source change immediately - AddUntilStep("wait for sample null", () => skinnableSound.ChildrenOfType().Count(), () => Is.Zero); - AddStep("start sample", () => skinnableSound.Play()); AddUntilStep("sample updated", () => skinnableSound.ChildrenOfType().Single().Name, () => Is.EqualTo("new skin")); } diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index 361c8688e7..eacb33f7d7 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -4,12 +4,10 @@ #nullable disable using System; -using System.Linq; using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; @@ -70,48 +68,21 @@ namespace osu.Game.Skinning updateSample(); } - protected override void LoadComplete() - { - base.LoadComplete(); - - CurrentSkin.SourceChanged += skinChangedImmediate; - } - - private void skinChangedImmediate() - { - // Clean up the previous sample immediately on a source change. - // This avoids a potential call to Play() of an already disposed sample (samples are disposed along with the skin, but SkinChanged is scheduled). - clearPreviousSamples(); - } - protected override void SkinChanged(ISkinSource skin) { base.SkinChanged(skin); updateSample(); } - /// - /// Whether this sample was playing before a skin source change. - /// - private bool wasPlaying; - - private void clearPreviousSamples() - { - // only run if the samples aren't already cleared. - // this ensures the "wasPlaying" state is stored correctly even if multiple clear calls are executed. - if (!sampleContainer.Any()) return; - - wasPlaying = Playing; - - sampleContainer.Clear(); - Sample = null; - } - private void updateSample() { if (sampleInfo == null) return; + bool wasPlaying = Playing; + + sampleContainer.Clear(); + var sample = CurrentSkin.GetSample(sampleInfo); if (sample == null) @@ -174,14 +145,6 @@ namespace osu.Game.Skinning } } - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (CurrentSkin.IsNotNull()) - CurrentSkin.SourceChanged -= skinChangedImmediate; - } - #region Re-expose AudioContainer public BindableNumber Volume => sampleContainer.Volume; From e1fb63e1f313943d058c820ca6a660d9342ca15f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 20 Mar 2023 22:27:07 -0700 Subject: [PATCH 0388/1400] Move beatmap listing filter control to header --- .../BeatmapListing/BeatmapListingHeader.cs | 5 +++++ osu.Game/Overlays/BeatmapListingOverlay.cs | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs index 76b6dec65b..3336c383ff 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -3,6 +3,7 @@ #nullable disable +using osu.Framework.Graphics; using osu.Game.Localisation; using osu.Game.Resources.Localisation.Web; @@ -10,8 +11,12 @@ namespace osu.Game.Overlays.BeatmapListing { public partial class BeatmapListingHeader : OverlayHeader { + public BeatmapListingFilterControl FilterControl { get; private set; } + protected override OverlayTitle CreateTitle() => new BeatmapListingTitle(); + protected override Drawable CreateContent() => FilterControl = new BeatmapListingFilterControl(); + private partial class BeatmapListingTitle : OverlayTitle { public BeatmapListingTitle() diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 73961487ed..d2f39fde8e 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -43,7 +43,13 @@ namespace osu.Game.Overlays private Container panelTarget; private FillFlowContainer foundContent; - private BeatmapListingFilterControl filterControl; + + private BeatmapListingFilterControl filterControl => Header.FilterControl.With(f => + { + f.TypingStarted = onTypingStarted; + f.SearchStarted = onSearchStarted; + f.SearchFinished = onSearchFinished; + }); public BeatmapListingOverlay() : base(OverlayColourScheme.Blue) @@ -60,12 +66,6 @@ namespace osu.Game.Overlays Direction = FillDirection.Vertical, Children = new Drawable[] { - filterControl = new BeatmapListingFilterControl - { - TypingStarted = onTypingStarted, - SearchStarted = onSearchStarted, - SearchFinished = onSearchFinished, - }, new Container { AutoSizeAxes = Axes.Y, From 74a15d742495d95fbb94ce2793e750802f67feef Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 20 Mar 2023 22:26:51 -0700 Subject: [PATCH 0389/1400] Fix overlay headers being blocked by loading layer --- osu.Game/Overlays/OnlineOverlay.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index 4fdf7cb2b6..f29a5719d8 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.cs @@ -3,6 +3,7 @@ #nullable disable +using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,6 +23,7 @@ namespace osu.Game.Overlays protected readonly OverlayScrollContainer ScrollFlow; protected readonly LoadingLayer Loading; + private readonly Container loadingContainer; private readonly Container content; protected OnlineOverlay(OverlayColourScheme colourScheme, bool requiresSignIn = true) @@ -65,10 +67,21 @@ namespace osu.Game.Overlays }, } }, - Loading = new LoadingLayer(true) + loadingContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = Loading = new LoadingLayer(true), + } }); base.Content.Add(mainContent); } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + loadingContainer.Padding = new MarginPadding { Top = Math.Max(0, Header.Height - ScrollFlow.Current) }; + } } } From d9571b6fc9700111a5ca3ee1433618e667cca766 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 21 Mar 2023 21:31:35 -0700 Subject: [PATCH 0390/1400] Move filter control property setters to `load()` --- osu.Game/Overlays/BeatmapListingOverlay.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index d2f39fde8e..f8784504b8 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -44,12 +44,7 @@ namespace osu.Game.Overlays private Container panelTarget; private FillFlowContainer foundContent; - private BeatmapListingFilterControl filterControl => Header.FilterControl.With(f => - { - f.TypingStarted = onTypingStarted; - f.SearchStarted = onSearchStarted; - f.SearchFinished = onSearchFinished; - }); + private BeatmapListingFilterControl filterControl => Header.FilterControl; public BeatmapListingOverlay() : base(OverlayColourScheme.Blue) @@ -88,6 +83,10 @@ namespace osu.Game.Overlays }, } }; + + filterControl.TypingStarted = onTypingStarted; + filterControl.SearchStarted = onSearchStarted; + filterControl.SearchFinished = onSearchFinished; } protected override void LoadComplete() From 425be20e462f32af5ca4a5103383a664f281315e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Mar 2023 14:13:42 +0900 Subject: [PATCH 0391/1400] Fix song select search textbox font size incorrectly having increased --- osu.Game/Screens/Select/FilterControl.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b44ca8ac04..38520a85b7 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -257,6 +257,7 @@ namespace osu.Game.Screens.Select public FilterControlTextBox() { Height += filter_text_size; + TextContainer.Height *= (Height - filter_text_size) / Height; TextContainer.Margin = new MarginPadding { Bottom = filter_text_size }; } From c65a79614dcee1f5d570a31fe1dc37a0bcc1487a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Mar 2023 15:45:02 +0900 Subject: [PATCH 0392/1400] Don't show offset calibration controls when "relax" mod is active Closes https://github.com/ppy/osu/issues/22892. --- osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs index 9492614b66..8d5459809e 100644 --- a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs +++ b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Localisation; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Statistics; @@ -183,7 +184,7 @@ namespace osu.Game.Screens.Play.PlayerSettings if (score.NewValue == null) return; - if (score.NewValue.Mods.Any(m => !m.UserPlayable)) + if (score.NewValue.Mods.Any(m => !m.UserPlayable || m is ModRelax)) return; var hitEvents = score.NewValue.HitEvents; From 6f3bb85eaab77c727a64bffc415d56c853796aa7 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 22 Mar 2023 00:19:23 -0700 Subject: [PATCH 0393/1400] Always show down arrow on inactive sort buttons --- .../Overlays/BeatmapListing/BeatmapListingSortTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index 9cc4f8a34b..2f290d05e9 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -138,7 +138,7 @@ namespace osu.Game.Overlays.BeatmapListing SortDirection.BindValueChanged(direction => { - icon.Icon = direction.NewValue == Overlays.SortDirection.Ascending ? FontAwesome.Solid.CaretUp : FontAwesome.Solid.CaretDown; + icon.Icon = direction.NewValue == Overlays.SortDirection.Ascending && Active.Value ? FontAwesome.Solid.CaretUp : FontAwesome.Solid.CaretDown; }, true); } From 9bc6b46e4e407704dddfe91ce2b043494825424a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Mar 2023 16:36:05 +0900 Subject: [PATCH 0394/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4e580a6919..a62e28dca0 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c08dc9ed8f..d5ff3fad56 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 8738979c57..25466f5426 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 13be7097180551ff44c801ed219472d2d999c588 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Mar 2023 19:29:34 +0900 Subject: [PATCH 0395/1400] Add basic renderer selection --- .../Settings/Sections/Graphics/RendererSettings.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index a5fdfdc105..08a62ff324 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -23,6 +22,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics // NOTE: Compatability mode omitted Children = new Drawable[] { + new SettingsEnumDropdown + { + LabelText = GraphicsSettingsStrings.Renderer, + Current = config.GetBindable(FrameworkSetting.Renderer), + Keywords = new[] { @"compatibility", @"directx" }, + }, // TODO: this needs to be a custom dropdown at some point new SettingsEnumDropdown { From 956fabb445aa22ec931750f20c5c78c7a80bab6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Mar 2023 20:28:26 +0900 Subject: [PATCH 0396/1400] Show restart notice when changing renderer --- .../Localisation/GraphicsSettingsStrings.cs | 11 ++++++++++ .../Sections/Graphics/RendererSettings.cs | 20 +++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 6e05929d81..422704514f 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -19,6 +19,11 @@ namespace osu.Game.Localisation /// public static LocalisableString RendererHeader => new TranslatableString(getKey(@"renderer_header"), @"Renderer"); + /// + /// "Renderer" + /// + public static LocalisableString Renderer => new TranslatableString(getKey(@"renderer"), @"Renderer"); + /// /// "Frame limiter" /// @@ -144,6 +149,12 @@ namespace osu.Game.Localisation /// public static LocalisableString Png => new TranslatableString(getKey(@"png_lossless"), @"PNG (lossless)"); + /// + /// "In order to change the renderer, the game will close. Please open it again." + /// + public static LocalisableString ChangeRendererConfirmation => + new TranslatableString(getKey(@"change_renderer_configuration"), @"In order to change the renderer, the game will close. Please open it again."); + private static string getKey(string key) => $"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 08a62ff324..ba2691e41c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -2,13 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Configuration; using osu.Game.Localisation; +using osu.Game.Overlays.Dialog; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -17,15 +17,16 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuConfigManager osuConfig) + private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDialogOverlay dialogOverlay, OsuGame game, GameHost host) { - // NOTE: Compatability mode omitted + var renderer = config.GetBindable(FrameworkSetting.Renderer); + Children = new Drawable[] { new SettingsEnumDropdown { LabelText = GraphicsSettingsStrings.Renderer, - Current = config.GetBindable(FrameworkSetting.Renderer), + Current = renderer, Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point @@ -46,6 +47,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Current = osuConfig.GetBindable(OsuSetting.ShowFpsDisplay) }, }; + + renderer.BindValueChanged(r => + { + if (r.NewValue == host.ResolvedRenderer) + return; + + dialogOverlay.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, game.AttemptExit, () => + { + renderer.SetDefault(); + })); + }); } } } From aabe86dc26c90c90e1d9a5c0bd860bcf6d1b06fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Mar 2023 20:28:36 +0900 Subject: [PATCH 0397/1400] Limit renderers to those available for the current platform --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index ba2691e41c..80e5dd3843 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.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 System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -27,6 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, + Items = host.GetPreferredRenderersForCurrentPlatform().OrderBy(t => t), Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point From 3050a16bf866895a9188e008f397b3e0262cea58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Mar 2023 16:56:35 +0900 Subject: [PATCH 0398/1400] Don't require a restart when selecting `Automatic` and startup setting was also automatic --- .../Settings/Sections/Graphics/RendererSettings.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 80e5dd3843..4f24898bce 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -17,10 +17,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { protected override LocalisableString Header => GraphicsSettingsStrings.RendererHeader; + private bool automaticRendererInUse; + [BackgroundDependencyLoader] private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDialogOverlay dialogOverlay, OsuGame game, GameHost host) { var renderer = config.GetBindable(FrameworkSetting.Renderer); + automaticRendererInUse = renderer.Value == RendererType.Automatic; Children = new Drawable[] { @@ -55,6 +58,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (r.NewValue == host.ResolvedRenderer) return; + // Need to check startup renderer for the "automatic" case, as ResolvedRenderer above will track the final resolved renderer instead. + if (r.NewValue == RendererType.Automatic && automaticRendererInUse) + return; + dialogOverlay.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, game.AttemptExit, () => { renderer.SetDefault(); From 8518d15b8daf8cd2cbb047054e8b2286c0f63493 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Mar 2023 00:13:24 +0900 Subject: [PATCH 0399/1400] use endpoint --- .../Visual/Online/TestSceneChatOverlay.cs | 33 +++++++++++++++- .../Online/API/Requests/ChatReportRequest.cs | 38 +++++++++++++++++++ osu.Game/Overlays/Chat/ChatLine.cs | 2 +- osu.Game/Overlays/Chat/DrawableUsername.cs | 24 ++++++++++-- 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 osu.Game/Online/API/Requests/ChatReportRequest.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 48db5691ce..08337fbff9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Collections.Generic; using System.Net; using System.Threading; +using System.Threading.Tasks; using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; @@ -32,6 +33,7 @@ using osu.Game.Overlays.Chat.ChannelList; using osuTK; using osuTK.Input; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { @@ -55,6 +57,9 @@ namespace osu.Game.Tests.Visual.Online private int currentMessageId; + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + private readonly ManualResetEventSlim requestLock = new ManualResetEventSlim(); + [SetUp] public void SetUp() => Schedule(() => { @@ -581,6 +586,8 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestChatReport() { + ChatReportRequest request = null; + AddStep("Show overlay with channel", () => { chatOverlay.Show(); @@ -590,6 +597,26 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Overlay is visible", () => chatOverlay.State.Value == Visibility.Visible); waitForChannel1Visible(); + AddStep("Setup request handling", () => + { + requestLock.Reset(); + + dummyAPI.HandleRequest = r => + { + if (!(r is ChatReportRequest req)) + return false; + + Task.Run(() => + { + request = req; + requestLock.Wait(10000); + req.TriggerSuccess(); + }); + + return true; + }; + }); + AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); AddStep("Try to report", () => @@ -599,7 +626,11 @@ namespace osu.Game.Tests.Visual.Online InputManager.Click(MouseButton.Left); }); - AddAssert("Report message sended", () => channelManager.CurrentChannel.Value.Messages.Any(x => x.Content.Contains("!report"))); + AddWaitStep("Wait", 3); + + AddAssert("Overlay closed", () => !this.ChildrenOfType().Any()); + AddStep("Complete request", () => requestLock.Set()); + AddUntilStep("Request sent", () => request != null); } private void joinTestChannel(int i) diff --git a/osu.Game/Online/API/Requests/ChatReportRequest.cs b/osu.Game/Online/API/Requests/ChatReportRequest.cs new file mode 100644 index 0000000000..00d314be68 --- /dev/null +++ b/osu.Game/Online/API/Requests/ChatReportRequest.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Net.Http; +using osu.Framework.IO.Network; +using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; + +namespace osu.Game.Online.API.Requests; + +public class ChatReportRequest : APIRequest +{ + public readonly long? MessageId; + public readonly ChatReportReason Reason; + public readonly string Comment; + + public ChatReportRequest(long? id, ChatReportReason reason, string comment) + { + MessageId = id; + Reason = reason; + Comment = comment; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + + req.AddParameter(@"reportable_type", @"message"); + req.AddParameter(@"reportable_id", $"{MessageId}"); + req.AddParameter(@"reason", Reason.ToString()); + req.AddParameter(@"comments", Comment); + + return req; + } + + protected override string Target => @"reports"; +} diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 70c3bf181c..0e69501ae9 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername = new DrawableUsername(message.Sender) + drawableUsername = new DrawableUsername(message) { Width = UsernameWidth, FontSize = FontSize, diff --git a/osu.Game/Overlays/Chat/DrawableUsername.cs b/osu.Game/Overlays/Chat/DrawableUsername.cs index 640ce2eca6..c9b0b018e3 100644 --- a/osu.Game/Overlays/Chat/DrawableUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableUsername.cs @@ -21,6 +21,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Resources.Localisation.Web; @@ -72,13 +73,15 @@ namespace osu.Game.Overlays.Chat private Bindable? currentChannel { get; set; } private readonly APIUser user; + private readonly Message message; private readonly OsuSpriteText drawableText; private readonly Drawable colouredDrawable; - public DrawableUsername(APIUser user) + public DrawableUsername(Message message) { - this.user = user; + this.message = message; + user = message.Sender; Action = openUserProfile; @@ -171,7 +174,8 @@ namespace osu.Game.Overlays.Chat })); } - items.Add(new OsuMenuItem("Report", MenuItemType.Destructive, this.ShowPopover)); + if (!user.Equals(api.LocalUser.Value)) + items.Add(new OsuMenuItem("Report", MenuItemType.Destructive, this.ShowPopover)); return items.ToArray(); } @@ -179,7 +183,19 @@ namespace osu.Game.Overlays.Chat private void report(ChatReportReason reason, string comments) { - chatManager?.PostMessage($"!report {user.Username} ({reason.GetDescription()}): {comments}"); + var request = new ChatReportRequest(message.Id, reason, comments); + + request.Failure += _ => Schedule(() => + { + currentChannel?.Value?.AddNewMessages(new ErrorMessage("Report failed to send, please retry")); + }); + + request.Success += () => Schedule(() => + { + currentChannel?.Value?.AddNewMessages(new InfoMessage("Report has been sent")); + }); + + api.Queue(request); } private void openUserChannel() From 85a924f0782ee04f48aae86224f09343f7b37979 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Mar 2023 01:02:17 +0900 Subject: [PATCH 0400/1400] why merge problem? --- osu.Game/Overlays/Chat/DrawableUsername.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Chat/DrawableUsername.cs b/osu.Game/Overlays/Chat/DrawableUsername.cs index c9b0b018e3..25967003e9 100644 --- a/osu.Game/Overlays/Chat/DrawableUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableUsername.cs @@ -163,8 +163,7 @@ namespace osu.Game.Overlays.Chat }; if (!user.Equals(api.LocalUser.Value)) - items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, openUserChannel)); - items.Add(new OsuMenuItem(UsersStrings.CardSendMessage, MenuItemType.Standard, openUserChannel)); + items.Add(new OsuMenuItem(UsersStrings.CardSendMessage, MenuItemType.Standard, openUserChannel)); if (currentChannel?.Value != null) { From 26f2d9047d3238b4790613102e2d0500a18d69d9 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 23 Mar 2023 01:11:44 +0900 Subject: [PATCH 0401/1400] code style fix --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 1 - osu.Game/Online/API/Requests/ChatReportRequest.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 08337fbff9..5845ba3783 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -33,7 +33,6 @@ using osu.Game.Overlays.Chat.ChannelList; using osuTK; using osuTK.Input; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Overlays.Comments; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Online/API/Requests/ChatReportRequest.cs b/osu.Game/Online/API/Requests/ChatReportRequest.cs index 00d314be68..01cb455183 100644 --- a/osu.Game/Online/API/Requests/ChatReportRequest.cs +++ b/osu.Game/Online/API/Requests/ChatReportRequest.cs @@ -3,7 +3,6 @@ using System.Net.Http; using osu.Framework.IO.Network; -using osu.Game.Online.Chat; using osu.Game.Overlays.Chat; namespace osu.Game.Online.API.Requests; From ab6cfea5c71dded5fbd88ef4183943e7e25fbc74 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Mar 2023 11:27:05 +0900 Subject: [PATCH 0402/1400] Revert old value instead of always using default Co-authored-by: cdwcgt --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 4f24898bce..45a6d35749 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics dialogOverlay.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, game.AttemptExit, () => { - renderer.SetDefault(); + renderer.Value = r.OldValue; })); }); } From 540b38dc2191691047b7ccf646c2b82541870233 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Mar 2023 14:01:19 +0900 Subject: [PATCH 0403/1400] Fix tournament interface save button not usable after changing match progression/round --- osu.Game.Tournament/TournamentGameBase.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 7e19cb3aa5..634cc87a9f 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -332,13 +332,6 @@ namespace osu.Game.Tournament private void saveChanges() { - foreach (var r in ladder.Rounds) - r.Matches = ladder.Matches.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); - - ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( - ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) - .ToList(); - // Serialise before opening stream for writing, so if there's a failure it will leave the file in the previous state. string serialisedLadder = GetSerialisedLadder(); @@ -349,6 +342,13 @@ namespace osu.Game.Tournament public string GetSerialisedLadder() { + foreach (var r in ladder.Rounds) + r.Matches = ladder.Matches.Where(p => p.Round.Value == r).Select(p => p.ID).ToList(); + + ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat( + ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true))) + .ToList(); + return JsonConvert.SerializeObject(ladder, new JsonSerializerSettings { From e6f1ec57a963cf4bdc16d8c186227dd18230d6d9 Mon Sep 17 00:00:00 2001 From: Terochi Date: Thu, 23 Mar 2023 18:46:48 +0100 Subject: [PATCH 0404/1400] Bring back and make use of `clearPreviousSamples()` --- osu.Game/Skinning/PoolableSkinnableSample.cs | 26 ++++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Skinning/PoolableSkinnableSample.cs b/osu.Game/Skinning/PoolableSkinnableSample.cs index eacb33f7d7..76c2c4d7ec 100644 --- a/osu.Game/Skinning/PoolableSkinnableSample.cs +++ b/osu.Game/Skinning/PoolableSkinnableSample.cs @@ -4,6 +4,7 @@ #nullable disable using System; +using System.Linq; using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -74,14 +75,29 @@ namespace osu.Game.Skinning updateSample(); } - private void updateSample() - { - if (sampleInfo == null) - return; + /// + /// Whether this sample was playing before a skin source change. + /// + private bool wasPlaying; - bool wasPlaying = Playing; + private void clearPreviousSamples() + { + // only run if the samples aren't already cleared. + // this ensures the "wasPlaying" state is stored correctly even if multiple clear calls are executed. + if (!sampleContainer.Any()) return; + + wasPlaying = Playing; sampleContainer.Clear(); + Sample = null; + } + + private void updateSample() + { + clearPreviousSamples(); + + if (sampleInfo == null) + return; var sample = CurrentSkin.GetSample(sampleInfo); From 450c5cef074b85b6f190b9ca05687937b044d776 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 24 Mar 2023 18:42:34 -0700 Subject: [PATCH 0405/1400] Add comment explaining loading container padding --- osu.Game/Overlays/OnlineOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index f29a5719d8..4d2c6bc9d0 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.cs @@ -81,6 +81,7 @@ namespace osu.Game.Overlays { base.UpdateAfterChildren(); + // don't block header by applying padding equal to the visible header height loadingContainer.Padding = new MarginPadding { Top = Math.Max(0, Header.Height - ScrollFlow.Current) }; } } From e1906a90eb8f6ea79140490304b06ee3453f1508 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 21 Mar 2023 13:23:08 -0700 Subject: [PATCH 0406/1400] Use `image@2x` from tournament banner api --- osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs | 1 + osu.Game/Users/TournamentBanner.cs | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index a97c8aff66..4278c46d6a 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -126,6 +126,7 @@ namespace osu.Game.Tests.Visual.Online Id = 13926, TournamentId = 35, ImageLowRes = "https://assets.ppy.sh/tournament-banners/official/owc2022/profile/winner_US.jpg", + Image = "https://assets.ppy.sh/tournament-banners/official/owc2022/profile/winner_US@2x.jpg", }, Badges = new[] { diff --git a/osu.Game/Users/TournamentBanner.cs b/osu.Game/Users/TournamentBanner.cs index 62e1913412..e7fada1eff 100644 --- a/osu.Game/Users/TournamentBanner.cs +++ b/osu.Game/Users/TournamentBanner.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.IO; using Newtonsoft.Json; namespace osu.Game.Users @@ -17,7 +16,7 @@ namespace osu.Game.Users [JsonProperty("image")] public string ImageLowRes = null!; - // TODO: remove when api returns @2x image link: https://github.com/ppy/osu-web/issues/9816 - public string Image => $@"{Path.ChangeExtension(ImageLowRes, null)}@2x{Path.GetExtension(ImageLowRes)}"; + [JsonProperty("image@2x")] + public string Image = null!; } } From eaef5ff2a3e0412036246eb6b4226a156bdbeaed Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 25 Mar 2023 22:13:51 -0700 Subject: [PATCH 0407/1400] Fix now playing playlist not highlighting selected item on initial open --- osu.Game/Overlays/Music/PlaylistItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 00c5ce8002..4032af7651 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music selected = newSelected; updateSelectionState(false); - }); + }, true); updateSelectionState(true); }); From c803eb8e044424c601a585632755bf5f48f47834 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 16:14:15 +0900 Subject: [PATCH 0408/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index a62e28dca0..bc382d8f97 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f8fc6ffda6..16f780d034 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 25466f5426..5d90119233 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 27de3314fdfb89cec20e1d34d9d323354e3922c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 16:23:07 +0900 Subject: [PATCH 0409/1400] Remove iOS mouse handler code --- osu.iOS/IOSMouseSettings.cs | 36 ------------------------------------ osu.iOS/OsuGameIOS.cs | 15 --------------- 2 files changed, 51 deletions(-) delete mode 100644 osu.iOS/IOSMouseSettings.cs diff --git a/osu.iOS/IOSMouseSettings.cs b/osu.iOS/IOSMouseSettings.cs deleted file mode 100644 index f464bd93b8..0000000000 --- a/osu.iOS/IOSMouseSettings.cs +++ /dev/null @@ -1,36 +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.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Localisation; -using osu.Game.Configuration; -using osu.Game.Localisation; -using osu.Game.Overlays.Settings; - -namespace osu.iOS -{ - public partial class IOSMouseSettings : SettingsSubsection - { - protected override LocalisableString Header => MouseSettingsStrings.Mouse; - - [BackgroundDependencyLoader] - private void load(OsuConfigManager osuConfig) - { - Children = new Drawable[] - { - new SettingsCheckbox - { - LabelText = MouseSettingsStrings.DisableMouseWheelVolumeAdjust, - TooltipText = MouseSettingsStrings.DisableMouseWheelVolumeAdjustTooltip, - Current = osuConfig.GetBindable(OsuSetting.MouseDisableWheel), - }, - new SettingsCheckbox - { - LabelText = MouseSettingsStrings.DisableMouseButtons, - Current = osuConfig.GetBindable(OsuSetting.MouseDisableButtons), - }, - }; - } - } -} diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index 3e79bc6ad6..c49e6907ff 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.cs @@ -7,10 +7,7 @@ using System; using Foundation; using Microsoft.Maui.Devices; using osu.Framework.Graphics; -using osu.Framework.Input.Handlers; -using osu.Framework.iOS.Input; using osu.Game; -using osu.Game.Overlays.Settings; using osu.Game.Updater; using osu.Game.Utils; @@ -29,18 +26,6 @@ namespace osu.iOS // Because we have the home indicator (mostly) hidden we don't really care about drawing in this region. Edges.Bottom; - public override SettingsSubsection CreateSettingsSubsectionFor(InputHandler handler) - { - switch (handler) - { - case IOSMouseHandler: - return new IOSMouseSettings(); - - default: - return base.CreateSettingsSubsectionFor(handler); - } - } - private class IOSBatteryInfo : BatteryInfo { public override double? ChargeLevel => Battery.ChargeLevel; From 816eff1a87348e1b240dec34df0222868866fdf8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 16:27:44 +0900 Subject: [PATCH 0410/1400] Update iOS startup code --- .../AppDelegate.cs | 17 ----------- .../Application.cs | 7 ++--- .../AppDelegate.cs | 17 ----------- .../Application.cs | 7 ++--- .../AppDelegate.cs | 17 ----------- .../Application.cs | 7 ++--- .../AppDelegate.cs | 17 ----------- .../Application.cs | 7 ++--- osu.Game.Tests.iOS/AppDelegate.cs | 16 ---------- osu.Game.Tests.iOS/Application.cs | 6 ++-- osu.iOS/AppDelegate.cs | 29 ------------------- osu.iOS/Application.cs | 6 ++-- 12 files changed, 16 insertions(+), 137 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs delete mode 100644 osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs delete mode 100644 osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs delete mode 100644 osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs delete mode 100644 osu.Game.Tests.iOS/AppDelegate.cs delete mode 100644 osu.iOS/AppDelegate.cs diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs deleted file mode 100644 index 64ff3f7151..0000000000 --- a/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using Foundation; -using osu.Framework.iOS; -using osu.Game.Tests; - -namespace osu.Game.Rulesets.Catch.Tests.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - protected override Framework.Game CreateGame() => new OsuTestBrowser(); - } -} diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs index 1fcb0aa427..d097c6a698 100644 --- a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; +using osu.Game.Tests; namespace osu.Game.Rulesets.Catch.Tests.iOS { @@ -11,7 +10,7 @@ namespace osu.Game.Rulesets.Catch.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuTestBrowser()); } } } diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs deleted file mode 100644 index a528634f3b..0000000000 --- a/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using Foundation; -using osu.Framework.iOS; -using osu.Game.Tests; - -namespace osu.Game.Rulesets.Mania.Tests.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - protected override Framework.Game CreateGame() => new OsuTestBrowser(); - } -} diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs index a508198f7f..75a5a73058 100644 --- a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; +using osu.Game.Tests; namespace osu.Game.Rulesets.Mania.Tests.iOS { @@ -11,7 +10,7 @@ namespace osu.Game.Rulesets.Mania.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuTestBrowser()); } } } diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs deleted file mode 100644 index fa40a8536e..0000000000 --- a/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using Foundation; -using osu.Framework.iOS; -using osu.Game.Tests; - -namespace osu.Game.Rulesets.Osu.Tests.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - protected override Framework.Game CreateGame() => new OsuTestBrowser(); - } -} diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs index 6ef29fa68e..f9059014a5 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; +using osu.Game.Tests; namespace osu.Game.Rulesets.Osu.Tests.iOS { @@ -11,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuTestBrowser()); } } } diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs deleted file mode 100644 index 385ba48707..0000000000 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using Foundation; -using osu.Framework.iOS; -using osu.Game.Tests; - -namespace osu.Game.Rulesets.Taiko.Tests.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - protected override Framework.Game CreateGame() => new OsuTestBrowser(); - } -} diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs index 0e3a953728..0b6a11d8c2 100644 --- a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; +using osu.Game.Tests; namespace osu.Game.Rulesets.Taiko.Tests.iOS { @@ -11,7 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuTestBrowser()); } } } diff --git a/osu.Game.Tests.iOS/AppDelegate.cs b/osu.Game.Tests.iOS/AppDelegate.cs deleted file mode 100644 index b13027459f..0000000000 --- a/osu.Game.Tests.iOS/AppDelegate.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. - -#nullable disable - -using Foundation; -using osu.Framework.iOS; - -namespace osu.Game.Tests.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - protected override Framework.Game CreateGame() => new OsuTestBrowser(); - } -} diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs index 4678be4fb8..e5df79f3de 100644 --- a/osu.Game.Tests.iOS/Application.cs +++ b/osu.Game.Tests.iOS/Application.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; namespace osu.Game.Tests.iOS { @@ -11,7 +9,7 @@ namespace osu.Game.Tests.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuTestBrowser()); } } } diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs deleted file mode 100644 index 1d29d59fff..0000000000 --- a/osu.iOS/AppDelegate.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using System.Threading.Tasks; -using Foundation; -using osu.Framework.iOS; -using UIKit; - -namespace osu.iOS -{ - [Register("AppDelegate")] - public class AppDelegate : GameAppDelegate - { - private OsuGameIOS game; - - protected override Framework.Game CreateGame() => game = new OsuGameIOS(); - - public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) - { - if (url.IsFileUrl) - Task.Run(() => game.Import(url.Path)); - else - Task.Run(() => game.HandleLink(url.AbsoluteString)); - return true; - } - } -} diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs index 64eb5c63f5..74bd58acb8 100644 --- a/osu.iOS/Application.cs +++ b/osu.iOS/Application.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using UIKit; +using osu.Framework.iOS; namespace osu.iOS { @@ -11,7 +9,7 @@ namespace osu.iOS { public static void Main(string[] args) { - UIApplication.Main(args, null, typeof(AppDelegate)); + GameApplication.Main(new OsuGameIOS()); } } } From e346b02ebf811f172bd7416db85bc0975406ccd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 20:09:35 +0900 Subject: [PATCH 0411/1400] Add display of current renderer --- osu.Game/Localisation/GraphicsSettingsStrings.cs | 5 +++++ .../Settings/Sections/Graphics/RendererSettings.cs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index 422704514f..d35446af3d 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -24,6 +24,11 @@ namespace osu.Game.Localisation /// public static LocalisableString Renderer => new TranslatableString(getKey(@"renderer"), @"Renderer"); + /// + /// "Current renderer is "{0}"" + /// + public static LocalisableString CurrentRenderer(string arg0) => new TranslatableString(getKey(@"current_renderer"), @"Current renderer is ""{0}""", arg0); + /// /// "Frame limiter" /// diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 45a6d35749..2a25939e08 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -4,6 +4,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; @@ -25,9 +26,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics var renderer = config.GetBindable(FrameworkSetting.Renderer); automaticRendererInUse = renderer.Value == RendererType.Automatic; + SettingsEnumDropdown rendererDropdown; + Children = new Drawable[] { - new SettingsEnumDropdown + rendererDropdown = new SettingsEnumDropdown { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, @@ -67,6 +70,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics renderer.Value = r.OldValue; })); }); + + if (renderer.Value == RendererType.Automatic) + rendererDropdown.SetNoticeText(GraphicsSettingsStrings.CurrentRenderer(host.ResolvedRenderer.GetDescription())); } } } From 764361b3d3ae9e7c5276cb4ec861b98ae0b90fb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 20:14:33 +0900 Subject: [PATCH 0412/1400] Add special case to hide definitely non-working renderers on android --- .../Settings/Sections/Graphics/RendererSettings.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 2a25939e08..4b5d2f5a7e 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions; @@ -71,7 +72,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics })); }); - if (renderer.Value == RendererType.Automatic) + // TODO: remove this once we support SDL+android. + if (RuntimeInfo.OS == RuntimeInfo.Platform.Android) + { + rendererDropdown.Items = new[] { RendererType.Automatic, RendererType.OpenGLLegacy }; + rendererDropdown.SetNoticeText("New renderer support for android is coming soon!", true); + } + else if (renderer.Value == RendererType.Automatic) rendererDropdown.SetNoticeText(GraphicsSettingsStrings.CurrentRenderer(host.ResolvedRenderer.GetDescription())); } } From ba078e8357ef50d4a737a2e8f7366887e1bbd670 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 20:29:30 +0900 Subject: [PATCH 0413/1400] Show "automatic" resolved renderer inline in dropdown instead --- .../Localisation/GraphicsSettingsStrings.cs | 5 --- .../Sections/Graphics/RendererSettings.cs | 33 ++++++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/osu.Game/Localisation/GraphicsSettingsStrings.cs b/osu.Game/Localisation/GraphicsSettingsStrings.cs index d35446af3d..422704514f 100644 --- a/osu.Game/Localisation/GraphicsSettingsStrings.cs +++ b/osu.Game/Localisation/GraphicsSettingsStrings.cs @@ -24,11 +24,6 @@ namespace osu.Game.Localisation /// public static LocalisableString Renderer => new TranslatableString(getKey(@"renderer"), @"Renderer"); - /// - /// "Current renderer is "{0}"" - /// - public static LocalisableString CurrentRenderer(string arg0) => new TranslatableString(getKey(@"current_renderer"), @"Current renderer is ""{0}""", arg0); - /// /// "Frame limiter" /// diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 4b5d2f5a7e..f007d45e8f 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -5,11 +5,11 @@ using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; using osu.Game.Configuration; +using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Overlays.Dialog; @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Children = new Drawable[] { - rendererDropdown = new SettingsEnumDropdown + rendererDropdown = new RendererSettingsDropdown { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, @@ -78,8 +78,33 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics rendererDropdown.Items = new[] { RendererType.Automatic, RendererType.OpenGLLegacy }; rendererDropdown.SetNoticeText("New renderer support for android is coming soon!", true); } - else if (renderer.Value == RendererType.Automatic) - rendererDropdown.SetNoticeText(GraphicsSettingsStrings.CurrentRenderer(host.ResolvedRenderer.GetDescription())); + } + + private partial class RendererSettingsDropdown : SettingsEnumDropdown + { + protected override OsuDropdown CreateDropdown() => new RendererDropdown(); + + protected partial class RendererDropdown : DropdownControl + { + private RendererType hostResolvedRenderer; + private bool automaticRendererInUse; + + [BackgroundDependencyLoader] + private void load(FrameworkConfigManager config, GameHost host) + { + var renderer = config.GetBindable(FrameworkSetting.Renderer); + automaticRendererInUse = renderer.Value == RendererType.Automatic; + hostResolvedRenderer = host.ResolvedRenderer; + } + + protected override LocalisableString GenerateItemText(RendererType item) + { + if (item == RendererType.Automatic && automaticRendererInUse) + return $"{base.GenerateItemText(item)} ({hostResolvedRenderer})"; + + return base.GenerateItemText(item); + } + } } } } From bab93bed177bd85c52f7ea9928e1cda4c8733603 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 26 Mar 2023 20:43:28 +0900 Subject: [PATCH 0414/1400] Fix string interpolation and use `GetDescription` on renderer value --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index f007d45e8f..f9127fcd9a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -5,6 +5,7 @@ using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Platform; @@ -100,7 +101,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString GenerateItemText(RendererType item) { if (item == RendererType.Automatic && automaticRendererInUse) - return $"{base.GenerateItemText(item)} ({hostResolvedRenderer})"; + return LocalisableString.Interpolate($"{base.GenerateItemText(item)} ({hostResolvedRenderer.GetDescription()})"); return base.GenerateItemText(item); } From f3c174a7f2d5538d38daa4293c86677a1e324272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 26 Mar 2023 13:52:26 +0200 Subject: [PATCH 0415/1400] Fix test errors due to missing dependencies --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index f9127fcd9a..ca21b15ff7 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private bool automaticRendererInUse; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDialogOverlay dialogOverlay, OsuGame game, GameHost host) + private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, IDialogOverlay? dialogOverlay, OsuGame? game, GameHost host) { var renderer = config.GetBindable(FrameworkSetting.Renderer); automaticRendererInUse = renderer.Value == RendererType.Automatic; @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (r.NewValue == RendererType.Automatic && automaticRendererInUse) return; - dialogOverlay.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, game.AttemptExit, () => + dialogOverlay?.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, () => game?.AttemptExit(), () => { renderer.Value = r.OldValue; })); From 292486c25ac65f9ef3c7b92a77699bd773fde531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 26 Mar 2023 14:35:00 +0200 Subject: [PATCH 0416/1400] Use more resilient restore method --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index ca21b15ff7..a4b0feb8bf 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -69,7 +69,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics dialogOverlay?.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, () => game?.AttemptExit(), () => { - renderer.Value = r.OldValue; + renderer.Value = automaticRendererInUse ? RendererType.Automatic : host.ResolvedRenderer; })); }); From 898717231b333d744f5adb94263cc1faa466ae45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2023 02:00:09 +0900 Subject: [PATCH 0417/1400] Hide vulkan renderer option for now We'll bring it back when it's more stable. --- .../Overlays/Settings/Sections/Graphics/RendererSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index a4b0feb8bf..a1f728ca87 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = GraphicsSettingsStrings.Renderer, Current = renderer, - Items = host.GetPreferredRenderersForCurrentPlatform().OrderBy(t => t), + Items = host.GetPreferredRenderersForCurrentPlatform().OrderBy(t => t).Where(t => t != RendererType.Vulkan), Keywords = new[] { @"compatibility", @"directx" }, }, // TODO: this needs to be a custom dropdown at some point From 6924dc5c5066e761e00822c47a62f9999dbc69b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2023 02:16:33 +0900 Subject: [PATCH 0418/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index bc382d8f97..927d66d93f 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 16f780d034..3de022e88d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 5d90119233..eb7ba24336 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 3e0bbb24326ee0d0b4c6dae72ea86d423dc47bed Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Mar 2023 16:03:21 -0700 Subject: [PATCH 0419/1400] Fix select beatmap button not highlighting when creating a multiplayer room using keyboard --- .../Match/MultiplayerMatchSettingsOverlay.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 207b9c378b..66acd6d1b0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -73,11 +73,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private OsuSpriteText typeLabel = null!; private LoadingLayer loadingLayer = null!; - public void SelectBeatmap() - { - if (matchSubScreen.IsCurrentScreen()) - matchSubScreen.Push(new MultiplayerMatchSongSelect(matchSubScreen.Room)); - } + public void SelectBeatmap() => selectBeatmapButton.TriggerClick(); [Resolved] private MultiplayerMatchSubScreen matchSubScreen { get; set; } = null!; @@ -97,6 +93,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match private IDisposable? applyingSettingsOperation; private Drawable playlistContainer = null!; private DrawableRoomPlaylist drawablePlaylist = null!; + private RoundedButton selectBeatmapButton = null!; public MatchSettings(Room room) { @@ -275,12 +272,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match RelativeSizeAxes = Axes.X, Height = DrawableRoomPlaylistItem.HEIGHT }, - new RoundedButton + selectBeatmapButton = new RoundedButton { RelativeSizeAxes = Axes.X, Height = 40, Text = "Select beatmap", - Action = SelectBeatmap + Action = () => + { + if (matchSubScreen.IsCurrentScreen()) + matchSubScreen.Push(new MultiplayerMatchSongSelect(matchSubScreen.Room)); + } } } } From 76a6f97fbb13aeb163818c1baed19422c30620be Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Mar 2023 17:32:03 -0700 Subject: [PATCH 0420/1400] Fix wrong definition of a beatmap in first run setup --- osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs b/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs index 3a7fe4bb12..d822f4976f 100644 --- a/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs +++ b/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs @@ -15,9 +15,9 @@ namespace osu.Game.Localisation public static LocalisableString Header => new TranslatableString(getKey(@"header"), @"Obtaining Beatmaps"); /// - /// ""Beatmaps" are what we call playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection." + /// ""Beatmaps" are what we call a set of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection." /// - public static LocalisableString Description => new TranslatableString(getKey(@"description"), @"""Beatmaps"" are what we call playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection."); + public static LocalisableString Description => new TranslatableString(getKey(@"description"), @"""Beatmaps"" are what we call a set of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection."); /// /// "If you are a new player, we recommend playing through the tutorial to get accustomed to the gameplay." From 8b30c67580f34dd8375d473e4fa469b928339088 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 26 Mar 2023 18:01:48 -0700 Subject: [PATCH 0421/1400] Fix incorrect song select matching label by showing both beatmap and difficulty count for less ambiguity --- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 ++++++- osu.Game/Screens/Select/SongSelect.cs | 9 ++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 68d3247275..dd3f13373d 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -64,7 +64,12 @@ namespace osu.Game.Screens.Select /// /// The total count of non-filtered beatmaps displayed. /// - public int CountDisplayed => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.Beatmaps.Count(b => !b.Filtered.Value)); + public int CountDisplayedBeatmaps => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.Beatmaps.Count(b => !b.Filtered.Value)); + + /// + /// The total count of non-filtered beatmap sets displayed. + /// + public int CountDisplayedSets => beatmapSets.Count(s => !s.Filtered.Value); /// /// The currently selected beatmap set. diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index c5e914b461..7191ff7c2a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using Humanizer; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -861,11 +862,9 @@ namespace osu.Game.Screens.Select private void updateVisibleBeatmapCount() { - FilterControl.InformationalText = Carousel.CountDisplayed == 1 - // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 - // but also in this case we want support for formatting a number within a string). - ? $"{Carousel.CountDisplayed:#,0} matching beatmap" - : $"{Carousel.CountDisplayed:#,0} matching beatmaps"; + // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 + // but also in this case we want support for formatting a number within a string). + FilterControl.InformationalText = $"{"matching beatmap".ToQuantity(Carousel.CountDisplayedSets, "#,0")} ({"difficulty".ToQuantity(Carousel.CountDisplayedBeatmaps, "#,0")})"; } private bool boundLocalBindables; From b065689cf89b0771c7d117d67c36f9400942d3d7 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 27 Mar 2023 23:04:45 +0900 Subject: [PATCH 0422/1400] Limit the area of popover to DrawableChannel popover may be blocked by textBar --- osu.Game/Overlays/ChatOverlay.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 332ffa110a..96dbfe31f3 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -123,7 +123,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Width = side_bar_width, }, - new PopoverContainer + new Container { RelativeSizeAxes = Axes.Both, Anchor = Anchor.TopRight, @@ -135,9 +135,13 @@ namespace osu.Game.Overlays }, Children = new Drawable[] { - currentChannelContainer = new Container + new PopoverContainer { RelativeSizeAxes = Axes.Both, + Child = currentChannelContainer = new Container + { + RelativeSizeAxes = Axes.Both, + } }, loading = new LoadingLayer(true), channelListing = new ChannelListing From 3d032d0024bec4aa11c52725476025c92dbb9452 Mon Sep 17 00:00:00 2001 From: Mohammed Keyvanzadeh Date: Mon, 27 Mar 2023 18:10:32 +0330 Subject: [PATCH 0423/1400] github: update workflows and make tweaks - Update the GitHub Actions workflows to their latest versions. - Replace the usage of the deprecated `set-output` command with the new recommended way to set the output. - Format the YAML files. --- .github/ISSUE_TEMPLATE/config.yml | 19 +++--- .github/dependabot.yml | 88 ++++++++++++++-------------- .github/workflows/ci.yml | 46 +++++++-------- .github/workflows/diffcalc.yml | 29 +++++---- .github/workflows/report-nunit.yml | 23 ++++---- .github/workflows/sentry-release.yml | 4 +- 6 files changed, 104 insertions(+), 105 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 47a6a4c3d3..3f76831a81 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,12 +1,11 @@ blank_issues_enabled: false contact_links: - - name: Help - url: https://github.com/ppy/osu/discussions/categories/q-a - about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section! - - name: Suggestions or feature request - url: https://github.com/ppy/osu/discussions/categories/ideas - about: Got something you think should change or be added? Search for or start a new discussion! - - name: osu!stable issues - url: https://github.com/ppy/osu-stable-issues - about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support. - + - name: Help + url: https://github.com/ppy/osu/discussions/categories/q-a + about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section! + - name: Suggestions or feature request + url: https://github.com/ppy/osu/discussions/categories/ideas + about: Got something you think should change or be added? Search for or start a new discussion! + - name: osu!stable issues + url: https://github.com/ppy/osu-stable-issues + about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 814fc81f51..ed1c3cf658 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,46 +1,46 @@ version: 2 updates: -- package-ecosystem: nuget - directory: "/" - schedule: - interval: monthly - time: "17:00" - open-pull-requests-limit: 0 # disabled until https://github.com/dependabot/dependabot-core/issues/369 is resolved. - ignore: - - dependency-name: Microsoft.EntityFrameworkCore.Design - versions: - - "> 2.2.6" - - dependency-name: Microsoft.EntityFrameworkCore.Sqlite - versions: - - "> 2.2.6" - - dependency-name: Microsoft.EntityFrameworkCore.Sqlite.Core - versions: - - "> 2.2.6" - - dependency-name: Microsoft.Extensions.DependencyInjection - versions: - - ">= 5.a, < 6" - - dependency-name: NUnit3TestAdapter - versions: - - ">= 3.16.a, < 3.17" - - dependency-name: Microsoft.NET.Test.Sdk - versions: - - 16.9.1 - - dependency-name: Microsoft.Extensions.DependencyInjection - versions: - - 3.1.11 - - 3.1.12 - - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson - versions: - - 3.1.11 - - dependency-name: Microsoft.NETCore.Targets - versions: - - 5.0.0 - - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack - versions: - - 5.0.2 - - dependency-name: NUnit - versions: - - 3.13.1 - - dependency-name: Microsoft.AspNetCore.SignalR.Client - versions: - - 3.1.11 + - package-ecosystem: nuget + directory: "/" + schedule: + interval: monthly + time: "17:00" + open-pull-requests-limit: 0 # disabled until https://github.com/dependabot/dependabot-core/issues/369 is resolved. + ignore: + - dependency-name: Microsoft.EntityFrameworkCore.Design + versions: + - "> 2.2.6" + - dependency-name: Microsoft.EntityFrameworkCore.Sqlite + versions: + - "> 2.2.6" + - dependency-name: Microsoft.EntityFrameworkCore.Sqlite.Core + versions: + - "> 2.2.6" + - dependency-name: Microsoft.Extensions.DependencyInjection + versions: + - ">= 5.a, < 6" + - dependency-name: NUnit3TestAdapter + versions: + - ">= 3.16.a, < 3.17" + - dependency-name: Microsoft.NET.Test.Sdk + versions: + - 16.9.1 + - dependency-name: Microsoft.Extensions.DependencyInjection + versions: + - 3.1.11 + - 3.1.12 + - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson + versions: + - 3.1.11 + - dependency-name: Microsoft.NETCore.Targets + versions: + - 5.0.0 + - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack + versions: + - 5.0.2 + - dependency-name: NUnit + versions: + - 3.13.1 + - dependency-name: Microsoft.AspNetCore.SignalR.Client + versions: + - 3.1.11 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c11f91994..742b428d1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,17 +13,17 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 # FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side. # https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e - name: Install .NET 3.1.x LTS - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "3.1.x" - name: Install .NET 6.0.x - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "6.0.x" @@ -59,28 +59,28 @@ jobs: run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN - name: NVika - run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors + run: dotnet nvika parsereport "${{ github.workspace }}/inspectcodereport.xml" --treatwarningsaserrors test: name: Test - runs-on: ${{matrix.os.fullname}} + runs-on: ${{ matrix.os.fullname }} env: - OSU_EXECUTION_MODE: ${{matrix.threadingMode}} + OSU_EXECUTION_MODE: ${{ matrix.threadingMode }} strategy: - fail-fast: false - matrix: - os: - - { prettyname: Windows, fullname: windows-latest } - - { prettyname: macOS, fullname: macos-latest } - - { prettyname: Linux, fullname: ubuntu-latest } - threadingMode: ['SingleThread', 'MultiThreaded'] + fail-fast: false + matrix: + os: + - { prettyname: Windows, fullname: windows-latest } + - { prettyname: macOS, fullname: macos-latest } + - { prettyname: Linux, fullname: ubuntu-latest } + threadingMode: ["SingleThread", "MultiThreaded"] timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install .NET 6.0.x - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "6.0.x" @@ -88,17 +88,17 @@ jobs: run: dotnet build -c Debug -warnaserror osu.Desktop.slnf - name: Test - run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" -- NUnit.ConsoleOut=0 + run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }}.trx" -- NUnit.ConsoleOut=0 shell: pwsh # Attempt to upload results even if test fails. # https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#always - name: Upload Test Results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: ${{ always() }} with: - name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} - path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx + name: osu-test-results-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }} + path: ${{ github.workspace }}/TestResults/TestResults-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }}.trx build-only-android: name: Build only (Android) @@ -106,10 +106,10 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install .NET 6.0.x - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "6.0.x" @@ -125,10 +125,10 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install .NET 6.0.x - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "6.0.x" diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index 9e11ab6663..b213d76794 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -2,12 +2,11 @@ # Usage: # !pp check 0 | Runs only the osu! ruleset. # !pp check 0 2 | Runs only the osu! and catch rulesets. -# name: Difficulty Calculation on: issue_comment: - types: [ created ] + types: [created] env: CONCURRENCY: 4 @@ -48,8 +47,8 @@ jobs: CONTINUE="no" fi - echo "::set-output name=continue::${CONTINUE}" - echo "::set-output name=matrix::${MATRIX_JSON}" + echo "continue=${CONTINUE}" >> $GITHUB_OUTPUT + echo "matrix=${MATRIX_JSON}" >> $GITHUB_OUTPUT diffcalc: name: Run runs-on: self-hosted @@ -80,34 +79,34 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo "::set-output name=branchname::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')" - echo "::set-output name=repo::$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.repo.full_name' | sed 's/\"//g')" + echo "branchname=$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')" >> $GITHUB_OUTPUT + echo "repo=$(curl -H "Authorization: token ${GITHUB_TOKEN}" ${{ github.event.issue.pull_request.url }} | jq '.head.repo.full_name' | sed 's/\"//g')" >> $GITHUB_OUTPUT # Checkout osu - name: Checkout osu (master) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: - path: 'master/osu' + path: "master/osu" - name: Checkout osu (pr) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: - path: 'pr/osu' + path: "pr/osu" repository: ${{ steps.upstreambranch.outputs.repo }} ref: ${{ steps.upstreambranch.outputs.branchname }} - name: Checkout osu-difficulty-calculator (master) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: ppy/osu-difficulty-calculator - path: 'master/osu-difficulty-calculator' + path: "master/osu-difficulty-calculator" - name: Checkout osu-difficulty-calculator (pr) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: ppy/osu-difficulty-calculator - path: 'pr/osu-difficulty-calculator' + path: "pr/osu-difficulty-calculator" - name: Install .NET 5.0.x - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v3 with: dotnet-version: "5.0.x" diff --git a/.github/workflows/report-nunit.yml b/.github/workflows/report-nunit.yml index 99e39f6f56..fee10aa487 100644 --- a/.github/workflows/report-nunit.yml +++ b/.github/workflows/report-nunit.yml @@ -2,6 +2,7 @@ # See: # * https://github.com/dorny/test-reporter#recommended-setup-for-public-repositories # * https://docs.github.com/en/actions/reference/authentication-in-a-workflow#permissions-for-the-github_token + name: Annotate CI run with test results on: workflow_run: @@ -18,21 +19,21 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion != 'cancelled' }} strategy: - fail-fast: false - matrix: - os: - - { prettyname: Windows } - - { prettyname: macOS } - - { prettyname: Linux } - threadingMode: ['SingleThread', 'MultiThreaded'] + fail-fast: false + matrix: + os: + - { prettyname: Windows } + - { prettyname: macOS } + - { prettyname: Linux } + threadingMode: ["SingleThread", "MultiThreaded"] timeout-minutes: 5 steps: - name: Annotate CI run with test results uses: dorny/test-reporter@v1.6.0 with: - artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} - name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}}) + artifact: osu-test-results-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }} + name: Test Results (${{ matrix.os.prettyname }}, ${{ matrix.threadingMode }}) path: "*.trx" reporter: dotnet-trx - list-suites: 'failed' - list-tests: 'failed' + list-suites: "failed" + list-tests: "failed" diff --git a/.github/workflows/sentry-release.yml b/.github/workflows/sentry-release.yml index cce3f23e5f..001a63cc64 100644 --- a/.github/workflows/sentry-release.yml +++ b/.github/workflows/sentry-release.yml @@ -3,7 +3,7 @@ name: Add Release to Sentry on: push: tags: - - '*' + - "*" permissions: contents: read # to fetch code (actions/checkout) @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 From 433f9e53679f4595cf1b9b42da5e713981dcc95d Mon Sep 17 00:00:00 2001 From: Mohammed Keyvanzadeh Date: Mon, 27 Mar 2023 18:37:01 +0330 Subject: [PATCH 0424/1400] fixup! revert formatting changes --- .github/ISSUE_TEMPLATE/config.yml | 19 +++--- .github/dependabot.yml | 88 ++++++++++++++-------------- .github/workflows/ci.yml | 26 ++++---- .github/workflows/diffcalc.yml | 11 ++-- .github/workflows/report-nunit.yml | 23 ++++---- .github/workflows/sentry-release.yml | 2 +- 6 files changed, 85 insertions(+), 84 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3f76831a81..47a6a4c3d3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,12 @@ blank_issues_enabled: false contact_links: - - name: Help - url: https://github.com/ppy/osu/discussions/categories/q-a - about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section! - - name: Suggestions or feature request - url: https://github.com/ppy/osu/discussions/categories/ideas - about: Got something you think should change or be added? Search for or start a new discussion! - - name: osu!stable issues - url: https://github.com/ppy/osu-stable-issues - about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support. + - name: Help + url: https://github.com/ppy/osu/discussions/categories/q-a + about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section! + - name: Suggestions or feature request + url: https://github.com/ppy/osu/discussions/categories/ideas + about: Got something you think should change or be added? Search for or start a new discussion! + - name: osu!stable issues + url: https://github.com/ppy/osu-stable-issues + about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support. + diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ed1c3cf658..814fc81f51 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,46 +1,46 @@ version: 2 updates: - - package-ecosystem: nuget - directory: "/" - schedule: - interval: monthly - time: "17:00" - open-pull-requests-limit: 0 # disabled until https://github.com/dependabot/dependabot-core/issues/369 is resolved. - ignore: - - dependency-name: Microsoft.EntityFrameworkCore.Design - versions: - - "> 2.2.6" - - dependency-name: Microsoft.EntityFrameworkCore.Sqlite - versions: - - "> 2.2.6" - - dependency-name: Microsoft.EntityFrameworkCore.Sqlite.Core - versions: - - "> 2.2.6" - - dependency-name: Microsoft.Extensions.DependencyInjection - versions: - - ">= 5.a, < 6" - - dependency-name: NUnit3TestAdapter - versions: - - ">= 3.16.a, < 3.17" - - dependency-name: Microsoft.NET.Test.Sdk - versions: - - 16.9.1 - - dependency-name: Microsoft.Extensions.DependencyInjection - versions: - - 3.1.11 - - 3.1.12 - - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson - versions: - - 3.1.11 - - dependency-name: Microsoft.NETCore.Targets - versions: - - 5.0.0 - - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack - versions: - - 5.0.2 - - dependency-name: NUnit - versions: - - 3.13.1 - - dependency-name: Microsoft.AspNetCore.SignalR.Client - versions: - - 3.1.11 +- package-ecosystem: nuget + directory: "/" + schedule: + interval: monthly + time: "17:00" + open-pull-requests-limit: 0 # disabled until https://github.com/dependabot/dependabot-core/issues/369 is resolved. + ignore: + - dependency-name: Microsoft.EntityFrameworkCore.Design + versions: + - "> 2.2.6" + - dependency-name: Microsoft.EntityFrameworkCore.Sqlite + versions: + - "> 2.2.6" + - dependency-name: Microsoft.EntityFrameworkCore.Sqlite.Core + versions: + - "> 2.2.6" + - dependency-name: Microsoft.Extensions.DependencyInjection + versions: + - ">= 5.a, < 6" + - dependency-name: NUnit3TestAdapter + versions: + - ">= 3.16.a, < 3.17" + - dependency-name: Microsoft.NET.Test.Sdk + versions: + - 16.9.1 + - dependency-name: Microsoft.Extensions.DependencyInjection + versions: + - 3.1.11 + - 3.1.12 + - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson + versions: + - 3.1.11 + - dependency-name: Microsoft.NETCore.Targets + versions: + - 5.0.0 + - dependency-name: Microsoft.AspNetCore.SignalR.Protocols.MessagePack + versions: + - 5.0.2 + - dependency-name: NUnit + versions: + - 3.13.1 + - dependency-name: Microsoft.AspNetCore.SignalR.Client + versions: + - 3.1.11 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 742b428d1d..e60e0a39ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,21 +59,21 @@ jobs: run: dotnet jb inspectcode $(pwd)/osu.Desktop.slnf --no-build --output="inspectcodereport.xml" --caches-home="inspectcode" --verbosity=WARN - name: NVika - run: dotnet nvika parsereport "${{ github.workspace }}/inspectcodereport.xml" --treatwarningsaserrors + run: dotnet nvika parsereport "${{github.workspace}}/inspectcodereport.xml" --treatwarningsaserrors test: name: Test - runs-on: ${{ matrix.os.fullname }} + runs-on: ${{matrix.os.fullname}} env: - OSU_EXECUTION_MODE: ${{ matrix.threadingMode }} + OSU_EXECUTION_MODE: ${{matrix.threadingMode}} strategy: - fail-fast: false - matrix: - os: - - { prettyname: Windows, fullname: windows-latest } - - { prettyname: macOS, fullname: macos-latest } - - { prettyname: Linux, fullname: ubuntu-latest } - threadingMode: ["SingleThread", "MultiThreaded"] + fail-fast: false + matrix: + os: + - { prettyname: Windows, fullname: windows-latest } + - { prettyname: macOS, fullname: macos-latest } + - { prettyname: Linux, fullname: ubuntu-latest } + threadingMode: ['SingleThread', 'MultiThreaded'] timeout-minutes: 60 steps: - name: Checkout @@ -88,7 +88,7 @@ jobs: run: dotnet build -c Debug -warnaserror osu.Desktop.slnf - name: Test - run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }}.trx" -- NUnit.ConsoleOut=0 + run: dotnet test $pwd/**/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx" -- NUnit.ConsoleOut=0 shell: pwsh # Attempt to upload results even if test fails. @@ -97,8 +97,8 @@ jobs: uses: actions/upload-artifact@v3 if: ${{ always() }} with: - name: osu-test-results-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }} - path: ${{ github.workspace }}/TestResults/TestResults-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }}.trx + name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} + path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx build-only-android: name: Build only (Android) diff --git a/.github/workflows/diffcalc.yml b/.github/workflows/diffcalc.yml index b213d76794..2c6ec17e18 100644 --- a/.github/workflows/diffcalc.yml +++ b/.github/workflows/diffcalc.yml @@ -2,11 +2,12 @@ # Usage: # !pp check 0 | Runs only the osu! ruleset. # !pp check 0 2 | Runs only the osu! and catch rulesets. +# name: Difficulty Calculation on: issue_comment: - types: [created] + types: [ created ] env: CONCURRENCY: 4 @@ -86,11 +87,11 @@ jobs: - name: Checkout osu (master) uses: actions/checkout@v3 with: - path: "master/osu" + path: 'master/osu' - name: Checkout osu (pr) uses: actions/checkout@v3 with: - path: "pr/osu" + path: 'pr/osu' repository: ${{ steps.upstreambranch.outputs.repo }} ref: ${{ steps.upstreambranch.outputs.branchname }} @@ -98,12 +99,12 @@ jobs: uses: actions/checkout@v3 with: repository: ppy/osu-difficulty-calculator - path: "master/osu-difficulty-calculator" + path: 'master/osu-difficulty-calculator' - name: Checkout osu-difficulty-calculator (pr) uses: actions/checkout@v3 with: repository: ppy/osu-difficulty-calculator - path: "pr/osu-difficulty-calculator" + path: 'pr/osu-difficulty-calculator' - name: Install .NET 5.0.x uses: actions/setup-dotnet@v3 diff --git a/.github/workflows/report-nunit.yml b/.github/workflows/report-nunit.yml index fee10aa487..99e39f6f56 100644 --- a/.github/workflows/report-nunit.yml +++ b/.github/workflows/report-nunit.yml @@ -2,7 +2,6 @@ # See: # * https://github.com/dorny/test-reporter#recommended-setup-for-public-repositories # * https://docs.github.com/en/actions/reference/authentication-in-a-workflow#permissions-for-the-github_token - name: Annotate CI run with test results on: workflow_run: @@ -19,21 +18,21 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion != 'cancelled' }} strategy: - fail-fast: false - matrix: - os: - - { prettyname: Windows } - - { prettyname: macOS } - - { prettyname: Linux } - threadingMode: ["SingleThread", "MultiThreaded"] + fail-fast: false + matrix: + os: + - { prettyname: Windows } + - { prettyname: macOS } + - { prettyname: Linux } + threadingMode: ['SingleThread', 'MultiThreaded'] timeout-minutes: 5 steps: - name: Annotate CI run with test results uses: dorny/test-reporter@v1.6.0 with: - artifact: osu-test-results-${{ matrix.os.prettyname }}-${{ matrix.threadingMode }} - name: Test Results (${{ matrix.os.prettyname }}, ${{ matrix.threadingMode }}) + artifact: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}} + name: Test Results (${{matrix.os.prettyname}}, ${{matrix.threadingMode}}) path: "*.trx" reporter: dotnet-trx - list-suites: "failed" - list-tests: "failed" + list-suites: 'failed' + list-tests: 'failed' diff --git a/.github/workflows/sentry-release.yml b/.github/workflows/sentry-release.yml index 001a63cc64..ff4165c414 100644 --- a/.github/workflows/sentry-release.yml +++ b/.github/workflows/sentry-release.yml @@ -3,7 +3,7 @@ name: Add Release to Sentry on: push: tags: - - "*" + - '*' permissions: contents: read # to fetch code (actions/checkout) From 9426633a05c04c640666463fde89b20f07e96595 Mon Sep 17 00:00:00 2001 From: rrex971 <75212090+rrex971@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:39:13 +0530 Subject: [PATCH 0425/1400] Allow AR and CS values below 1.0 for Catch the Beat Difficulty Adjustment mod --- osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs index e59a0a0431..6efb415880 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDifficultyAdjust.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Mods public DifficultyBindable CircleSize { get; } = new DifficultyBindable { Precision = 0.1f, - MinValue = 1, + MinValue = 0, MaxValue = 10, ExtendedMaxValue = 11, ReadCurrentFromDifficulty = diff => diff.CircleSize, @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Mods public DifficultyBindable ApproachRate { get; } = new DifficultyBindable { Precision = 0.1f, - MinValue = 1, + MinValue = 0, MaxValue = 10, ExtendedMaxValue = 11, ReadCurrentFromDifficulty = diff => diff.ApproachRate, From f31e77dce5317b3beb82838e678c183536deb6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 27 Mar 2023 18:08:06 +0200 Subject: [PATCH 0426/1400] Add direction switching to `TestSceneManiaPlayer` To test upscroll easier, and with all parts in conjunction. `ManiaSkinnableTestScene`s already had the capability to switch directions, but they did not show all parts together, which meant regressions were missed. --- .../TestSceneManiaPlayer.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs index 98046320cb..4e50fd924c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs @@ -3,6 +3,9 @@ #nullable disable +using osu.Framework.Extensions.ObjectExtensions; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -10,5 +13,19 @@ namespace osu.Game.Rulesets.Mania.Tests public partial class TestSceneManiaPlayer : PlayerTestScene { protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset(); + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("change direction to down", () => changeDirectionTo(ManiaScrollingDirection.Down)); + AddStep("change direction to up", () => changeDirectionTo(ManiaScrollingDirection.Up)); + } + + private void changeDirectionTo(ManiaScrollingDirection direction) + { + var rulesetConfig = (ManiaRulesetConfigManager)RulesetConfigs.GetConfigFor(new ManiaRuleset()).AsNonNull(); + rulesetConfig.SetValue(ManiaRulesetSetting.ScrollDirection, direction); + } } } From c54934cb45f361daaacbac7059b8139c655c6901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 27 Mar 2023 18:15:01 +0200 Subject: [PATCH 0427/1400] Fix hit lighting misalignment on argon skin with upscroll --- .../Skinning/Argon/ArgonHitExplosion.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs index 8e27b4abd7..fb38b536dc 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs @@ -43,8 +43,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { largeFaint = new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Height = ArgonNotePiece.NOTE_ACCENT_RATIO, Masking = true, @@ -78,16 +76,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private void onDirectionChanged(ValueChangedEvent direction) { - if (direction.NewValue == ScrollingDirection.Up) - { - Anchor = Anchor.TopCentre; - Y = ArgonNotePiece.NOTE_HEIGHT / 2; - } - else - { - Anchor = Anchor.BottomCentre; - Y = -ArgonNotePiece.NOTE_HEIGHT / 2; - } + Anchor = largeFaint.Anchor = largeFaint.Origin = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Y = direction.NewValue == ScrollingDirection.Up ? ArgonNotePiece.NOTE_HEIGHT / 2 : -ArgonNotePiece.NOTE_HEIGHT / 2; } public void Animate(JudgementResult result) From 2b525b626c1e7a46c7402edbb4def3fa6d6a9581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 28 Mar 2023 06:22:00 +0200 Subject: [PATCH 0428/1400] Revert to previous conditional style --- .../Skinning/Argon/ArgonHitExplosion.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs index fb38b536dc..d490d3f944 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHitExplosion.cs @@ -76,8 +76,20 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon private void onDirectionChanged(ValueChangedEvent direction) { - Anchor = largeFaint.Anchor = largeFaint.Origin = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; - Y = direction.NewValue == ScrollingDirection.Up ? ArgonNotePiece.NOTE_HEIGHT / 2 : -ArgonNotePiece.NOTE_HEIGHT / 2; + if (direction.NewValue == ScrollingDirection.Up) + { + Anchor = Anchor.TopCentre; + largeFaint.Anchor = Anchor.TopCentre; + largeFaint.Origin = Anchor.TopCentre; + Y = ArgonNotePiece.NOTE_HEIGHT / 2; + } + else + { + Anchor = Anchor.BottomCentre; + largeFaint.Anchor = Anchor.BottomCentre; + largeFaint.Origin = Anchor.BottomCentre; + Y = -ArgonNotePiece.NOTE_HEIGHT / 2; + } } public void Animate(JudgementResult result) From c742b3f0a8a10854ba73fc59c0f5a521c445a968 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2023 14:15:19 +0900 Subject: [PATCH 0429/1400] Update `DrawableRulesetDependencies` xmldoc to read more correctly --- osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index 96b02ee4dc..5c031c5f08 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -25,21 +25,28 @@ namespace osu.Game.Rulesets.UI /// /// The texture store to be used for the ruleset. /// + /// + /// Reads textures from the "Textures" folder in ruleset resources. + /// If not available locally, lookups will fallback to the global texture store. + /// public TextureStore TextureStore { get; } /// /// The sample store to be used for the ruleset. /// /// - /// This is the local sample store pointing to the ruleset sample resources, - /// the cached sample store () retrieves from - /// this store and falls back to the parent store if this store doesn't have the requested sample. + /// Reads samples from the "Samples" folder in ruleset resources. + /// If not available locally, lookups will fallback to the global sample store. /// public ISampleStore SampleStore { get; } /// /// The shader manager to be used for the ruleset. /// + /// + /// Reads shaders from the "Shaders" folder in ruleset resources. + /// If not available locally, lookups will fallback to the global shader manager. + /// public ShaderManager ShaderManager { get; } /// From 5dfac02b11a3c5c70ee84f6787d5e355d4b1b7ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2023 14:15:38 +0900 Subject: [PATCH 0430/1400] Preload triangle shader on startup --- osu.Game/Screens/Loader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index b70c1f7ddf..bee6207a35 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -130,6 +130,10 @@ namespace osu.Game.Screens loadTargets.Add(manager.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE)); + loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder")); + + loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); + loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); } From 0d77ec013a936fd77b852837b7007229028f34bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2023 14:53:08 +0900 Subject: [PATCH 0431/1400] Fix ruleset-local shader manager not correctly falling back to existing cached shaders --- .../UI/DrawableRulesetDependencies.cs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index 5c031c5f08..e6ee770e19 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -68,8 +68,7 @@ namespace osu.Game.Rulesets.UI SampleStore.PlaybackConcurrency = OsuGameBase.SAMPLE_CONCURRENCY; CacheAs(SampleStore = new FallbackSampleStore(SampleStore, parent.Get())); - ShaderManager = new ShaderManager(host.Renderer, new NamespacedResourceStore(resources, @"Shaders")); - CacheAs(ShaderManager = new FallbackShaderManager(host.Renderer, ShaderManager, parent.Get())); + CacheAs(ShaderManager = new RulesetShaderManager(host.Renderer, new NamespacedResourceStore(resources, @"Shaders"), parent.Get())); RulesetConfigManager = parent.Get().GetConfigFor(ruleset); if (RulesetConfigManager != null) @@ -197,24 +196,27 @@ namespace osu.Game.Rulesets.UI } } - private class FallbackShaderManager : ShaderManager + private class RulesetShaderManager : ShaderManager { - private readonly ShaderManager primary; - private readonly ShaderManager fallback; + private readonly ShaderManager parent; - public FallbackShaderManager(IRenderer renderer, ShaderManager primary, ShaderManager fallback) - : base(renderer, new ResourceStore()) + public RulesetShaderManager(IRenderer renderer, NamespacedResourceStore rulesetResources, ShaderManager parent) + : base(renderer, rulesetResources) { - this.primary = primary; - this.fallback = fallback; + this.parent = parent; } - public override byte[]? LoadRaw(string name) => primary.LoadRaw(name) ?? fallback.LoadRaw(name); - - protected override void Dispose(bool disposing) + public override IShader Load(string vertex, string fragment) { - base.Dispose(disposing); - if (primary.IsNotNull()) primary.Dispose(); + try + { + return base.Load(vertex, fragment); + } + catch + { + // Shader lookup is very non-standard. Rather than returning null on missing shaders, exceptions are thrown. + return parent.Load(vertex, fragment); + } } } } From 8c1df3c8d9d6c875d151f086035dc6b7d13ceb04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2023 15:38:19 +0900 Subject: [PATCH 0432/1400] Fix web account registration not bypassing the URL warning --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 2e20f83e9e..219cbe7eef 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -209,7 +209,7 @@ namespace osu.Game.Overlays.AccountCreation if (!string.IsNullOrEmpty(errors.Message)) passwordDescription.AddErrors(new[] { errors.Message }); - game.OpenUrlExternally($"{errors.Redirect}?username={usernameTextBox.Text}&email={emailTextBox.Text}"); + game.OpenUrlExternally($"{errors.Redirect}?username={usernameTextBox.Text}&email={emailTextBox.Text}", true); } } else From 45e3e3623b70c206a9889dd602186d895506d448 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2023 18:48:55 +0900 Subject: [PATCH 0433/1400] Fix spinners being selectable for too long after they fade in the editor The actual visual extension is only applied to `HitCircle`s (which does include slider start / end), and should not be applied to spinners in the first place. Addresses https://github.com/ppy/osu/discussions/22949. --- osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 3e161089cd..d6409279a4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints protected override bool AlwaysShowWhenSelected => true; protected override bool ShouldBeAlive => base.ShouldBeAlive - || (ShowHitMarkers.Value && editorClock.CurrentTime >= Item.StartTime && editorClock.CurrentTime - Item.GetEndTime() < HitCircleOverlapMarker.FADE_OUT_EXTENSION); + || (DrawableObject is not DrawableSpinner && ShowHitMarkers.Value && editorClock.CurrentTime >= Item.StartTime && editorClock.CurrentTime - Item.GetEndTime() < HitCircleOverlapMarker.FADE_OUT_EXTENSION); protected OsuSelectionBlueprint(T hitObject) : base(hitObject) From 31df626f0ebe022884f2b5bd2bce49898661ec1d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 28 Mar 2023 21:32:28 +0900 Subject: [PATCH 0434/1400] disable button when select other reason --- .../Graphics/UserInterfaceV2/ReportPopover.cs | 24 ++++++++++++------- osu.Game/Overlays/Chat/ReportChatPopover.cs | 6 ++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs index 44af108ab1..46006402ad 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs @@ -24,8 +24,6 @@ namespace osu.Game.Graphics.UserInterfaceV2 private OsuEnumDropdown reasonDropdown = null!; private OsuTextBox commentsTextBox = null!; private RoundedButton submitButton = null!; - - public bool CanSubmitEmptyReason = false; public LocalisableString Header; protected ReportPopover(LocalisableString headerString) @@ -102,13 +100,21 @@ namespace osu.Game.Graphics.UserInterfaceV2 } }; - if (!CanSubmitEmptyReason) - { - commentsTextBox.Current.BindValueChanged(e => - { - submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(e.NewValue); - }, true); - } + commentsTextBox.Current.BindValueChanged(_ => updateStatus()); + + reasonDropdown.Current.BindValueChanged(_ => updateStatus()); + + updateStatus(); + } + + private void updateStatus() + { + submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(commentsTextBox.Current.Value) || CheckCanSubmitEmptyComment(reasonDropdown.Current.Value); + } + + protected virtual bool CheckCanSubmitEmptyComment(T reason) + { + return false; } } } diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index 79c3922795..de5f3268b8 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -12,7 +12,11 @@ namespace osu.Game.Overlays.Chat public ReportChatPopover(APIUser? user) : base(ReportStrings.UserTitle(user?.Username ?? @"Someone")) { - CanSubmitEmptyReason = true; + } + + protected override bool CheckCanSubmitEmptyComment(ChatReportReason reason) + { + return reason != ChatReportReason.Other; } } } From f01247f1ab75dfd7f9dc81200a569b3f114b4296 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 28 Mar 2023 21:39:42 +0900 Subject: [PATCH 0435/1400] test --- .../Visual/Online/TestSceneChatOverlay.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 5845ba3783..faf48ef854 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -618,6 +618,12 @@ namespace osu.Game.Tests.Visual.Online AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); + AddStep("Set report reason to other", () => + { + var reason = this.ChildrenOfType>().Single(); + reason.Current.Value = ChatReportReason.Other; + }); + AddStep("Try to report", () => { var btn = this.ChildrenOfType().Single().ChildrenOfType().Single(); @@ -626,7 +632,21 @@ namespace osu.Game.Tests.Visual.Online }); AddWaitStep("Wait", 3); + AddAssert("Nothing happened", () => this.ChildrenOfType().Any()); + AddStep("Set report data", () => + { + var field = this.ChildrenOfType().Single().ChildrenOfType().Single(); + field.Current.Value = "test other"; + }); + AddStep("Try to report", () => + { + var btn = this.ChildrenOfType().Single().ChildrenOfType().Single(); + InputManager.MoveMouseTo(btn); + InputManager.Click(MouseButton.Left); + }); + + AddWaitStep("Wait", 3); AddAssert("Overlay closed", () => !this.ChildrenOfType().Any()); AddStep("Complete request", () => requestLock.Set()); AddUntilStep("Request sent", () => request != null); From 46ede27869efca77ec226081454cf682ad907a77 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 28 Mar 2023 22:24:05 +0900 Subject: [PATCH 0436/1400] add feature to adjust `ScalingContainer` background dim --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ .../Graphics/Containers/ScalingContainer.cs | 11 +++++++++-- .../Sections/Graphics/LayoutSettings.cs | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 70ad6bfc96..a06bfcc5f0 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -157,6 +157,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.Scaling, ScalingMode.Off); SetDefault(OsuSetting.SafeAreaConsiderations, true); + SetDefault(OsuSetting.ScalingMenuBackgroundDim, 0.9f, 0.5f, 1f); SetDefault(OsuSetting.ScalingSizeX, 0.8f, 0.2f, 1f); SetDefault(OsuSetting.ScalingSizeY, 0.8f, 0.2f, 1f); @@ -364,6 +365,7 @@ namespace osu.Game.Configuration ScalingPositionY, ScalingSizeX, ScalingSizeY, + ScalingMenuBackgroundDim, UIScale, IntroSequence, NotifyOnUsernameMentioned, diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index fb5c3e3b60..9c6830ce05 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -46,6 +46,8 @@ namespace osu.Game.Graphics.Containers private BackgroundScreenStack backgroundStack; + private Bindable scalingMenuBackgroundDim; + private RectangleF? customRect; private bool customRectIsRelativePosition; @@ -138,6 +140,9 @@ namespace osu.Game.Graphics.Containers safeAreaPadding = safeArea.SafeAreaPadding.GetBoundCopy(); safeAreaPadding.BindValueChanged(_ => Scheduler.AddOnce(updateSize)); + + scalingMenuBackgroundDim = config.GetBindable(OsuSetting.ScalingMenuBackgroundDim); + scalingMenuBackgroundDim.ValueChanged += _ => Scheduler.AddOnce(updateSize); } protected override void LoadComplete() @@ -148,7 +153,9 @@ namespace osu.Game.Graphics.Containers sizableContainer.FinishTransforms(); } - private bool requiresBackgroundVisible => (scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); + private bool requiresBackgroundVisible => (scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays) + && (sizeX.Value != 1 || sizeY.Value != 1) + && scalingMenuBackgroundDim.Value != 1f; private void updateSize() { @@ -161,7 +168,6 @@ namespace osu.Game.Graphics.Containers { AddInternal(backgroundStack = new BackgroundScreenStack { - Colour = OsuColour.Gray(0.1f), Alpha = 0, Depth = float.MaxValue }); @@ -170,6 +176,7 @@ namespace osu.Game.Graphics.Containers } backgroundStack.FadeIn(TRANSITION_DURATION); + backgroundStack.FadeColour(OsuColour.Gray(1.0f - scalingMenuBackgroundDim.Value), 800, Easing.OutQuint); } else backgroundStack?.FadeOut(TRANSITION_DURATION); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 6465d62ef0..6dbaf27afc 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -30,6 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics protected override LocalisableString Header => GraphicsSettingsStrings.LayoutHeader; private FillFlowContainer> scalingSettings = null!; + private SettingsSlider dimSlider = null!; private readonly Bindable currentDisplay = new Bindable(); private readonly IBindableList windowModes = new BindableList(); @@ -58,6 +59,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable scalingSizeX = null!; private Bindable scalingSizeY = null!; + private Bindable scalingBackgroundDim = null!; + private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -71,6 +74,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSizeY = osuConfig.GetBindable(OsuSetting.ScalingSizeY); scalingPositionX = osuConfig.GetBindable(OsuSetting.ScalingPositionX); scalingPositionY = osuConfig.GetBindable(OsuSetting.ScalingPositionY); + scalingBackgroundDim = osuConfig.GetBindable(OsuSetting.ScalingMenuBackgroundDim); if (window != null) { @@ -162,6 +166,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics KeyboardStep = 0.01f, DisplayAsPercentage = true }, + dimSlider = new SettingsSlider + { + LabelText = GameplaySettingsStrings.BackgroundDim, + Current = scalingBackgroundDim, + KeyboardStep = 0.01f, + DisplayAsPercentage = true + }, } }, }; @@ -219,6 +230,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None; scalingSettings.ForEach(s => { + if (s == dimSlider) + { + s.TransferValueOnCommit = false; + s.CanBeShown.Value = scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays; + return; + } + s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; }); From aad540629f4818f10310b56d5878c828196e7a80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 12:36:56 +0900 Subject: [PATCH 0437/1400] Remove duplicate load rule from `ShaderPrecompiler` --- osu.Game/Screens/Loader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index bee6207a35..372cfe748e 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -133,8 +133,6 @@ namespace osu.Game.Screens loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder")); loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); - - loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); } protected virtual bool AllLoaded => loadTargets.All(s => s.IsLoaded); From 9b45591c2f92ae4a2cd45329557187b043751b1b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 14:00:07 +0900 Subject: [PATCH 0438/1400] Add failing test coverage of saving failed replay causing progression to results --- .../Gameplay/TestSceneStoryboardWithOutro.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs index 0d88fb01a8..283866bef2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboardWithOutro.cs @@ -13,6 +13,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; @@ -106,6 +107,26 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); } + [Test] + public void TestSaveFailedReplayWithStoryboardEndedDoesNotProgress() + { + CreateTest(() => + { + AddStep("fail on first judgement", () => currentFailConditions = (_, _) => true); + AddStep("set storyboard duration to 0s", () => currentStoryboardDuration = 0); + }); + AddUntilStep("storyboard ends", () => Player.GameplayClockContainer.CurrentTime >= currentStoryboardDuration); + AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed); + + AddUntilStep("wait for fail overlay", () => Player.FailOverlay.State.Value == Visibility.Visible); + AddUntilStep("wait for button clickable", () => Player.ChildrenOfType().First().ChildrenOfType().First().Enabled.Value); + AddStep("click save button", () => Player.ChildrenOfType().First().ChildrenOfType().First().TriggerClick()); + + // Test a regression where importing the fail replay would cause progression to results screen in a failed state. + AddWaitStep("wait some", 10); + AddAssert("player is still current screen", () => Player.IsCurrentScreen()); + } + [Test] public void TestShowResultsFalse() { From a8bb2e33ac669b4c47b1c5b1e6b42c94f3a7bc32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 13:30:13 +0900 Subject: [PATCH 0439/1400] Ensure all preconditions are checked before progressing to results screen after storyboard ends --- osu.Game/Screens/Play/Player.cs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 45a671fb89..3976e5059b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -358,14 +358,10 @@ namespace osu.Game.Screens.Play ScoreProcessor.RevertResult(r); }; - DimmableStoryboard.HasStoryboardEnded.ValueChanged += storyboardEnded => - { - if (storyboardEnded.NewValue) - progressToResults(true); - }; + DimmableStoryboard.HasStoryboardEnded.ValueChanged += _ => scoreCompleted(); // Bind the judgement processors to ourselves - ScoreProcessor.HasCompleted.BindValueChanged(scoreCompletionChanged); + ScoreProcessor.HasCompleted.BindValueChanged(_ => scoreCompleted()); HealthProcessor.Failed += onFail; // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock, @@ -706,8 +702,7 @@ namespace osu.Game.Screens.Play /// /// Handles changes in player state which may progress the completion of gameplay / this screen's lifetime. /// - /// Thrown if this method is called more than once without changing state. - private void scoreCompletionChanged(ValueChangedEvent completed) + private void scoreCompleted() { // If this player instance is in the middle of an exit, don't attempt any kind of state update. if (!this.IsCurrentScreen()) @@ -718,7 +713,7 @@ namespace osu.Game.Screens.Play // Currently, even if this scenario is hit, prepareScoreForDisplay has already been queued (and potentially run). // In scenarios where rewinding is possible (replay, spectating) this is a non-issue as no submission/import work is done, // but it still doesn't feel right that this exists here. - if (!completed.NewValue) + if (!ScoreProcessor.HasCompleted.Value) { resultsDisplayDelegate?.Cancel(); resultsDisplayDelegate = null; @@ -742,12 +737,12 @@ namespace osu.Game.Screens.Play if (!Configuration.ShowResults) return; - bool storyboardHasOutro = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; + bool storyboardStillRunning = DimmableStoryboard.ContentDisplayed && !DimmableStoryboard.HasStoryboardEnded.Value; - if (storyboardHasOutro) + // If the current beatmap has a storyboard, this method will be called again on storyboard completion. + // Alternatively, the user may press the outro skip button, forcing immediate display of the results screen. + if (storyboardStillRunning) { - // if the current beatmap has a storyboard, the progression to results will be handled by the storyboard ending - // or the user pressing the skip outro button. skipOutroOverlay.Show(); return; } From 4dd0c2c7a5eb3b0d57fbed9bdf4acf1bacb439e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 14:11:56 +0900 Subject: [PATCH 0440/1400] Add assert ensuring we don't ever get to the results screen with an F rank Intentionally an assertion as I want tests to fail, but I don't want this to cause crashes for an end user if it does happen to occur. --- osu.Game/Screens/Play/Player.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3976e5059b..b8b3a8b5c0 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -788,6 +788,8 @@ namespace osu.Game.Screens.Play // This player instance may already be in the process of exiting. return; + Debug.Assert(ScoreProcessor.Rank.Value != ScoreRank.F); + this.Push(CreateResults(prepareScoreForDisplayTask.GetResultSafely())); }, Time.Current + delay, 50); From c7003434b2f1640e88443a536fac5b716f04bcbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 14:33:10 +0900 Subject: [PATCH 0441/1400] Fix localisation for audio device error containing incorrect newline escaping --- osu.Game/Localisation/NotificationsStrings.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Localisation/NotificationsStrings.cs b/osu.Game/Localisation/NotificationsStrings.cs index 6a9793b20c..5e2600bc50 100644 --- a/osu.Game/Localisation/NotificationsStrings.cs +++ b/osu.Game/Localisation/NotificationsStrings.cs @@ -50,16 +50,18 @@ namespace osu.Game.Localisation public static LocalisableString NoAutoplayMod => new TranslatableString(getKey(@"no_autoplay_mod"), @"The current ruleset doesn't have an autoplay mod available!"); /// - /// "osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting." + /// "osu! doesn't seem to be able to play audio correctly. + /// + /// Please try changing your audio device to a working setting." /// - public static LocalisableString AudioPlaybackIssue => new TranslatableString(getKey(@"audio_playback_issue"), - @"osu! doesn't seem to be able to play audio correctly.\n\nPlease try changing your audio device to a working setting."); + public static LocalisableString AudioPlaybackIssue => new TranslatableString(getKey(@"audio_playback_issue"), @"osu! doesn't seem to be able to play audio correctly. + +Please try changing your audio device to a working setting."); /// /// "The score overlay is currently disabled. You can toggle this by pressing {0}." /// - public static LocalisableString ScoreOverlayDisabled(LocalisableString arg0) => new TranslatableString(getKey(@"score_overlay_disabled"), - @"The score overlay is currently disabled. You can toggle this by pressing {0}.", arg0); + public static LocalisableString ScoreOverlayDisabled(LocalisableString arg0) => new TranslatableString(getKey(@"score_overlay_disabled"), @"The score overlay is currently disabled. You can toggle this by pressing {0}.", arg0); private static string getKey(string key) => $@"{prefix}:{key}"; } From 72c5c9848f8761c719ca1fa22ecc6f784019d0ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 14:44:42 +0900 Subject: [PATCH 0442/1400] Always use `LocalisableString` fallbacks when deploying debug and viewing english This allows changes to `xxxStrings.cs` files to immediately reflect in the UI, which is (at least for me) an expectation. --- osu.Game/Localisation/ResourceManagerLocalisationStore.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index d2ff783413..50a450c101 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Resources; using System.Threading; using System.Threading.Tasks; +using osu.Framework.Development; using osu.Framework.Localisation; namespace osu.Game.Localisation @@ -65,6 +66,11 @@ namespace osu.Game.Localisation if (manager == null) return null; + // When running a debug build and in viewing english culture, use the fallbacks rather than osu-resources baked strings. + // This is what a developer expects to see when making changes to `xxxStrings.cs` files. + if (DebugUtils.IsDebugBuild && EffectiveCulture.Name == @"en") + return null; + try { return manager.GetString(key, EffectiveCulture); From 836c884aaed7c97925a7c4f8279192a053ebb8fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2023 18:03:21 +0900 Subject: [PATCH 0443/1400] Fix circle-size based scale being applied twice to caught fruit Closes #22968. --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 1c52c092ec..ab754e51f7 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -136,6 +136,7 @@ namespace osu.Game.Rulesets.Catch.UI Origin = Anchor.TopCentre; Size = new Vector2(BASE_SIZE); + if (difficulty != null) Scale = calculateScale(difficulty); @@ -333,8 +334,11 @@ namespace osu.Game.Rulesets.Catch.UI base.Update(); var scaleFromDirection = new Vector2((int)VisualDirection, 1); + body.Scale = scaleFromDirection; - caughtObjectContainer.Scale = hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One; + // Inverse of catcher scale is applied here, as catcher gets scaled by circle size and so do the incoming fruit. + caughtObjectContainer.Scale = (1 / Scale.X) * (flipCatcherPlate ? scaleFromDirection : Vector2.One); + hitExplosionContainer.Scale = flipCatcherPlate ? scaleFromDirection : Vector2.One; // Correct overshooting. if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) || From e85c28031e2348f0f4e71eafe3d1fe13ba4305fc Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 29 Mar 2023 22:55:25 +0900 Subject: [PATCH 0444/1400] change weird name --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 +- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index a06bfcc5f0..1e7d3cf84f 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -157,7 +157,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.Scaling, ScalingMode.Off); SetDefault(OsuSetting.SafeAreaConsiderations, true); - SetDefault(OsuSetting.ScalingMenuBackgroundDim, 0.9f, 0.5f, 1f); + SetDefault(OsuSetting.ScalingBackgroundDim, 0.9f, 0.5f, 1f); SetDefault(OsuSetting.ScalingSizeX, 0.8f, 0.2f, 1f); SetDefault(OsuSetting.ScalingSizeY, 0.8f, 0.2f, 1f); @@ -365,7 +365,7 @@ namespace osu.Game.Configuration ScalingPositionY, ScalingSizeX, ScalingSizeY, - ScalingMenuBackgroundDim, + ScalingBackgroundDim, UIScale, IntroSequence, NotifyOnUsernameMentioned, diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 9c6830ce05..8b0450b71c 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -141,7 +141,7 @@ namespace osu.Game.Graphics.Containers safeAreaPadding = safeArea.SafeAreaPadding.GetBoundCopy(); safeAreaPadding.BindValueChanged(_ => Scheduler.AddOnce(updateSize)); - scalingMenuBackgroundDim = config.GetBindable(OsuSetting.ScalingMenuBackgroundDim); + scalingMenuBackgroundDim = config.GetBindable(OsuSetting.ScalingBackgroundDim); scalingMenuBackgroundDim.ValueChanged += _ => Scheduler.AddOnce(updateSize); } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 6dbaf27afc..895ae1ed89 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingSizeY = osuConfig.GetBindable(OsuSetting.ScalingSizeY); scalingPositionX = osuConfig.GetBindable(OsuSetting.ScalingPositionX); scalingPositionY = osuConfig.GetBindable(OsuSetting.ScalingPositionY); - scalingBackgroundDim = osuConfig.GetBindable(OsuSetting.ScalingMenuBackgroundDim); + scalingBackgroundDim = osuConfig.GetBindable(OsuSetting.ScalingBackgroundDim); if (window != null) { From 19b7036b95eeac979f75850feb19b2a5a1a97ce2 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 29 Mar 2023 22:56:35 +0900 Subject: [PATCH 0445/1400] use same same duration negligence in migrating code --- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 8b0450b71c..bd52c8bb32 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -176,7 +176,7 @@ namespace osu.Game.Graphics.Containers } backgroundStack.FadeIn(TRANSITION_DURATION); - backgroundStack.FadeColour(OsuColour.Gray(1.0f - scalingMenuBackgroundDim.Value), 800, Easing.OutQuint); + backgroundStack.FadeColour(OsuColour.Gray(1.0f - scalingMenuBackgroundDim.Value), TRANSITION_DURATION, Easing.OutQuint); } else backgroundStack?.FadeOut(TRANSITION_DURATION); From 5d395e6d37f6247430e57c3ede359cad4c729b64 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 29 Mar 2023 22:59:54 +0900 Subject: [PATCH 0446/1400] move to ctor --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 895ae1ed89..523b1237fa 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -171,7 +171,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = GameplaySettingsStrings.BackgroundDim, Current = scalingBackgroundDim, KeyboardStep = 0.01f, - DisplayAsPercentage = true + DisplayAsPercentage = true, + TransferValueOnCommit = false }, } }, @@ -232,7 +233,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { if (s == dimSlider) { - s.TransferValueOnCommit = false; s.CanBeShown.Value = scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays; return; } From b25a59fd14ddac89f688e2bed48b6aef944b416d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2023 02:30:04 +0900 Subject: [PATCH 0447/1400] Rename `scoreCompleted` -> `checkScoreCompleted` to reflect the fact it doesn't always succeed --- osu.Game/Screens/Play/Player.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b8b3a8b5c0..c4b52136b9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -358,10 +358,10 @@ namespace osu.Game.Screens.Play ScoreProcessor.RevertResult(r); }; - DimmableStoryboard.HasStoryboardEnded.ValueChanged += _ => scoreCompleted(); + DimmableStoryboard.HasStoryboardEnded.ValueChanged += _ => checkScoreCompleted(); // Bind the judgement processors to ourselves - ScoreProcessor.HasCompleted.BindValueChanged(_ => scoreCompleted()); + ScoreProcessor.HasCompleted.BindValueChanged(_ => checkScoreCompleted()); HealthProcessor.Failed += onFail; // Provide judgement processors to mods after they're loaded so that they're on the gameplay clock, @@ -702,7 +702,7 @@ namespace osu.Game.Screens.Play /// /// Handles changes in player state which may progress the completion of gameplay / this screen's lifetime. /// - private void scoreCompleted() + private void checkScoreCompleted() { // If this player instance is in the middle of an exit, don't attempt any kind of state update. if (!this.IsCurrentScreen()) From 796cd9c916d8c9643b569986e106afa554584a6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2023 02:36:17 +0900 Subject: [PATCH 0448/1400] Rewrite comment explaining early return on `checkScoreCompleted` given new usages --- osu.Game/Screens/Play/Player.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c4b52136b9..eb33bf43d6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -708,11 +708,13 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; - // Special case to handle rewinding post-completion. This is the only way already queued forward progress can be cancelled. - // TODO: Investigate whether this can be moved to a RewindablePlayer subclass or similar. - // Currently, even if this scenario is hit, prepareScoreForDisplay has already been queued (and potentially run). - // In scenarios where rewinding is possible (replay, spectating) this is a non-issue as no submission/import work is done, - // but it still doesn't feel right that this exists here. + // Handle cases of arriving at this method when not in a completed state. + // - When a storyboard completion triggered this call earlier than gameplay finishes. + // - When a replay has been rewound before a queued resultsDisplayDelegate has run. + // + // Currently, even if this scenario is hit, prepareAndImportScoreAsync has already been queued (and potentially run). + // In the scenarios above, this is a non-issue, but it still feels a bit convoluted to have to cancel in this method. + // Maybe this can be improved with further refactoring. if (!ScoreProcessor.HasCompleted.Value) { resultsDisplayDelegate?.Cancel(); From db71db84915aa219e96aa50f67fcae9599a132b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2023 13:07:14 +0900 Subject: [PATCH 0449/1400] Update README bounty/compensation section in line with changes applied to osu-web --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3f025fa10..eb2fe6d0eb 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ When it comes to contributing to the project, the two main things you can do to If you wish to help with localisation efforts, head over to [crowdin](https://crowdin.com/project/osu-web). -For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via PayPal or osu!supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project. +We love to reward quality contributions. If you have made a large contribution, or are a regular contributor, you are welcome to [submit an expense via opencollective](https://opencollective.com/ppy/expenses/new). If you have any questions, feel free to [reach out to peppy](mailto:pe@ppy.sh) before doing so. ## Licence From d5b8a45541703f3a469cf866f92c75755334183b Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 31 Mar 2023 16:20:16 +0900 Subject: [PATCH 0450/1400] Always use fallback strings for English MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Localisation/ResourceManagerLocalisationStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index 50a450c101..1a05bec41a 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -68,7 +68,7 @@ namespace osu.Game.Localisation // When running a debug build and in viewing english culture, use the fallbacks rather than osu-resources baked strings. // This is what a developer expects to see when making changes to `xxxStrings.cs` files. - if (DebugUtils.IsDebugBuild && EffectiveCulture.Name == @"en") + if (EffectiveCulture.Name == @"en") return null; try From 28f31ef37968134a61a59255f7ea2037ae413644 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 31 Mar 2023 16:23:37 +0900 Subject: [PATCH 0451/1400] Adjust comment slightly --- osu.Game/Localisation/ResourceManagerLocalisationStore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index 1a05bec41a..8551a140bd 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -66,8 +66,8 @@ namespace osu.Game.Localisation if (manager == null) return null; - // When running a debug build and in viewing english culture, use the fallbacks rather than osu-resources baked strings. - // This is what a developer expects to see when making changes to `xxxStrings.cs` files. + // When using the English culture, prefer the fallbacks rather than osu-resources baked strings. + // They are guaranteed to be up-to-date, and is also what a developer expects to see when making changes to `xxxStrings.cs` files. if (EffectiveCulture.Name == @"en") return null; From 4b7d44c329dd12fd97651492edf0b1b0d58d0fcf Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 31 Mar 2023 16:23:56 +0900 Subject: [PATCH 0452/1400] Remove unused using --- osu.Game/Localisation/ResourceManagerLocalisationStore.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs index 8551a140bd..3fa86c188c 100644 --- a/osu.Game/Localisation/ResourceManagerLocalisationStore.cs +++ b/osu.Game/Localisation/ResourceManagerLocalisationStore.cs @@ -11,7 +11,6 @@ using System.Linq; using System.Resources; using System.Threading; using System.Threading.Tasks; -using osu.Framework.Development; using osu.Framework.Localisation; namespace osu.Game.Localisation From 7f9bf09e0396f7b76f78b55ebaaf995c21d245c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 20:07:31 +0900 Subject: [PATCH 0453/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 927d66d93f..9b26526b9a 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3de022e88d..6c10137a92 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index eb7ba24336..25fad5eaa3 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 0f0dd9f2dcdb731ac3e33d4c9a416ce3a3952a95 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 20:07:33 +0900 Subject: [PATCH 0454/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6c10137a92..640f72c7da 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From cf5acbf66eb5b0ff872eef50ff78f5409d4111a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 20:16:14 +0900 Subject: [PATCH 0455/1400] Update usage of `SupportedWindowModes` --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 6465d62ef0..a40156cf6d 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -75,7 +75,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (window != null) { currentDisplay.BindTo(window.CurrentDisplayBindable); - windowModes.BindTo(window.SupportedWindowModes); window.DisplaysChanged += onDisplaysChanged; } @@ -87,7 +86,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics windowModeDropdown = new SettingsDropdown { LabelText = GraphicsSettingsStrings.ScreenMode, - ItemSource = windowModes, + Items = window?.SupportedWindowModes, Current = config.GetBindable(FrameworkSetting.WindowMode), }, displayDropdown = new DisplaySettingsDropdown From e66569b394848348d62dd654af716afd69eae1b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 21:04:44 +0900 Subject: [PATCH 0456/1400] Update ruleset dependency tests in line with nullable changes --- .../Testing/TestSceneRulesetDependencies.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index f1533a32b9..a5a83d7231 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.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. -#nullable disable - using System; using System.Collections.Generic; using NUnit.Framework; @@ -51,9 +49,11 @@ namespace osu.Game.Tests.Testing [Test] public void TestRetrieveShader() { - AddAssert("ruleset shaders retrieved", () => - Dependencies.Get().LoadRaw(@"sh_TestVertex.vs") != null && - Dependencies.Get().LoadRaw(@"sh_TestFragment.fs") != null); + AddStep("ruleset shaders retrieved without error", () => + { + Dependencies.Get().LoadRaw(@"sh_TestVertex.vs"); + Dependencies.Get().LoadRaw(@"sh_TestFragment.fs"); + }); } [Test] @@ -76,12 +76,12 @@ namespace osu.Game.Tests.Testing } public override IResourceStore CreateResourceStore() => new NamespacedResourceStore(TestResources.GetStore(), @"Resources"); - public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new TestRulesetConfigManager(); + public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new TestRulesetConfigManager(); public override IEnumerable GetModsFor(ModType type) => Array.Empty(); - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => null; - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; + public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => null!; + public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null!; + public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null!; } private class TestRulesetConfigManager : IRulesetConfigManager From 4c2b7e7788823978d8f82f9f006395ce3d06892c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 21:05:20 +0900 Subject: [PATCH 0457/1400] Fix random inspection showing up only in CI --- osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 7b26640e50..1a44262ef8 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu set => valueText.Text = value.ToLocalisableString("N0"); } - public CountSection(LocalisableString header) + protected CountSection(LocalisableString header) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; From 2cf863636632887cc7c6029b81dd45b3cad6b10a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 2 Apr 2023 22:25:58 +0900 Subject: [PATCH 0458/1400] show guest diff author in `BeatmapPicker` --- .../Online/TestSceneBeatmapSetOverlay.cs | 73 ++++++++++++++++++- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 30 +++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 5d13421195..3090ff6c49 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Testing; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -26,7 +27,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser; namespace osu.Game.Tests.Visual.Online { - public partial class TestSceneBeatmapSetOverlay : OsuTestScene + public partial class TestSceneBeatmapSetOverlay : OsuManualInputManagerTestScene { private readonly TestBeatmapSetOverlay overlay; @@ -281,6 +282,22 @@ namespace osu.Game.Tests.Visual.Online AddAssert(@"type is correct", () => type == lookupType.ToString()); } + [Test] + public void TestBeatmapSetWithGuestDIff() + { + AddStep("show map", () => overlay.ShowBeatmapSet(createBeatmapSetWithGuestDiff())); + AddStep("Move mouse to host diff", () => + { + InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(0)); + }); + AddAssert("Guset mapper information not show", () => !overlay.ChildrenOfType().Single().ChildrenOfType().Any()); + AddStep("move mouse to guest diff", () => + { + InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(1)); + }); + AddAssert("Guset mapper information show", () => overlay.ChildrenOfType().Single().ChildrenOfType().Any()); + } + private APIBeatmapSet createManyDifficultiesBeatmapSet() { var set = getBeatmapSet(); @@ -320,6 +337,60 @@ namespace osu.Game.Tests.Visual.Online return beatmapSet; } + private APIBeatmapSet createBeatmapSetWithGuestDiff() + { + var set = getBeatmapSet(); + + var beatmaps = new List(); + + var guestUser = new APIUser + { + Username = @"BanchoBot", + Id = 3, + }; + + set.RelatedUsers = new[] + { + set.Author, guestUser + }; + + beatmaps.Add(new APIBeatmap + { + OnlineID = 1145, + DifficultyName = "Host Diff", + RulesetID = Ruleset.Value.OnlineID, + StarRating = 1.4, + OverallDifficulty = 3.5f, + AuthorID = set.AuthorID, + FailTimes = new APIFailTimes + { + Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), + }, + Status = BeatmapOnlineStatus.Graveyard + }); + + beatmaps.Add(new APIBeatmap + { + OnlineID = 1919, + DifficultyName = "Guest Diff", + RulesetID = Ruleset.Value.OnlineID, + StarRating = 8.1, + OverallDifficulty = 3.5f, + AuthorID = 3, + FailTimes = new APIFailTimes + { + Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(), + }, + Status = BeatmapOnlineStatus.Graveyard + }); + + set.Beatmaps = beatmaps.ToArray(); + + return set; + } + private void downloadAssert(bool shown) { AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.HeaderContent.DownloadButtonsVisible == shown); diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 585e0dd1a2..7dc3fc665f 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.BeatmapSet private const float tile_spacing = 2; private readonly OsuSpriteText version, starRating, starRatingText; + public readonly FillFlowContainer GuestMapperContainer; private readonly FillFlowContainer starRatingContainer; private readonly Statistic plays, favourites; @@ -88,6 +89,12 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, + GuestMapperContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }, starRatingContainer = new FillFlowContainer { Anchor = Anchor.BottomLeft, @@ -198,11 +205,32 @@ namespace osu.Game.Overlays.BeatmapSet updateDifficultyButtons(); } - private void showBeatmap(IBeatmapInfo? beatmapInfo) + private void showBeatmap(APIBeatmap? beatmapInfo) { + GuestMapperContainer.Clear(); + + if (beatmapInfo != null && beatmapSet?.Author.OnlineID != beatmapInfo.AuthorID) + { + if (BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID) is APIUser user) + GuestMapperContainer.Child = getGueatMapper(user); + } + version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } + private Drawable getGueatMapper(APIUser user) + { + return new LinkFlowContainer(s => + { + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.AddText("mapped by "); + d.AddUserLink(user); + }); + } + private void updateDifficultyButtons() { Difficulties.Children.ToList().ForEach(diff => diff.State = diff.Beatmap == Beatmap.Value ? DifficultySelectorState.Selected : DifficultySelectorState.NotSelected); From d949ef3ca4cf0891f6dff2bc02b9a38c9ee9687c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 2 Apr 2023 22:53:15 +0900 Subject: [PATCH 0459/1400] make `guestMapperContainer` private tests don't use it --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 7dc3fc665f..61bfd97f3c 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.BeatmapSet private const float tile_spacing = 2; private readonly OsuSpriteText version, starRating, starRatingText; - public readonly FillFlowContainer GuestMapperContainer; + private readonly FillFlowContainer guestMapperContainer; private readonly FillFlowContainer starRatingContainer; private readonly Statistic plays, favourites; @@ -89,7 +89,7 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, - GuestMapperContainer = new FillFlowContainer + guestMapperContainer = new FillFlowContainer { AutoSizeAxes = Axes.Both, Anchor = Anchor.BottomLeft, @@ -207,12 +207,12 @@ namespace osu.Game.Overlays.BeatmapSet private void showBeatmap(APIBeatmap? beatmapInfo) { - GuestMapperContainer.Clear(); + guestMapperContainer.Clear(); if (beatmapInfo != null && beatmapSet?.Author.OnlineID != beatmapInfo.AuthorID) { if (BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID) is APIUser user) - GuestMapperContainer.Child = getGueatMapper(user); + guestMapperContainer.Child = getGueatMapper(user); } version.Text = beatmapInfo?.DifficultyName ?? string.Empty; From 1e0b64c9e8c408e27f039c47c67327d33a79bd38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 2 Apr 2023 23:07:39 +0900 Subject: [PATCH 0460/1400] Update framework (again) --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 9b26526b9a..eb9a7e60df 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 640f72c7da..ec33eff5eb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 25fad5eaa3..096c4d52ab 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From c3a6a581693efda04f913462f216960b19bedd5e Mon Sep 17 00:00:00 2001 From: Susko3 Date: Sun, 2 Apr 2023 19:23:18 +0200 Subject: [PATCH 0461/1400] Fix window mode dropdown not showing --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index a40156cf6d..2765d2b437 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -32,7 +32,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private FillFlowContainer> scalingSettings = null!; private readonly Bindable currentDisplay = new Bindable(); - private readonly IBindableList windowModes = new BindableList(); private Bindable scalingMode = null!; private Bindable sizeFullscreen = null!; @@ -87,6 +86,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { LabelText = GraphicsSettingsStrings.ScreenMode, Items = window?.SupportedWindowModes, + CanBeShown = { Value = window?.SupportedWindowModes.Count() > 1 }, Current = config.GetBindable(FrameworkSetting.WindowMode), }, displayDropdown = new DisplaySettingsDropdown @@ -180,8 +180,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics updateScreenModeWarning(); }, true); - windowModes.BindCollectionChanged((_, _) => updateDisplaySettingsVisibility()); - currentDisplay.BindValueChanged(display => Schedule(() => { resolutions.RemoveRange(1, resolutions.Count - 1); @@ -235,7 +233,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private void updateDisplaySettingsVisibility() { - windowModeDropdown.CanBeShown.Value = windowModes.Count > 1; resolutionDropdown.CanBeShown.Value = resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen; displayDropdown.CanBeShown.Value = displayDropdown.Items.Count() > 1; safeAreaConsiderationsCheckbox.CanBeShown.Value = host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero; From 63ea17f10e7661bafe2c2c978ab20ac9fbd9e789 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 Apr 2023 18:15:00 -0700 Subject: [PATCH 0462/1400] Update comment vote pill in line with web --- osu.Game/Overlays/Comments/VotePill.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Comments/VotePill.cs b/osu.Game/Overlays/Comments/VotePill.cs index 6cfa5cb9e8..dd418a9e58 100644 --- a/osu.Game/Overlays/Comments/VotePill.cs +++ b/osu.Game/Overlays/Comments/VotePill.cs @@ -132,11 +132,10 @@ namespace osu.Game.Overlays.Comments }, sideNumber = new OsuSpriteText { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreRight, + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, Text = "+1", Font = OsuFont.GetFont(size: 14), - Margin = new MarginPadding { Right = 3 }, Alpha = 0, }, votesCounter = new OsuSpriteText @@ -189,7 +188,7 @@ namespace osu.Game.Overlays.Comments else sideNumber.FadeTo(IsHovered ? 1 : 0); - borderContainer.BorderThickness = IsHovered ? 3 : 0; + borderContainer.BorderThickness = IsHovered ? 2 : 0; } private void onHoverAction() From 8932668f77c46d358da083a8f5d2dce2d9a9c3af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Apr 2023 10:31:47 +0900 Subject: [PATCH 0463/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index eb9a7e60df..4b89e82729 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ec33eff5eb..b9c6c1df9d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 096c4d52ab..083d8192ea 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 7a0edabd5dc557680b06b5e51f4628da9c08879f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 Apr 2023 17:11:19 -0700 Subject: [PATCH 0464/1400] Normalise overlay horizontal padding const --- osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs | 6 +++--- osu.Game/Overlays/BeatmapSet/Info.cs | 2 +- osu.Game/Overlays/BeatmapSetOverlay.cs | 1 - osu.Game/Overlays/Changelog/ChangelogBuild.cs | 4 +--- osu.Game/Overlays/Changelog/ChangelogListing.cs | 2 +- osu.Game/Overlays/Profile/Header/BadgeHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs | 4 ++-- osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- osu.Game/Overlays/Profile/ProfileSection.cs | 4 ++-- osu.Game/Overlays/Rankings/CountryFilter.cs | 2 +- osu.Game/Overlays/Rankings/SpotlightSelector.cs | 2 +- osu.Game/Overlays/Rankings/Tables/RankingsTable.cs | 3 +-- osu.Game/Overlays/UserProfileOverlay.cs | 4 +--- osu.Game/Overlays/WaveOverlayContainer.cs | 2 ++ 17 files changed, 21 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index 26e6b1f158..7ff8352054 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -97,8 +97,8 @@ namespace osu.Game.Overlays.BeatmapSet Padding = new MarginPadding { Vertical = BeatmapSetOverlay.Y_PADDING, - Left = BeatmapSetOverlay.X_PADDING, - Right = BeatmapSetOverlay.X_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, + Left = WaveOverlayContainer.HORIZONTAL_PADDING, + Right = WaveOverlayContainer.HORIZONTAL_PADDING + BeatmapSetOverlay.RIGHT_WIDTH, }, Children = new Drawable[] { @@ -170,7 +170,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = BeatmapSetOverlay.Y_PADDING, Right = BeatmapSetOverlay.X_PADDING }, + Margin = new MarginPadding { Top = BeatmapSetOverlay.Y_PADDING, Right = WaveOverlayContainer.HORIZONTAL_PADDING }, Direction = FillDirection.Vertical, Spacing = new Vector2(10), Children = new Drawable[] diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 58739eb471..8758b9c5cf 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 15, Horizontal = BeatmapSetOverlay.X_PADDING }, + Padding = new MarginPadding { Top = 15, Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }, Children = new Drawable[] { new Container diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 237ce22767..873336bb6e 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -25,7 +25,6 @@ namespace osu.Game.Overlays { public partial class BeatmapSetOverlay : OnlineOverlay { - public const float X_PADDING = 40; public const float Y_PADDING = 25; public const float RIGHT_WIDTH = 275; diff --git a/osu.Game/Overlays/Changelog/ChangelogBuild.cs b/osu.Game/Overlays/Changelog/ChangelogBuild.cs index 96d5203d14..08978ac2ab 100644 --- a/osu.Game/Overlays/Changelog/ChangelogBuild.cs +++ b/osu.Game/Overlays/Changelog/ChangelogBuild.cs @@ -18,8 +18,6 @@ namespace osu.Game.Overlays.Changelog { public partial class ChangelogBuild : FillFlowContainer { - public const float HORIZONTAL_PADDING = 70; - public Action SelectBuild; protected readonly APIChangelogBuild Build; @@ -33,7 +31,7 @@ namespace osu.Game.Overlays.Changelog RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; - Padding = new MarginPadding { Horizontal = HORIZONTAL_PADDING }; + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }; Children = new Drawable[] { diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index d7c9ff67fe..4b784c7a28 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Changelog { RelativeSizeAxes = Axes.X, Height = 1, - Padding = new MarginPadding { Horizontal = ChangelogBuild.HORIZONTAL_PADDING }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }, Margin = new MarginPadding { Top = 30 }, Child = new Box { diff --git a/osu.Game/Overlays/Profile/Header/BadgeHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeHeaderContainer.cs index 508041eb76..24be6ce2f5 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeHeaderContainer.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(10, 10), - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Top = 10 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Top = 10 }, } }; } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 1e80257a57..08a816930e 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 10 }, Spacing = new Vector2(0, 10), Children = new Drawable[] { diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index 0dab4d582d..cafee7ea85 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.Y, Direction = FillDirection.Horizontal, Padding = new MarginPadding { Vertical = 10 }, - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Margin = new MarginPadding { Left = WaveOverlayContainer.HORIZONTAL_PADDING }, Spacing = new Vector2(10, 0), Children = new Drawable[] { @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Right = UserProfileOverlay.CONTENT_X_MARGIN }, + Margin = new MarginPadding { Right = WaveOverlayContainer.HORIZONTAL_PADDING }, Children = new Drawable[] { levelBadge = new LevelBadge diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index 1cc3aae735..1f35f39b49 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Profile.Header { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 10 }, Child = new GridContainer { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 2f4f49788f..d04329430b 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Profile.Header Direction = FillDirection.Horizontal, Padding = new MarginPadding { - Left = UserProfileOverlay.CONTENT_X_MARGIN, + Left = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = vertical_padding }, Height = content_height + 2 * vertical_padding, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 363eb5d58e..80d48ae09e 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { - ContentSidePadding = UserProfileOverlay.CONTENT_X_MARGIN; + ContentSidePadding = WaveOverlayContainer.HORIZONTAL_PADDING; TabControl.AddItem(LayoutStrings.HeaderUsersShow); diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 4ac86924f8..a8a240ddde 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Profile AutoSizeAxes = Axes.Both, Margin = new MarginPadding { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN - outer_gutter_width, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING - outer_gutter_width, Top = 20, Bottom = 20, }, @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Profile RelativeSizeAxes = Axes.X, Padding = new MarginPadding { - Horizontal = UserProfileOverlay.CONTENT_X_MARGIN - outer_gutter_width, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING - outer_gutter_width, Bottom = 20 } }, diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index e27fa7c7bd..525816f8fd 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Rankings Origin = Anchor.CentreLeft, Direction = FillDirection.Horizontal, Spacing = new Vector2(10, 0), - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Margin = new MarginPadding { Left = WaveOverlayContainer.HORIZONTAL_PADDING }, Children = new Drawable[] { new OsuSpriteText diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index 31273e3b01..190da04a5d 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.Rankings { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }, Child = new FillFlowContainer { RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs index affd9a2c44..27d894cdc2 100644 --- a/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/RankingsTable.cs @@ -23,7 +23,6 @@ namespace osu.Game.Overlays.Rankings.Tables public abstract partial class RankingsTable : TableContainer { protected const int TEXT_SIZE = 12; - private const float horizontal_inset = 20; private const float row_height = 32; private const float row_spacing = 3; private const int items_per_page = 50; @@ -39,7 +38,7 @@ namespace osu.Game.Overlays.Rankings.Tables RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Padding = new MarginPadding { Horizontal = horizontal_inset }; + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }; RowSize = new Dimension(GridSizeMode.Absolute, row_height + row_spacing); } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index c5f8a820ea..d1fe877e55 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -45,8 +45,6 @@ namespace osu.Game.Overlays [Resolved] private RulesetStore rulesets { get; set; } = null!; - public const float CONTENT_X_MARGIN = 50; - public UserProfileOverlay() : base(OverlayColourScheme.Pink) { @@ -184,7 +182,7 @@ namespace osu.Game.Overlays public ProfileSectionTabControl() { Height = 40; - Padding = new MarginPadding { Horizontal = CONTENT_X_MARGIN }; + Padding = new MarginPadding { Horizontal = HORIZONTAL_PADDING }; TabContainer.Spacing = new Vector2(20); } diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index d25f6a9ae5..00474cc0d8 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays protected override string PopInSampleName => "UI/wave-pop-in"; + public const float HORIZONTAL_PADDING = 50; + protected WaveOverlayContainer() { AddInternal(Waves = new WaveContainer From af389b1107367207fd42cbef0b30d0f23175d541 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 Apr 2023 17:12:27 -0700 Subject: [PATCH 0465/1400] Replace all hardcoded 50 horizontal padding with const --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 4 ++-- osu.Game/Overlays/Comments/CommentsContainer.cs | 4 ++-- osu.Game/Overlays/Comments/CommentsHeader.cs | 2 +- osu.Game/Overlays/Comments/TotalCommentsCounter.cs | 2 +- osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs | 2 +- osu.Game/Overlays/News/Displays/ArticleListing.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 2 +- osu.Game/Overlays/OverlaySidebar.cs | 2 +- osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs | 2 +- osu.Game/Overlays/Wiki/WikiArticlePage.cs | 2 +- osu.Game/Overlays/WikiOverlay.cs | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 9eb04d9cc5..6d89313979 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -116,7 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Padding = new MarginPadding { Horizontal = 50 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }, Margin = new MarginPadding { Vertical = 20 }, Children = new Drawable[] { diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 04526eb7ba..4aded1dd59 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Changelog Padding = new MarginPadding { Vertical = 20, - Horizontal = 50, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, }; } @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.Changelog Direction = FillDirection.Vertical, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Padding = new MarginPadding { Right = 50 + image_container_width }, + Padding = new MarginPadding { Right = WaveOverlayContainer.HORIZONTAL_PADDING + image_container_width }, Children = new Drawable[] { new OsuSpriteText diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index c4e4700674..2a873690a7 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Comments { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = 50, Vertical = 20 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 20 }, Children = new Drawable[] { avatar = new UpdateableAvatar(api.LocalUser.Value) @@ -393,7 +393,7 @@ namespace osu.Game.Overlays.Comments { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Margin = new MarginPadding { Left = 50 }, + Margin = new MarginPadding { Left = WaveOverlayContainer.HORIZONTAL_PADDING }, Text = CommentsStrings.Empty } }); diff --git a/osu.Game/Overlays/Comments/CommentsHeader.cs b/osu.Game/Overlays/Comments/CommentsHeader.cs index e6d44e618b..0ae1f839a1 100644 --- a/osu.Game/Overlays/Comments/CommentsHeader.cs +++ b/osu.Game/Overlays/Comments/CommentsHeader.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Comments new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 50 }, + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING }, Children = new Drawable[] { new OverlaySortTabControl diff --git a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs index 38928f6f3d..2065f7a76b 100644 --- a/osu.Game/Overlays/Comments/TotalCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/TotalCommentsCounter.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Comments Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - Margin = new MarginPadding { Left = 50 }, + Margin = new MarginPadding { Left = WaveOverlayContainer.HORIZONTAL_PADDING }, Spacing = new Vector2(5, 0), Children = new Drawable[] { diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs index 73fab6d62b..a40993ae05 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Dashboard.Friends { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = 50 } + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING } }, loading = new LoadingLayer(true) } diff --git a/osu.Game/Overlays/News/Displays/ArticleListing.cs b/osu.Game/Overlays/News/Displays/ArticleListing.cs index b6ce16ae7d..4fc9dde156 100644 --- a/osu.Game/Overlays/News/Displays/ArticleListing.cs +++ b/osu.Game/Overlays/News/Displays/ArticleListing.cs @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.News.Displays { Vertical = 20, Left = 30, - Right = 50 + Right = WaveOverlayContainer.HORIZONTAL_PADDING }; InternalChild = new FillFlowContainer diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index f28d40c429..93de463204 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -89,7 +89,7 @@ namespace osu.Game.Overlays } }); - ContentSidePadding = 50; + ContentSidePadding = WaveOverlayContainer.HORIZONTAL_PADDING; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/OverlaySidebar.cs b/osu.Game/Overlays/OverlaySidebar.cs index b8c0032e87..93e5e83ffc 100644 --- a/osu.Game/Overlays/OverlaySidebar.cs +++ b/osu.Game/Overlays/OverlaySidebar.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Vertical = 20, - Left = 50, + Left = WaveOverlayContainer.HORIZONTAL_PADDING, Right = 30 }, Child = CreateContent() diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index cafee7ea85..d964364510 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Profile.Header Origin = Anchor.CentreRight, Width = 200, Height = 6, - Margin = new MarginPadding { Right = 50 }, + Margin = new MarginPadding { Right = WaveOverlayContainer.HORIZONTAL_PADDING }, Child = new LevelProgressBar { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/Wiki/WikiArticlePage.cs b/osu.Game/Overlays/Wiki/WikiArticlePage.cs index 6c1dbe3181..342a395871 100644 --- a/osu.Game/Overlays/Wiki/WikiArticlePage.cs +++ b/osu.Game/Overlays/Wiki/WikiArticlePage.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Wiki { Vertical = 20, Left = 30, - Right = 50, + Right = WaveOverlayContainer.HORIZONTAL_PADDING, }, OnAddHeading = sidebar.AddEntry, } diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 88dc2cd7a4..2444aa4fa2 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -145,7 +145,7 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Vertical = 20, - Horizontal = 50, + Horizontal = HORIZONTAL_PADDING, }, }); } From 436f1e4ae40fb980447672a5f2ad69a41ce61243 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 Apr 2023 20:45:09 -0700 Subject: [PATCH 0466/1400] Replace other hardcoded horizontal padding with const - Also add overlay stream item padding const and account for it --- .../Overlays/BeatmapListing/BeatmapListingSearchControl.cs | 2 +- osu.Game/Overlays/Changelog/ChangelogHeader.cs | 2 +- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/DrawableComment.cs | 2 +- osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs | 2 +- osu.Game/Overlays/OverlayStreamItem.cs | 4 +++- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs index 23de1cf76d..3fa0fc7a77 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapListing Padding = new MarginPadding { Vertical = 20, - Horizontal = 40, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, }, Child = new FillFlowContainer { diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs index 54ada24987..e9be67e977 100644 --- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs +++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Changelog AutoSizeAxes = Axes.Y, Padding = new MarginPadding { - Horizontal = 65, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING - ChangelogUpdateStreamItem.PADDING, Vertical = 20 }, Child = Streams = new ChangelogUpdateStreamControl { Current = currentStream }, diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 2a873690a7..24536fe460 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays.Comments ShowDeleted = { BindTarget = ShowDeleted }, Margin = new MarginPadding { - Horizontal = 70, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 10 } }, diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 397dd46cdc..a710406548 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -537,7 +537,7 @@ namespace osu.Game.Overlays.Comments { return new MarginPadding { - Horizontal = 70, + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = 15 }; } diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs index a40993ae05..e3accfd2ad 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.Dashboard.Friends Padding = new MarginPadding { Top = 20, - Horizontal = 45 + Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING - FriendsOnlineStatusItem.PADDING }, Child = onlineStreamControl = new FriendOnlineStreamControl(), } diff --git a/osu.Game/Overlays/OverlayStreamItem.cs b/osu.Game/Overlays/OverlayStreamItem.cs index 9b18e5cccf..45181c13e4 100644 --- a/osu.Game/Overlays/OverlayStreamItem.cs +++ b/osu.Game/Overlays/OverlayStreamItem.cs @@ -39,12 +39,14 @@ namespace osu.Game.Overlays private FillFlowContainer text; private ExpandingBar expandingBar; + public const float PADDING = 5; + protected OverlayStreamItem(T value) : base(value) { Height = 50; Width = 90; - Margin = new MarginPadding(5); + Margin = new MarginPadding(PADDING); } [BackgroundDependencyLoader] From 247d426c8a61cebe24693bf0124798483bea7239 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 2 Apr 2023 17:14:31 -0700 Subject: [PATCH 0467/1400] Add horizontal padding to currently playing search textbox --- osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index 1540aa8fbb..5047992c8b 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Dashboard new Container { RelativeSizeAxes = Axes.X, - Padding = new MarginPadding(padding), + Padding = new MarginPadding { Horizontal = WaveOverlayContainer.HORIZONTAL_PADDING, Vertical = padding }, Child = searchTextBox = new BasicSearchTextBox { RelativeSizeAxes = Axes.X, From a097433cb121f6315166cd8e9914efb9dc0347ea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Apr 2023 14:56:29 +0900 Subject: [PATCH 0468/1400] Fix overlay toggle keys working during disabled activation modes Closes #23104. --- osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs | 13 +++++++++++++ osu.Game/Overlays/Toolbar/Toolbar.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index aef6f9ade0..22c7bb64b2 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -114,6 +114,19 @@ namespace osu.Game.Tests.Visual.Menus } } + [TestCase(OverlayActivation.All)] + [TestCase(OverlayActivation.Disabled)] + public void TestButtonKeyboardInputRespectsOverlayActivation(OverlayActivation mode) + { + AddStep($"set activation mode to {mode}", () => toolbar.OverlayActivationMode.Value = mode); + AddStep("hide toolbar", () => toolbar.Hide()); + + if (mode == OverlayActivation.Disabled) + AddAssert("check buttons not accepting input", () => InputManager.NonPositionalInputQueue.OfType().Count(), () => Is.Zero); + else + AddAssert("check buttons accepting input", () => InputManager.NonPositionalInputQueue.OfType().Count(), () => Is.Not.Zero); + } + [TestCase(OverlayActivation.All)] [TestCase(OverlayActivation.Disabled)] public void TestRespectsOverlayActivation(OverlayActivation mode) diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index f21ef0ee98..93294a9d30 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Toolbar protected readonly IBindable OverlayActivationMode = new Bindable(OverlayActivation.All); // Toolbar and its components need keyboard input even when hidden. - public override bool PropagateNonPositionalInputSubTree => true; + public override bool PropagateNonPositionalInputSubTree => OverlayActivationMode.Value != OverlayActivation.Disabled; public Toolbar() { From 6239789188c94561aaae96b6932fd67ee9ad5a4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Apr 2023 15:37:10 +0900 Subject: [PATCH 0469/1400] Fix missing using statements in multiple test scenes --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 1 + osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index 7bc789ecc4..eecead5415 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 9d8d82108d..7bbfc6a62b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -10,6 +10,8 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; From 7011928d86e7ed83f3e7d8839d8e1acc0a878267 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Apr 2023 18:04:33 +0900 Subject: [PATCH 0470/1400] Fix abysmal debug performance due to try-catch logic in `DrawableRulesetDependencies` --- .../UI/DrawableRulesetDependencies.cs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index e6ee770e19..1d5fcc634e 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -206,17 +206,26 @@ namespace osu.Game.Rulesets.UI this.parent = parent; } + // When the debugger is attached, exceptions are expensive. + // Manually work around this by caching failed lookups and falling back straight to parent. + private readonly HashSet<(string, string)> failedLookups = new HashSet<(string, string)>(); + public override IShader Load(string vertex, string fragment) { - try + if (!failedLookups.Contains((vertex, fragment))) { - return base.Load(vertex, fragment); - } - catch - { - // Shader lookup is very non-standard. Rather than returning null on missing shaders, exceptions are thrown. - return parent.Load(vertex, fragment); + try + { + return base.Load(vertex, fragment); + } + catch + { + // Shader lookup is very non-standard. Rather than returning null on missing shaders, exceptions are thrown. + failedLookups.Add((vertex, fragment)); + } } + + return parent.Load(vertex, fragment); } } } From be79ea1c10eacfe4e759e2fd2fcdeeaf92280c6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Apr 2023 18:14:58 +0900 Subject: [PATCH 0471/1400] Remove left/right click based placement in taiko editor and respect sample selection --- .../Edit/Blueprints/HitPlacementBlueprint.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 0a1f5380b5..d47a50b94d 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -35,20 +35,8 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints protected override bool OnMouseDown(MouseDownEvent e) { - switch (e.Button) - { - case MouseButton.Left: - HitObject.Type = HitType.Centre; - EndPlacement(true); - return true; - - case MouseButton.Right: - HitObject.Type = HitType.Rim; - EndPlacement(true); - return true; - } - - return false; + EndPlacement(true); + return true; } public override void UpdateTimeAndPosition(SnapResult result) From 51240ed46b0fbec450b74c7513cf3737a997cad9 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 3 Apr 2023 19:51:22 +0900 Subject: [PATCH 0472/1400] typo --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 61bfd97f3c..59be9414fd 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -212,13 +212,13 @@ namespace osu.Game.Overlays.BeatmapSet if (beatmapInfo != null && beatmapSet?.Author.OnlineID != beatmapInfo.AuthorID) { if (BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID) is APIUser user) - guestMapperContainer.Child = getGueatMapper(user); + guestMapperContainer.Child = getGuestMapper(user); } version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } - private Drawable getGueatMapper(APIUser user) + private Drawable getGuestMapper(APIUser user) { return new LinkFlowContainer(s => { From 41c01d3929279865a1e542c7aa556bc3dad1d44d Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 3 Apr 2023 20:07:21 +0900 Subject: [PATCH 0473/1400] nullable condition --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 59be9414fd..67348959a6 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -211,21 +211,18 @@ namespace osu.Game.Overlays.BeatmapSet if (beatmapInfo != null && beatmapSet?.Author.OnlineID != beatmapInfo.AuthorID) { - if (BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID) is APIUser user) guestMapperContainer.Child = getGuestMapper(user); + APIUser? user = BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo?.AuthorID); + if (user != null) } version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } - private Drawable getGuestMapper(APIUser user) + private void getGuestMapper(APIUser user) { - return new LinkFlowContainer(s => + guestMapperContainer.With(d => { - s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15); - }).With(d => - { - d.AutoSizeAxes = Axes.Both; d.AddText("mapped by "); d.AddUserLink(user); }); From 735b48679e2d4cd025590d84e7bd84a6712b08ab Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 3 Apr 2023 20:09:49 +0900 Subject: [PATCH 0474/1400] use `LinkFlowContainer` directly --- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 5 +++-- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 3090ff6c49..37f7b7623b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -15,6 +15,7 @@ using System.Linq; using osu.Framework.Testing; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -290,12 +291,12 @@ namespace osu.Game.Tests.Visual.Online { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(0)); }); - AddAssert("Guset mapper information not show", () => !overlay.ChildrenOfType().Single().ChildrenOfType().Any()); + AddAssert("Guset mapper information not show", () => overlay.ChildrenOfType().Single().ChildrenOfType().All(s => s.Text != "BanchoBot")); AddStep("move mouse to guest diff", () => { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(1)); }); - AddAssert("Guset mapper information show", () => overlay.ChildrenOfType().Single().ChildrenOfType().Any()); + AddAssert("Guset mapper information show", () => overlay.ChildrenOfType().Single().ChildrenOfType().Any(s => s.Text == "BanchoBot")); } private APIBeatmapSet createManyDifficultiesBeatmapSet() diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 67348959a6..3689599a6f 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.BeatmapSet private const float tile_spacing = 2; private readonly OsuSpriteText version, starRating, starRatingText; - private readonly FillFlowContainer guestMapperContainer; + private readonly LinkFlowContainer guestMapperContainer; private readonly FillFlowContainer starRatingContainer; private readonly Statistic plays, favourites; @@ -89,7 +89,8 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, - guestMapperContainer = new FillFlowContainer + guestMapperContainer = new LinkFlowContainer(s => + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15)) { AutoSizeAxes = Axes.Both, Anchor = Anchor.BottomLeft, @@ -209,11 +210,11 @@ namespace osu.Game.Overlays.BeatmapSet { guestMapperContainer.Clear(); - if (beatmapInfo != null && beatmapSet?.Author.OnlineID != beatmapInfo.AuthorID) + if (beatmapInfo != null && beatmapInfo.AuthorID != beatmapSet?.AuthorID) { - guestMapperContainer.Child = getGuestMapper(user); - APIUser? user = BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo?.AuthorID); + APIUser? user = BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID); if (user != null) + getGuestMapper(user); } version.Text = beatmapInfo?.DifficultyName ?? string.Empty; From 9dd30e4b4cb87a783c3e3f121b0238716137e252 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 3 Apr 2023 20:24:38 +0900 Subject: [PATCH 0475/1400] condition fix --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 3689599a6f..63bb122cb6 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -210,9 +210,9 @@ namespace osu.Game.Overlays.BeatmapSet { guestMapperContainer.Clear(); - if (beatmapInfo != null && beatmapInfo.AuthorID != beatmapSet?.AuthorID) + if (beatmapInfo?.AuthorID != beatmapSet?.AuthorID) { - APIUser? user = BeatmapSet?.RelatedUsers?.Single(u => u.OnlineID == beatmapInfo.AuthorID); + APIUser? user = BeatmapSet?.RelatedUsers?.SingleOrDefault(u => u.OnlineID == beatmapInfo?.AuthorID); if (user != null) getGuestMapper(user); } From 9e0277b2fd85c825cb35e9cf47a1f4313db12656 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 4 Apr 2023 00:19:14 +0900 Subject: [PATCH 0476/1400] useless using --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 37f7b7623b..9e46738305 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -14,7 +14,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Testing; using osu.Game.Beatmaps.Drawables; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; From ed07c0640b4edca4424103fdadd45e9044dc8976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 3 Apr 2023 20:13:59 +0200 Subject: [PATCH 0477/1400] Remove unused using directive --- osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index d47a50b94d..67206fcd8f 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -8,7 +8,6 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.UI; using osuTK; -using osuTK.Input; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { From f42a463479d94480aefaf0189adddeafe0df3965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 3 Apr 2023 20:14:17 +0200 Subject: [PATCH 0478/1400] Remove `#nullable disable` May as well that we're here... --- .../Edit/Blueprints/HitPlacementBlueprint.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index 67206fcd8f..f152c98a2e 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.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. -#nullable disable - using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Objects; From f9ebdadfe8da725e41f3fd4cd86a21a832457c7e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 18:53:25 +0900 Subject: [PATCH 0479/1400] Move right-side editor toolbox to base `HitObjectComposer` Move right-side editor toolbox to base `HitObjectComposer` --- .../Edit/CatchHitObjectComposer.cs | 1 - .../Edit/DistancedHitObjectComposer.cs | 53 ++++++------------- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 22 +++++++- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index ea5f54a775..cd8894753f 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -48,7 +48,6 @@ namespace osu.Game.Rulesets.Catch.Edit private void load() { // todo: enable distance spacing once catch supports applying it to its existing distance snap grid implementation. - RightSideToolboxContainer.Alpha = 0; DistanceSpacingMultiplier.Disabled = true; LayerBelowRuleset.Add(new PlayfieldBorder diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index 0df481737e..aa47b4f424 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -11,8 +11,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; @@ -47,8 +45,6 @@ namespace osu.Game.Rulesets.Edit IBindable IDistanceSnapProvider.DistanceSpacingMultiplier => DistanceSpacingMultiplier; - protected ExpandingToolboxContainer RightSideToolboxContainer { get; private set; } - private ExpandableSlider> distanceSpacingSlider; private ExpandableButton currentDistanceSpacingButton; @@ -67,47 +63,29 @@ namespace osu.Game.Rulesets.Edit [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - AddInternal(new Container + RightToolbox.Add(new EditorToolboxGroup("snapping") { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, + Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, Children = new Drawable[] { - new Box + distanceSpacingSlider = new ExpandableSlider> { - Colour = colourProvider.Background5, - RelativeSizeAxes = Axes.Both, + KeyboardStep = adjust_step, + // Manual binding in LoadComplete to handle one-way event flow. + Current = DistanceSpacingMultiplier.GetUnboundCopy(), }, - RightSideToolboxContainer = new ExpandingToolboxContainer(130, 250) + currentDistanceSpacingButton = new ExpandableButton { - Alpha = DistanceSpacingMultiplier.Disabled ? 0 : 1, - Child = new EditorToolboxGroup("snapping") + Action = () => { - Children = new Drawable[] - { - distanceSpacingSlider = new ExpandableSlider> - { - KeyboardStep = adjust_step, - // Manual binding in LoadComplete to handle one-way event flow. - Current = DistanceSpacingMultiplier.GetUnboundCopy(), - }, - currentDistanceSpacingButton = new ExpandableButton - { - Action = () => - { - (HitObject before, HitObject after)? objects = getObjectsOnEitherSideOfCurrentTime(); + (HitObject before, HitObject after)? objects = getObjectsOnEitherSideOfCurrentTime(); - Debug.Assert(objects != null); + Debug.Assert(objects != null); - DistanceSpacingMultiplier.Value = ReadCurrentDistanceSnap(objects.Value.before, objects.Value.after); - DistanceSnapToggle.Value = TernaryState.True; - }, - RelativeSizeAxes = Axes.X, - } - } - } + DistanceSpacingMultiplier.Value = ReadCurrentDistanceSnap(objects.Value.before, objects.Value.after); + DistanceSnapToggle.Value = TernaryState.True; + }, + RelativeSizeAxes = Axes.X, } } }); @@ -261,7 +239,8 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity ? referenceObject.DifficultyControlPoint.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor); + return (float)(100 * (useReferenceSliderVelocity ? referenceObject.DifficultyControlPoint.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 + / BeatSnapProvider.BeatDivisor); } public virtual float DurationToDistance(HitObject referenceObject, double duration) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index aee86fd942..c2250b1cd5 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -60,6 +60,10 @@ namespace osu.Game.Rulesets.Edit protected ComposeBlueprintContainer BlueprintContainer { get; private set; } + protected ExpandingToolboxContainer LeftToolbox { get; private set; } + + protected ExpandingToolboxContainer RightToolbox { get; private set; } + private DrawableEditorRulesetWrapper drawableRulesetWrapper; protected readonly Container LayerBelowRuleset = new Container { RelativeSizeAxes = Axes.Both }; @@ -131,7 +135,7 @@ namespace osu.Game.Rulesets.Edit Colour = colourProvider.Background5, RelativeSizeAxes = Axes.Both, }, - new ExpandingToolboxContainer(60, 200) + LeftToolbox = new ExpandingToolboxContainer(60, 200) { Children = new Drawable[] { @@ -153,6 +157,22 @@ namespace osu.Game.Rulesets.Edit }, } }, + new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + Colour = colourProvider.Background5, + RelativeSizeAxes = Axes.Both, + }, + RightToolbox = new ExpandingToolboxContainer(130, 250) + } + } }; toolboxCollection.Items = CompositionTools From c356c163fa3b86597090751e1e4dcc3bb9598d86 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:03:45 +0900 Subject: [PATCH 0480/1400] Add hit object inspector view --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 98 +++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index c2250b1cd5..9f5663747c 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -18,12 +18,15 @@ using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; @@ -33,6 +36,7 @@ using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; using osuTK; using osuTK.Input; +using FontWeight = osu.Game.Graphics.FontWeight; namespace osu.Game.Rulesets.Edit { @@ -77,6 +81,14 @@ namespace osu.Game.Rulesets.Edit private IBindable hasTiming; private Bindable autoSeekOnPlacement; + [Resolved] + private EditorBeatmap beatmap { get; set; } + + [Resolved] + private OverlayColourProvider colours { get; set; } + + private OsuTextFlowContainer inspectorText; + protected HitObjectComposer(Ruleset ruleset) : base(ruleset) { @@ -171,6 +183,16 @@ namespace osu.Game.Rulesets.Edit RelativeSizeAxes = Axes.Both, }, RightToolbox = new ExpandingToolboxContainer(130, 250) + { + Child = new EditorToolboxGroup("inspector") + { + Child = inspectorText = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + }, + } } } }; @@ -212,6 +234,13 @@ namespace osu.Game.Rulesets.Edit }); } + protected override void Update() + { + base.Update(); + + updateInspectorText(); + } + public override Playfield Playfield => drawableRulesetWrapper.Playfield; public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; @@ -289,6 +318,75 @@ namespace osu.Game.Rulesets.Edit return base.OnKeyDown(e); } + private void updateInspectorText() + { + if (beatmap.SelectedHitObjects.Count != 1) + { + inspectorText.Clear(); + return; + } + + var selected = beatmap.SelectedHitObjects.Single(); + + inspectorText.Clear(); + + addHeader("Time"); + addValue($"{selected.StartTime:#,0.##}ms"); + + switch (selected) + { + case IHasPosition pos: + addHeader("Position"); + addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); + break; + + case IHasXPosition x: + addHeader("Position"); + + addValue($"x:{x.X:#,0.##} "); + break; + + case IHasYPosition y: + addHeader("Position"); + + addValue($"y:{y.Y:#,0.##}"); + break; + } + + if (selected is IHasDistance distance) + { + addHeader("Distance"); + addValue($"{distance.Distance:#,0.##}px"); + } + + if (selected is IHasRepeats repeats) + { + addHeader("Repeats"); + addValue($"{repeats.RepeatCount:#,0.##}"); + } + + if (selected is IHasDuration duration) + { + addHeader("End Time"); + addValue($"{duration.EndTime:#,0.##}ms"); + addHeader("Duration"); + addValue($"{duration.Duration:#,0.##}ms"); + } + + void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => + { + s.Padding = new MarginPadding { Top = 2 }; + s.Font = s.Font.With(size: 12); + s.Colour = colours.Content2; + }); + + void addValue(string value) => inspectorText.AddParagraph(value, s => + { + s.Font = s.Font.With(weight: FontWeight.SemiBold); + s.Colour = colours.Content1; + }); + } + private bool checkLeftToggleFromKey(Key key, out int index) { if (key < Key.Number1 || key > Key.Number9) From b0d57616679c01c8d6ac73000ceb034331ff2cc1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:05:50 +0900 Subject: [PATCH 0481/1400] Add object type --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 9f5663747c..753667eb4a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -10,6 +10,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; +using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -330,6 +331,9 @@ namespace osu.Game.Rulesets.Edit inspectorText.Clear(); + addHeader("Type"); + addValue($"{selected.GetType().ReadableName()}"); + addHeader("Time"); addValue($"{selected.StartTime:#,0.##}ms"); From 195b5fc3f182adfb7ffa68a98102571f635eda0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:11:48 +0900 Subject: [PATCH 0482/1400] Add view for selections of size != 1 --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 103 +++++++++++--------- 1 file changed, 59 insertions(+), 44 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 753667eb4a..b4c8c7798e 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -321,62 +321,77 @@ namespace osu.Game.Rulesets.Edit private void updateInspectorText() { - if (beatmap.SelectedHitObjects.Count != 1) - { - inspectorText.Clear(); - return; - } - - var selected = beatmap.SelectedHitObjects.Single(); - inspectorText.Clear(); - addHeader("Type"); - addValue($"{selected.GetType().ReadableName()}"); - - addHeader("Time"); - addValue($"{selected.StartTime:#,0.##}ms"); - - switch (selected) + switch (beatmap.SelectedHitObjects.Count) { - case IHasPosition pos: - addHeader("Position"); - addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); + case 0: + addHeader("No selection"); break; - case IHasXPosition x: - addHeader("Position"); + case 1: + var selected = beatmap.SelectedHitObjects.Single(); + + addHeader("Type"); + addValue($"{selected.GetType().ReadableName()}"); + + addHeader("Time"); + addValue($"{selected.StartTime:#,0.##}ms"); + + switch (selected) + { + case IHasPosition pos: + addHeader("Position"); + addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); + break; + + case IHasXPosition x: + addHeader("Position"); + + addValue($"x:{x.X:#,0.##} "); + break; + + case IHasYPosition y: + addHeader("Position"); + + addValue($"y:{y.Y:#,0.##}"); + break; + } + + if (selected is IHasDistance distance) + { + addHeader("Distance"); + addValue($"{distance.Distance:#,0.##}px"); + } + + if (selected is IHasRepeats repeats) + { + addHeader("Repeats"); + addValue($"{repeats.RepeatCount:#,0.##}"); + } + + if (selected is IHasDuration duration) + { + addHeader("End Time"); + addValue($"{duration.EndTime:#,0.##}ms"); + addHeader("Duration"); + addValue($"{duration.Duration:#,0.##}ms"); + } - addValue($"x:{x.X:#,0.##} "); break; - case IHasYPosition y: - addHeader("Position"); + default: + addHeader("Selected Objects"); + addValue($"{beatmap.SelectedHitObjects.Count:#,0.##}"); - addValue($"y:{y.Y:#,0.##}"); + addHeader("Start Time"); + addValue($"{beatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); + + addHeader("End Time"); + addValue($"{beatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); break; } - if (selected is IHasDistance distance) - { - addHeader("Distance"); - addValue($"{distance.Distance:#,0.##}px"); - } - - if (selected is IHasRepeats repeats) - { - addHeader("Repeats"); - addValue($"{repeats.RepeatCount:#,0.##}"); - } - - if (selected is IHasDuration duration) - { - addHeader("End Time"); - addValue($"{duration.EndTime:#,0.##}ms"); - addHeader("Duration"); - addValue($"{duration.Duration:#,0.##}ms"); - } - void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => { s.Padding = new MarginPadding { Top = 2 }; From 4aed483005abf9eaf9ad3f73197cdfad6fa2f051 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:14:30 +0900 Subject: [PATCH 0483/1400] Tidy up dependency resolution --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 25 +++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b4c8c7798e..b28dfdf3f0 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -63,6 +63,9 @@ namespace osu.Game.Rulesets.Edit [Resolved] protected IBeatSnapProvider BeatSnapProvider { get; private set; } + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + protected ComposeBlueprintContainer BlueprintContainer { get; private set; } protected ExpandingToolboxContainer LeftToolbox { get; private set; } @@ -82,12 +85,6 @@ namespace osu.Game.Rulesets.Edit private IBindable hasTiming; private Bindable autoSeekOnPlacement; - [Resolved] - private EditorBeatmap beatmap { get; set; } - - [Resolved] - private OverlayColourProvider colours { get; set; } - private OsuTextFlowContainer inspectorText; protected HitObjectComposer(Ruleset ruleset) @@ -99,7 +96,7 @@ namespace osu.Game.Rulesets.Edit dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, OsuConfigManager config) + private void load(OsuConfigManager config) { autoSeekOnPlacement = config.GetBindable(OsuSetting.EditorAutoSeekOnPlacement); @@ -323,14 +320,14 @@ namespace osu.Game.Rulesets.Edit { inspectorText.Clear(); - switch (beatmap.SelectedHitObjects.Count) + switch (EditorBeatmap.SelectedHitObjects.Count) { case 0: addHeader("No selection"); break; case 1: - var selected = beatmap.SelectedHitObjects.Single(); + var selected = EditorBeatmap.SelectedHitObjects.Single(); addHeader("Type"); addValue($"{selected.GetType().ReadableName()}"); @@ -382,13 +379,13 @@ namespace osu.Game.Rulesets.Edit default: addHeader("Selected Objects"); - addValue($"{beatmap.SelectedHitObjects.Count:#,0.##}"); + addValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); addHeader("Start Time"); - addValue($"{beatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); + addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); addHeader("End Time"); - addValue($"{beatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); + addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); break; } @@ -396,13 +393,13 @@ namespace osu.Game.Rulesets.Edit { s.Padding = new MarginPadding { Top = 2 }; s.Font = s.Font.With(size: 12); - s.Colour = colours.Content2; + s.Colour = colourProvider.Content2; }); void addValue(string value) => inspectorText.AddParagraph(value, s => { s.Font = s.Font.With(weight: FontWeight.SemiBold); - s.Colour = colours.Content1; + s.Colour = colourProvider.Content1; }); } From 3209b092702aaa78c376422de632d48c86792d65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:17:14 +0900 Subject: [PATCH 0484/1400] Move inspector into own file --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 107 +-------------- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 132 +++++++++++++++++++ 2 files changed, 133 insertions(+), 106 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/HitObjectInspector.cs diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b28dfdf3f0..653861c11c 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -10,7 +10,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; -using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -19,15 +18,12 @@ using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; @@ -37,7 +33,6 @@ using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; using osuTK; using osuTK.Input; -using FontWeight = osu.Game.Graphics.FontWeight; namespace osu.Game.Rulesets.Edit { @@ -85,8 +80,6 @@ namespace osu.Game.Rulesets.Edit private IBindable hasTiming; private Bindable autoSeekOnPlacement; - private OsuTextFlowContainer inspectorText; - protected HitObjectComposer(Ruleset ruleset) : base(ruleset) { @@ -184,11 +177,7 @@ namespace osu.Game.Rulesets.Edit { Child = new EditorToolboxGroup("inspector") { - Child = inspectorText = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - } + Child = new HitObjectInspector() }, } } @@ -232,13 +221,6 @@ namespace osu.Game.Rulesets.Edit }); } - protected override void Update() - { - base.Update(); - - updateInspectorText(); - } - public override Playfield Playfield => drawableRulesetWrapper.Playfield; public override IEnumerable HitObjects => drawableRulesetWrapper.Playfield.AllHitObjects; @@ -316,93 +298,6 @@ namespace osu.Game.Rulesets.Edit return base.OnKeyDown(e); } - private void updateInspectorText() - { - inspectorText.Clear(); - - switch (EditorBeatmap.SelectedHitObjects.Count) - { - case 0: - addHeader("No selection"); - break; - - case 1: - var selected = EditorBeatmap.SelectedHitObjects.Single(); - - addHeader("Type"); - addValue($"{selected.GetType().ReadableName()}"); - - addHeader("Time"); - addValue($"{selected.StartTime:#,0.##}ms"); - - switch (selected) - { - case IHasPosition pos: - addHeader("Position"); - addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); - break; - - case IHasXPosition x: - addHeader("Position"); - - addValue($"x:{x.X:#,0.##} "); - break; - - case IHasYPosition y: - addHeader("Position"); - - addValue($"y:{y.Y:#,0.##}"); - break; - } - - if (selected is IHasDistance distance) - { - addHeader("Distance"); - addValue($"{distance.Distance:#,0.##}px"); - } - - if (selected is IHasRepeats repeats) - { - addHeader("Repeats"); - addValue($"{repeats.RepeatCount:#,0.##}"); - } - - if (selected is IHasDuration duration) - { - addHeader("End Time"); - addValue($"{duration.EndTime:#,0.##}ms"); - addHeader("Duration"); - addValue($"{duration.Duration:#,0.##}ms"); - } - - break; - - default: - addHeader("Selected Objects"); - addValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); - - addHeader("Start Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); - - addHeader("End Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); - break; - } - - void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => - { - s.Padding = new MarginPadding { Top = 2 }; - s.Font = s.Font.With(size: 12); - s.Colour = colourProvider.Content2; - }); - - void addValue(string value) => inspectorText.AddParagraph(value, s => - { - s.Font = s.Font.With(weight: FontWeight.SemiBold); - s.Colour = colourProvider.Content1; - }); - } - private bool checkLeftToggleFromKey(Key key, out int index) { if (key < Key.Number1 || key > Key.Number9) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs new file mode 100644 index 0000000000..a6837b24f2 --- /dev/null +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -0,0 +1,132 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions.TypeExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Screens.Edit; + +namespace osu.Game.Rulesets.Edit +{ + internal partial class HitObjectInspector : CompositeDrawable + { + private OsuTextFlowContainer inspectorText; + + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = inspectorText = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + } + + protected override void Update() + { + base.Update(); + updateInspectorText(); + } + + private void updateInspectorText() + { + inspectorText.Clear(); + + switch (EditorBeatmap.SelectedHitObjects.Count) + { + case 0: + addHeader("No selection"); + break; + + case 1: + var selected = EditorBeatmap.SelectedHitObjects.Single(); + + addHeader("Type"); + addValue($"{selected.GetType().ReadableName()}"); + + addHeader("Time"); + addValue($"{selected.StartTime:#,0.##}ms"); + + switch (selected) + { + case IHasPosition pos: + addHeader("Position"); + addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); + break; + + case IHasXPosition x: + addHeader("Position"); + + addValue($"x:{x.X:#,0.##} "); + break; + + case IHasYPosition y: + addHeader("Position"); + + addValue($"y:{y.Y:#,0.##}"); + break; + } + + if (selected is IHasDistance distance) + { + addHeader("Distance"); + addValue($"{distance.Distance:#,0.##}px"); + } + + if (selected is IHasRepeats repeats) + { + addHeader("Repeats"); + addValue($"{repeats.RepeatCount:#,0.##}"); + } + + if (selected is IHasDuration duration) + { + addHeader("End Time"); + addValue($"{duration.EndTime:#,0.##}ms"); + addHeader("Duration"); + addValue($"{duration.Duration:#,0.##}ms"); + } + + break; + + default: + addHeader("Selected Objects"); + addValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); + + addHeader("Start Time"); + addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); + + addHeader("End Time"); + addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); + break; + } + + void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => + { + s.Padding = new MarginPadding { Top = 2 }; + s.Font = s.Font.With(size: 12); + s.Colour = colourProvider.Content2; + }); + + void addValue(string value) => inspectorText.AddParagraph(value, s => + { + s.Font = s.Font.With(weight: FontWeight.SemiBold); + s.Colour = colourProvider.Content1; + }); + } + } +} From f07d859532cc8906c298fddc59e187be1b3b2fd7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 4 Apr 2023 19:31:33 +0900 Subject: [PATCH 0485/1400] Optimise how often we update the display --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index a6837b24f2..71a3202f8d 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.TypeExtensions; @@ -18,17 +17,20 @@ namespace osu.Game.Rulesets.Edit { internal partial class HitObjectInspector : CompositeDrawable { - private OsuTextFlowContainer inspectorText; + private OsuTextFlowContainer inspectorText = null!; [Resolved] - protected EditorBeatmap EditorBeatmap { get; private set; } + protected EditorBeatmap EditorBeatmap { get; private set; } = null!; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; [BackgroundDependencyLoader] private void load() { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + InternalChild = inspectorText = new OsuTextFlowContainer { RelativeSizeAxes = Axes.X, @@ -36,10 +38,13 @@ namespace osu.Game.Rulesets.Edit }; } - protected override void Update() + protected override void LoadComplete() { - base.Update(); - updateInspectorText(); + base.LoadComplete(); + + EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, _) => updateInspectorText(); + EditorBeatmap.TransactionBegan += updateInspectorText; + EditorBeatmap.TransactionEnded += updateInspectorText; } private void updateInspectorText() @@ -49,7 +54,7 @@ namespace osu.Game.Rulesets.Edit switch (EditorBeatmap.SelectedHitObjects.Count) { case 0: - addHeader("No selection"); + addValue("No selection"); break; case 1: @@ -115,6 +120,9 @@ namespace osu.Game.Rulesets.Edit break; } + if (EditorBeatmap.TransactionActive) + Scheduler.AddDelayed(updateInspectorText, 100); + void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => { s.Padding = new MarginPadding { Top = 2 }; From 7d9327f3e209665dd13e08020dcb053dc05671ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 4 Apr 2023 18:40:10 +0200 Subject: [PATCH 0486/1400] Only allow hit placement when left mouse is clicked --- .../Edit/Blueprints/HitPlacementBlueprint.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs index f152c98a2e..8b1a4f688c 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPlacementBlueprint.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.UI; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints { @@ -32,6 +33,9 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints protected override bool OnMouseDown(MouseDownEvent e) { + if (e.Button != MouseButton.Left) + return false; + EndPlacement(true); return true; } From 9c8b25e0348cc2b9be66c22b0d4f4b46f6b880a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Apr 2023 13:45:24 +0900 Subject: [PATCH 0487/1400] Fix display not always updating when expected by updating on a schedule --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index 71a3202f8d..1870476ca0 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -106,6 +106,9 @@ namespace osu.Game.Rulesets.Edit addValue($"{duration.Duration:#,0.##}ms"); } + // I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes. + // This is a good middle-ground for the time being. + Scheduler.AddDelayed(updateInspectorText, 250); break; default: @@ -120,9 +123,6 @@ namespace osu.Game.Rulesets.Edit break; } - if (EditorBeatmap.TransactionActive) - Scheduler.AddDelayed(updateInspectorText, 100); - void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => { s.Padding = new MarginPadding { Top = 2 }; From e5d57a65c9d651419e750fb4f7a9038366651ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 5 Apr 2023 19:47:25 +0200 Subject: [PATCH 0488/1400] Fix incorrect indent --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 8b3d62034a..2ae54a3afe 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -166,10 +166,10 @@ namespace osu.Game.Rulesets.UI keyCounter.SetReceptor(receptor); keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings - .Select(b => b.GetAction()) - .Distinct() - .OrderBy(action => action) - .Select(action => new KeyCounterActionTrigger(action))); + .Select(b => b.GetAction()) + .Distinct() + .OrderBy(action => action) + .Select(action => new KeyCounterActionTrigger(action))); } private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler From 02c6126be7807833ba9583006ae6eba54f21d68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 5 Apr 2023 20:53:54 +0200 Subject: [PATCH 0489/1400] Ensure storyboards are enabled in existing epilepsy warning tests --- osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 2ea27c2fef..0c7991e0ca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -45,6 +45,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private SessionStatics sessionStatics { get; set; } + [Resolved] + private OsuConfigManager config { get; set; } + [Cached(typeof(INotificationOverlay))] private readonly NotificationOverlay notificationOverlay; @@ -317,6 +320,7 @@ namespace osu.Game.Tests.Visual.Gameplay saveVolumes(); setFullVolume(); + AddStep("enable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, true)); AddStep("change epilepsy warning", () => epilepsyWarning = warning); AddStep("load dummy beatmap", () => resetPlayer(false)); @@ -339,6 +343,7 @@ namespace osu.Game.Tests.Visual.Gameplay saveVolumes(); setFullVolume(); + AddStep("enable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, true)); AddStep("set epilepsy warning", () => epilepsyWarning = true); AddStep("load dummy beatmap", () => resetPlayer(false)); From 6df7614b9df0ed26479d147b6c193d1ea7f6a0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 5 Apr 2023 20:56:50 +0200 Subject: [PATCH 0490/1400] Add tests for suppressing epilepsy warning when storyboard disabled --- .../Visual/Gameplay/TestScenePlayerLoader.cs | 19 ++++++++++++++++++- osu.Game/Screens/Play/PlayerLoader.cs | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs index 0c7991e0ca..dbd1ce1f6e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs @@ -337,6 +337,23 @@ namespace osu.Game.Tests.Visual.Gameplay restoreVolumes(); } + [Test] + public void TestEpilepsyWarningWithDisabledStoryboard() + { + saveVolumes(); + setFullVolume(); + + AddStep("disable storyboards", () => config.SetValue(OsuSetting.ShowStoryboard, false)); + AddStep("change epilepsy warning", () => epilepsyWarning = true); + AddStep("load dummy beatmap", () => resetPlayer(false)); + + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + + AddUntilStep("epilepsy warning absent", () => getWarning() == null); + + restoreVolumes(); + } + [Test] public void TestEpilepsyWarningEarlyExit() { @@ -454,7 +471,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("click notification", () => notification.TriggerClick()); } - private EpilepsyWarning getWarning() => loader.ChildrenOfType().SingleOrDefault(); + private EpilepsyWarning getWarning() => loader.ChildrenOfType().SingleOrDefault(w => w.IsAlive); private partial class TestPlayerLoader : PlayerLoader { diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index be4229ade9..30ae5ee5aa 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -489,6 +489,7 @@ namespace osu.Game.Screens.Play { // This goes hand-in-hand with the restoration of low pass filter in contentOut(). this.TransformBindableTo(volumeAdjustment, 0, CONTENT_OUT_DURATION, Easing.OutCubic); + epilepsyWarning?.Expire(); } pushSequence.Schedule(() => From ed565b1e5905c47e3ab512c50f1894626999289c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 6 Apr 2023 11:40:04 +0300 Subject: [PATCH 0491/1400] Fix SampleStore isn't being disposed --- osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index 1d5fcc634e..76d84000f1 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -98,7 +98,7 @@ namespace osu.Game.Rulesets.UI isDisposed = true; - if (ShaderManager.IsNotNull()) SampleStore.Dispose(); + if (SampleStore.IsNotNull()) SampleStore.Dispose(); if (TextureStore.IsNotNull()) TextureStore.Dispose(); if (ShaderManager.IsNotNull()) ShaderManager.Dispose(); } From ad717d2368270b7cb04f7d4d3b70c2cc5d860fea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Apr 2023 23:39:36 +0900 Subject: [PATCH 0492/1400] Fix scheduled calls piling up during transactions --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index 1870476ca0..02270d4662 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays; @@ -47,9 +48,13 @@ namespace osu.Game.Rulesets.Edit EditorBeatmap.TransactionEnded += updateInspectorText; } + private ScheduledDelegate? rollingTextUpdate; + private void updateInspectorText() { inspectorText.Clear(); + rollingTextUpdate?.Cancel(); + rollingTextUpdate = null; switch (EditorBeatmap.SelectedHitObjects.Count) { @@ -108,7 +113,7 @@ namespace osu.Game.Rulesets.Edit // I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes. // This is a good middle-ground for the time being. - Scheduler.AddDelayed(updateInspectorText, 250); + rollingTextUpdate ??= Scheduler.AddDelayed(updateInspectorText, 250); break; default: From f1de560d5717ad17588640f5745c7e801f7dfd72 Mon Sep 17 00:00:00 2001 From: Micha Lehmann Date: Sat, 8 Apr 2023 00:50:31 +0200 Subject: [PATCH 0493/1400] Snap editor selection rotation when holding shift --- .../Components/SelectionBoxRotationHandle.cs | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 0f702e1c49..04eaf6c491 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -16,6 +16,8 @@ using osu.Framework.Localisation; using osuTK; using osuTK.Graphics; +using Key = osuTK.Input.Key; + namespace osu.Game.Screens.Edit.Compose.Components { public partial class SelectionBoxRotationHandle : SelectionBoxDragHandle, IHasTooltip @@ -26,6 +28,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private SpriteIcon icon; + private const float snapStep = 15; + private float rawCumulativeRotation = 0; private readonly Bindable cumulativeRotation = new Bindable(); [Resolved] @@ -74,21 +78,38 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.OnDrag(e); - float instantaneousAngle = convertDragEventToAngleOfRotation(e); - cumulativeRotation.Value += instantaneousAngle; + rawCumulativeRotation += convertDragEventToAngleOfRotation(e); - if (cumulativeRotation.Value < -180) - cumulativeRotation.Value += 360; - else if (cumulativeRotation.Value > 180) - cumulativeRotation.Value -= 360; + applyRotation(shouldSnap: e.ShiftPressed); + } - HandleRotate?.Invoke(instantaneousAngle); + protected override bool OnKeyDown(KeyDownEvent e) + { + base.OnKeyDown(e); + + if (cumulativeRotation.Value != null && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) + { + applyRotation(shouldSnap: true); + } + + return true; + } + + protected override void OnKeyUp(KeyUpEvent e) + { + base.OnKeyUp(e); + + if (cumulativeRotation.Value != null && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) + { + applyRotation(shouldSnap: false); + } } protected override void OnDragEnd(DragEndEvent e) { base.OnDragEnd(e); cumulativeRotation.Value = null; + rawCumulativeRotation = 0; } private float convertDragEventToAngleOfRotation(DragEvent e) @@ -100,6 +121,33 @@ namespace osu.Game.Screens.Edit.Compose.Components return (endAngle - startAngle) * 180 / MathF.PI; } + private void applyRotation(bool shouldSnap) + { + float oldRotation = cumulativeRotation.Value ?? 0; + + if (shouldSnap) + { + cumulativeRotation.Value = snap(rawCumulativeRotation, snapStep); + } + else + { + cumulativeRotation.Value = rawCumulativeRotation; + } + + if (cumulativeRotation.Value < -180) + cumulativeRotation.Value += 360; + else if (cumulativeRotation.Value > 180) + cumulativeRotation.Value -= 360; + + HandleRotate?.Invoke((float)cumulativeRotation.Value - oldRotation); + } + + private float snap(float value, float step) + { + float floor = MathF.Floor(value / step) * step; + return value - floor < step / 2f ? floor : floor + step; + } + private void updateTooltipText() { TooltipText = cumulativeRotation.Value?.ToLocalisableString("0.0°") ?? default; From c827c2810b99cae4a725023f69e85652dbd8fde3 Mon Sep 17 00:00:00 2001 From: Micha Lehmann Date: Sat, 8 Apr 2023 01:28:28 +0200 Subject: [PATCH 0494/1400] Improve editor selection rotation value wrapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes two issues the previous algorithm had: 1. A half-turn rotation used to show up as -180°. 2. Rotating more than 180° in one drag event would overwhelm it and cause the value to go outside its range. This comes at the cost of a negligible performance hit, since a division (modulo) is performed instead of just addition/subtraction. --- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 04eaf6c491..4990a522f8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -134,10 +134,7 @@ namespace osu.Game.Screens.Edit.Compose.Components cumulativeRotation.Value = rawCumulativeRotation; } - if (cumulativeRotation.Value < -180) - cumulativeRotation.Value += 360; - else if (cumulativeRotation.Value > 180) - cumulativeRotation.Value -= 360; + cumulativeRotation.Value = (cumulativeRotation.Value - 180) % 360 + 180; HandleRotate?.Invoke((float)cumulativeRotation.Value - oldRotation); } From f72dd86b4251123400048ed2b9474ba69d25ef57 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Apr 2023 10:40:36 +0900 Subject: [PATCH 0495/1400] Fix code quality issues and avoid updating bindable twice per operation --- .../Components/SelectionBoxRotationHandle.cs | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 4990a522f8..5a1587eea6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -15,7 +15,6 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osuTK; using osuTK.Graphics; - using Key = osuTK.Input.Key; namespace osu.Game.Screens.Edit.Compose.Components @@ -28,8 +27,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private SpriteIcon icon; - private const float snapStep = 15; - private float rawCumulativeRotation = 0; + private const float snap_step = 15; + private readonly Bindable cumulativeRotation = new Bindable(); [Resolved] @@ -66,6 +65,8 @@ namespace osu.Game.Screens.Edit.Compose.Components icon.FadeColour(!IsHeld && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } + private float rawCumulativeRotation; + protected override bool OnDragStart(DragStartEvent e) { bool handle = base.OnDragStart(e); @@ -125,17 +126,10 @@ namespace osu.Game.Screens.Edit.Compose.Components { float oldRotation = cumulativeRotation.Value ?? 0; - if (shouldSnap) - { - cumulativeRotation.Value = snap(rawCumulativeRotation, snapStep); - } - else - { - cumulativeRotation.Value = rawCumulativeRotation; - } - - cumulativeRotation.Value = (cumulativeRotation.Value - 180) % 360 + 180; + float newRotation = shouldSnap ? snap(rawCumulativeRotation, snap_step) : rawCumulativeRotation; + newRotation = (newRotation - 180) % 360 + 180; + cumulativeRotation.Value = newRotation; HandleRotate?.Invoke((float)cumulativeRotation.Value - oldRotation); } From ed208ef12739ff03fa18fefc15036a7594601739 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 7 Apr 2023 21:10:37 -0700 Subject: [PATCH 0496/1400] Fix more typos and adjust font size to match web --- osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs | 6 +++--- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 9e46738305..4838f42043 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -286,16 +286,16 @@ namespace osu.Game.Tests.Visual.Online public void TestBeatmapSetWithGuestDIff() { AddStep("show map", () => overlay.ShowBeatmapSet(createBeatmapSetWithGuestDiff())); - AddStep("Move mouse to host diff", () => + AddStep("move mouse to host diff", () => { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(0)); }); - AddAssert("Guset mapper information not show", () => overlay.ChildrenOfType().Single().ChildrenOfType().All(s => s.Text != "BanchoBot")); + AddAssert("guest mapper information not shown", () => overlay.ChildrenOfType().Single().ChildrenOfType().All(s => s.Text != "BanchoBot")); AddStep("move mouse to guest diff", () => { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(1)); }); - AddAssert("Guset mapper information show", () => overlay.ChildrenOfType().Single().ChildrenOfType().Any(s => s.Text == "BanchoBot")); + AddAssert("guest mapper information shown", () => overlay.ChildrenOfType().Single().ChildrenOfType().Any(s => s.Text == "BanchoBot")); } private APIBeatmapSet createManyDifficultiesBeatmapSet() diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 63bb122cb6..d527d4cc9a 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -90,11 +90,12 @@ namespace osu.Game.Overlays.BeatmapSet Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, guestMapperContainer = new LinkFlowContainer(s => - s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15)) + s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 11)) { AutoSizeAxes = Axes.Both, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Bottom = 1 }, }, starRatingContainer = new FillFlowContainer { From a86a968faca0168128a0ddb432e8dfd590e93c17 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 7 Apr 2023 21:16:36 -0700 Subject: [PATCH 0497/1400] Use public `BeatmapSet` to match other usages --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index d527d4cc9a..27e671ded0 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -211,7 +211,7 @@ namespace osu.Game.Overlays.BeatmapSet { guestMapperContainer.Clear(); - if (beatmapInfo?.AuthorID != beatmapSet?.AuthorID) + if (beatmapInfo?.AuthorID != BeatmapSet?.AuthorID) { APIUser? user = BeatmapSet?.RelatedUsers?.SingleOrDefault(u => u.OnlineID == beatmapInfo?.AuthorID); if (user != null) From 580d5745c0197dbd73c3103ba78b7485ea19fcd6 Mon Sep 17 00:00:00 2001 From: Micha Lehmann Date: Sat, 8 Apr 2023 14:15:49 +0200 Subject: [PATCH 0498/1400] Add "(snapped)" to the tooltip when snap-rotating in the editor --- osu.Game/Localisation/EditorStrings.cs | 10 ++++++++++ .../Compose/Components/SelectionBoxRotationHandle.cs | 12 +++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index f4e23ae7cb..beddcfd44e 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -99,6 +99,16 @@ namespace osu.Game.Localisation /// public static LocalisableString TimelineTicks => new TranslatableString(getKey(@"timeline_ticks"), @"Ticks"); + /// + /// "0.0°" + /// + public static LocalisableString RotationFormatUnsnapped => new TranslatableString(getKey(@"rotation_format_unsnapped"), @"0.0°"); + + /// + /// "0.0° (snapped)" + /// + public static LocalisableString RotationFormatSnapped => new TranslatableString(getKey(@"rotation_format_snapped"), @"0.0° (snapped)"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 5a1587eea6..8d0e20e4ac 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Game.Localisation; using osuTK; using osuTK.Graphics; using Key = osuTK.Input.Key; @@ -56,7 +57,6 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void LoadComplete() { base.LoadComplete(); - cumulativeRotation.BindValueChanged(_ => updateTooltipText(), true); } protected override void UpdateHoverState() @@ -130,7 +130,10 @@ namespace osu.Game.Screens.Edit.Compose.Components newRotation = (newRotation - 180) % 360 + 180; cumulativeRotation.Value = newRotation; - HandleRotate?.Invoke((float)cumulativeRotation.Value - oldRotation); + + HandleRotate?.Invoke(newRotation - oldRotation); + string tooltipFormat = shouldSnap ? EditorStrings.RotationFormatSnapped.ToString() : EditorStrings.RotationFormatUnsnapped.ToString(); + TooltipText = newRotation.ToLocalisableString(tooltipFormat); } private float snap(float value, float step) @@ -138,10 +141,5 @@ namespace osu.Game.Screens.Edit.Compose.Components float floor = MathF.Floor(value / step) * step; return value - floor < step / 2f ? floor : floor + step; } - - private void updateTooltipText() - { - TooltipText = cumulativeRotation.Value?.ToLocalisableString("0.0°") ?? default; - } } } From 3c4a25e53f3459aa6ef3e1a9182769b02dd3b966 Mon Sep 17 00:00:00 2001 From: Micha Lehmann Date: Sat, 8 Apr 2023 14:28:52 +0200 Subject: [PATCH 0499/1400] Fix tooltip text not resetting when ending an editor rotation --- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 8d0e20e4ac..09898f1f2f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -111,6 +111,7 @@ namespace osu.Game.Screens.Edit.Compose.Components base.OnDragEnd(e); cumulativeRotation.Value = null; rawCumulativeRotation = 0; + TooltipText = default; } private float convertDragEventToAngleOfRotation(DragEvent e) From a1fc4def1dca5791a6cbe0dd44a3badb244718f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Apr 2023 22:18:07 +0900 Subject: [PATCH 0500/1400] Remove redundant method override --- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 09898f1f2f..fb86cb4a01 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -54,11 +54,6 @@ namespace osu.Game.Screens.Edit.Compose.Components }); } - protected override void LoadComplete() - { - base.LoadComplete(); - } - protected override void UpdateHoverState() { base.UpdateHoverState(); From 8d2e852ffd2bf8b8d76b4b4132ce3b4aa067e468 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Apr 2023 22:18:29 +0900 Subject: [PATCH 0501/1400] Fix overbearing key down handling --- .../Compose/Components/SelectionBoxRotationHandle.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index fb86cb4a01..73da837d03 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -81,24 +81,21 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override bool OnKeyDown(KeyDownEvent e) { - base.OnKeyDown(e); - - if (cumulativeRotation.Value != null && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) + if (IsDragged && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) { applyRotation(shouldSnap: true); + return true; } - return true; + return base.OnKeyDown(e); } protected override void OnKeyUp(KeyUpEvent e) { base.OnKeyUp(e); - if (cumulativeRotation.Value != null && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) - { + if (IsDragged && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight)) applyRotation(shouldSnap: false); - } } protected override void OnDragEnd(DragEndEvent e) From 13b522e825b6f1b2f1d7e843bd8fa2421f41d482 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 21:54:26 +0900 Subject: [PATCH 0502/1400] repair usage of CancellationToken Co-Authored-By: n0099 --- osu.Game/Database/LegacyModelExporter.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 6f2fe90957..e8fc25ab84 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -60,7 +60,7 @@ namespace osu.Game.Database /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. /// /// - public async Task ExportAsync(TModel model, CancellationToken? cancellationToken = null) + public async Task ExportAsync(TModel model, CancellationToken cancellationToken = default) { // check if the model is being exporting already if (!exporting_models.Contains(model)) @@ -93,7 +93,8 @@ namespace osu.Game.Database { using (var stream = exportStorage.CreateFileSafely(filename)) { - success = await ExportToStreamAsync(model, stream, notification, cancellationToken ?? notification.CancellationToken).ConfigureAwait(false); + success = await ExportToStreamAsync(model, stream, notification, + cancellationToken == CancellationToken.None ? notification.CancellationToken : cancellationToken).ConfigureAwait(false); } } catch (OperationCanceledException) From 1f4da35c8d75e77d3eadca6bbf7624cf2b63331c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 22:11:52 +0900 Subject: [PATCH 0503/1400] notification nullable fix --- osu.Game/Database/LegacyArchiveExporter.cs | 12 ++++++++---- osu.Game/Database/LegacyModelExporter.cs | 9 +++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 1af8c454c1..35f09189c9 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -25,7 +25,7 @@ namespace osu.Game.Database { } - protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) + protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) => exportZipArchive(model, outputStream, notification, cancellationToken); /// @@ -35,7 +35,7 @@ namespace osu.Game.Database /// The output stream to export to. /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. - private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default) + private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { try { @@ -67,8 +67,12 @@ namespace osu.Game.Database } i++; - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + + if (notification != null) + { + notification.Progress = i / model.Files.Count(); + notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + } } } catch (ObjectDisposedException) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index e8fc25ab84..0f09c2c19b 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -105,6 +105,7 @@ namespace osu.Game.Database // cleanup if export is failed or canceled. if (!success) { + notification.State = ProgressNotificationState.Cancelled; exportStorage.Delete(filename); } else @@ -129,27 +130,23 @@ namespace osu.Game.Database /// Whether the export was successful public Task ExportToStreamAsync(TModel model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) { - ProgressNotification notify = notification ?? new ProgressNotification(); - Guid id = model.ID; return Task.Run(() => { realmAccess.Run(r => { TModel refetchModel = r.Find(id); - ExportToStream(refetchModel, stream, notify, cancellationToken); + ExportToStream(refetchModel, stream, notification, cancellationToken); }); }, cancellationToken).ContinueWith(t => { if (cancellationToken.IsCancellationRequested) { - notify.State = ProgressNotificationState.Cancelled; return false; } if (t.IsFaulted) { - notify.State = ProgressNotificationState.Cancelled; Logger.Error(t.Exception, "An error occurred while exporting", LoggingTarget.Database); return false; } @@ -165,6 +162,6 @@ namespace osu.Game.Database /// The output stream to export to. /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. - protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification notification, CancellationToken cancellationToken = default); + protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default); } } From de21b4a2f73dfd6ee9278148b88b1f8ab92ca5af Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 22:15:00 +0900 Subject: [PATCH 0504/1400] use Live Use RealmAccess only when needed --- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 9 ++--- osu.Game/Beatmaps/BeatmapManager.cs | 4 +-- osu.Game/Database/LegacyArchiveExporter.cs | 4 +-- osu.Game/Database/LegacyBeatmapExporter.cs | 4 +-- osu.Game/Database/LegacyModelExporter.cs | 36 ++++++++++++------- osu.Game/Database/LegacyScoreExporter.cs | 5 ++- osu.Game/Database/LegacySkinExporter.cs | 3 +- .../Overlays/Settings/Sections/SkinSection.cs | 2 +- osu.Game/Scoring/ScoreManager.cs | 4 +-- osu.Game/Skinning/SkinManager.cs | 6 ++-- 10 files changed, 42 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 726ff74d7f..8043c01d2d 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -119,10 +119,7 @@ namespace osu.Game.Tests.Skins.IO var import1 = await loadSkinIntoOsu(osu, new ImportTask(createOskWithIni("name 1", "author 1"), "custom.osk")); assertCorrectMetadata(import1, "name 1 [custom]", "author 1", osu); - await import1.PerformRead(async s => - { - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); - }); + await new LegacySkinExporter(osu.Dependencies.Get()).ExportToStreamAsync(import1, exportStream); string exportFilename = import1.GetDisplayString(); @@ -203,7 +200,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(ArgonSkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); + await new LegacySkinExporter(osu.Dependencies.Get()).ExportToStreamAsync(skinManager.CurrentSkinInfo.Value, exportStream); Assert.Greater(exportStream.Length, 0); }); @@ -236,7 +233,7 @@ namespace osu.Game.Tests.Skins.IO Assert.IsFalse(s.Protected); Assert.AreEqual(typeof(DefaultLegacySkin), s.CreateInstance(skinManager).GetType()); - await new LegacySkinExporter(osu.Dependencies.Get(), osu.Dependencies.Get()).ExportToStreamAsync(s, exportStream); + await new LegacySkinExporter(osu.Dependencies.Get()).ExportToStreamAsync(skinManager.CurrentSkinInfo.Value, exportStream); Assert.Greater(exportStream.Length, 0); }); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index d3bf8081b1..877a0c7667 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -79,7 +79,7 @@ namespace osu.Game.Beatmaps workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); - beatmapExporter = new LegacyBeatmapExporter(storage, realm) + beatmapExporter = new LegacyBeatmapExporter(storage) { PostNotification = obj => PostNotification?.Invoke(obj) }; @@ -400,7 +400,7 @@ namespace osu.Game.Beatmaps public Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) => beatmapImporter.ImportAsUpdate(notification, importTask, original); - public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap); + public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap, Realm); private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 35f09189c9..297139a20e 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -20,8 +20,8 @@ namespace osu.Game.Database public abstract class LegacyArchiveExporter : LegacyModelExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { - protected LegacyArchiveExporter(Storage storage, RealmAccess realm) - : base(storage, realm) + protected LegacyArchiveExporter(Storage storage) + : base(storage) { } diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index 107b91a234..e89d3da8c7 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -8,8 +8,8 @@ namespace osu.Game.Database { public class LegacyBeatmapExporter : LegacyArchiveExporter { - public LegacyBeatmapExporter(Storage storage, RealmAccess realm) - : base(storage, realm) + public LegacyBeatmapExporter(Storage storage) + : base(storage) { } diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 0f09c2c19b..58606cb5fa 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -31,24 +31,35 @@ namespace osu.Game.Database private readonly Storage exportStorage; protected virtual string GetFilename(TModel item) => item.GetDisplayString(); - private readonly RealmAccess realmAccess; - public Action? PostNotification { get; set; } // Store the model being exporting. - private static readonly List exporting_models = new List(); + private static readonly List> exporting_models = new List>(); /// /// Construct exporter. /// Create a new exporter for each export, otherwise it will cause confusing notifications. /// /// Storage for storing exported files. Basically it is used to provide export stream - /// The RealmAccess used to provide the exported file. - protected LegacyModelExporter(Storage storage, RealmAccess realm) + protected LegacyModelExporter(Storage storage) { exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); - realmAccess = realm; + } + + /// + /// Export the model to default folder. + /// + /// The model should export. + /// Realm that convert model to Live. + /// + /// The Cancellation token that can cancel the exporting. + /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. + /// + /// + public Task ExportAsync(TModel model, RealmAccess realm, CancellationToken cancellationToken = default) + { + return ExportAsync(model.ToLive(realm), cancellationToken); } /// @@ -60,7 +71,7 @@ namespace osu.Game.Database /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. /// /// - public async Task ExportAsync(TModel model, CancellationToken cancellationToken = default) + public async Task ExportAsync(Live model, CancellationToken cancellationToken = default) { // check if the model is being exporting already if (!exporting_models.Contains(model)) @@ -73,7 +84,8 @@ namespace osu.Game.Database return false; } - string itemFilename = GetFilename(model).GetValidFilename(); + string itemFilename = model.PerformRead(s => GetFilename(s).GetValidFilename()); + IEnumerable existingExports = exportStorage .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") @@ -128,15 +140,13 @@ namespace osu.Game.Database /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. /// Whether the export was successful - public Task ExportToStreamAsync(TModel model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) + public Task ExportToStreamAsync(Live model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) { - Guid id = model.ID; return Task.Run(() => { - realmAccess.Run(r => + model.PerformRead(s => { - TModel refetchModel = r.Find(id); - ExportToStream(refetchModel, stream, notification, cancellationToken); + ExportToStream(s, stream, notification, cancellationToken); }); }, cancellationToken).ContinueWith(t => { diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index ef55ffdd96..bd7d273a64 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -13,8 +13,7 @@ namespace osu.Game.Database { public class LegacyScoreExporter : LegacyModelExporter { - public LegacyScoreExporter(Storage storage, RealmAccess realm) - : base(storage, realm) + public LegacyScoreExporter(Storage storage) : base(storage) { } @@ -28,7 +27,7 @@ namespace osu.Game.Database protected override string FileExtension => ".osr"; - protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification notification, CancellationToken cancellationToken = default) + protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification? notification, CancellationToken cancellationToken = default) { var file = model.Files.SingleOrDefault(); if (file == null) diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index d3e6a2f0f4..2a531203bc 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -8,8 +8,7 @@ namespace osu.Game.Database { public class LegacySkinExporter : LegacyArchiveExporter { - public LegacySkinExporter(Storage storage, RealmAccess realm) - : base(storage, realm) + public LegacySkinExporter(Storage storage) : base(storage) { } diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index df5d7e0c27..5382eac675 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -159,7 +159,7 @@ namespace osu.Game.Overlays.Settings.Sections { try { - skins.CurrentSkinInfo.Value.PerformRead(s => skins.ExportSkin(s)); + skins.ExportCurrentSkin(); } catch (Exception e) { diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 3201fec696..5e432b6a96 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -50,7 +50,7 @@ namespace osu.Game.Scoring PostNotification = obj => PostNotification?.Invoke(obj) }; - scoreExporter = new LegacyScoreExporter(storage, realm) + scoreExporter = new LegacyScoreExporter(storage) { PostNotification = obj => PostNotification?.Invoke(obj) }; @@ -193,7 +193,7 @@ namespace osu.Game.Scoring public Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) => scoreImporter.Import(notification, tasks); - public Task Export(ScoreInfo score) => scoreExporter.ExportAsync(score); + public Task Export(ScoreInfo score) => scoreExporter.ExportAsync(score, Realm); public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 1a76ec8623..45536e04eb 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -123,7 +123,7 @@ namespace osu.Game.Skinning SourceChanged?.Invoke(); }; - skinExporter = new LegacySkinExporter(storage, realm) + skinExporter = new LegacySkinExporter(storage) { PostNotification = obj => PostNotification?.Invoke(obj) }; @@ -305,7 +305,9 @@ namespace osu.Game.Skinning public Task> Import(ImportTask task, ImportParameters parameters = default, CancellationToken cancellationToken = default) => skinImporter.Import(task, parameters, cancellationToken); - public Task ExportSkin(SkinInfo skin) => skinExporter.ExportAsync(skin); + public Task ExportCurrentSkin() => ExportSkin(CurrentSkinInfo.Value); + + public Task ExportSkin(Live skin) => skinExporter.ExportAsync(skin); #endregion From 49193a2bdd950aab1a0d4183ce75b47e97050512 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 22:25:47 +0900 Subject: [PATCH 0505/1400] CompletionText Co-Authored-By: Dean Herbert --- osu.Game/Database/LegacyModelExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 58606cb5fa..a61d9fd582 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -122,7 +122,7 @@ namespace osu.Game.Database } else { - notification.CompletionText = "Export Complete, Click to open the folder"; + notification.CompletionText = $"Exported {itemFilename}! Click to view."; notification.CompletionClickAction = () => exportStorage.PresentFileExternally(filename); notification.State = ProgressNotificationState.Completed; } From fc55b96e776401b8b35737a49ba07ff309a0eef6 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 14:27:42 +0900 Subject: [PATCH 0506/1400] remove `CompletionText` in Constructor this will never used Co-Authored-By: Dean Herbert --- osu.Game/Database/LegacyModelExporter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index a61d9fd582..975809b9a7 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -97,7 +97,6 @@ namespace osu.Game.Database { State = ProgressNotificationState.Active, Text = "Exporting...", - CompletionText = "Export completed" }; PostNotification?.Invoke(notification); From 5d64c1b7bfd7fd5ce51a2df503735a4f794b9517 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 15:09:18 +0900 Subject: [PATCH 0507/1400] exception handling --- osu.Game/Database/LegacyModelExporter.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 1c5d6b4813..7904be7f4f 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -124,8 +124,15 @@ namespace osu.Game.Database cancellationToken == CancellationToken.None ? notification.CancellationToken : cancellationToken).ConfigureAwait(false); } } - catch (OperationCanceledException) + catch { + notification.State = ProgressNotificationState.Cancelled; + throw; + } + finally + { + // Determines whether to export repeatedly, so he must be removed from the list at the end whether there is a error. + exporting_models.Remove(model); } // cleanup if export is failed or canceled. @@ -141,7 +148,6 @@ namespace osu.Game.Database notification.State = ProgressNotificationState.Completed; } - exporting_models.Remove(model); return success; } @@ -171,7 +177,7 @@ namespace osu.Game.Database if (t.IsFaulted) { Logger.Error(t.Exception, "An error occurred while exporting", LoggingTarget.Database); - return false; + throw t.Exception!; } return true; From 52fc6de13f0be2f624e1a26be301f3f4e0c6c39e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 15:12:15 +0900 Subject: [PATCH 0508/1400] merge fix wtf? --- osu.Game.Tests/Database/LegacyExporterTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index d41b3a5017..2f92ec1a4c 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -110,9 +110,9 @@ namespace osu.Game.Tests.Database public override string ToString() => Filename; } - private class TestLegacyExporter : LegacyExporter + private class TestLegacyModelExporter : LegacyModelExporter { - public TestLegacyExporter(Storage storage) + public TestLegacyModelExporter(Storage storage) : base(storage) { } From def6da98fc8760c63efe8208241eea0c25dfd880 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 15:40:40 +0900 Subject: [PATCH 0509/1400] fix test in #22653 --- osu.Game.Tests/Database/LegacyExporterTest.cs | 96 +++++++++++++------ 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyExporterTest.cs index 2f92ec1a4c..c25e14d2ef 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyExporterTest.cs @@ -1,19 +1,26 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; +using osu.Framework.Extensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Database; +using osu.Game.Overlays.Notifications; +using Realms; namespace osu.Game.Tests.Database { [TestFixture] - public class LegacyExporterTest + public class LegacyModelExporterTest { - private TestLegacyExporter legacyExporter = null!; + private TestLegacyModelExporter legacyExporter = null!; private TemporaryNativeStorage storage = null!; private const string short_filename = "normal file name"; @@ -25,15 +32,15 @@ namespace osu.Game.Tests.Database public void SetUp() { storage = new TemporaryNativeStorage("export-storage"); - legacyExporter = new TestLegacyExporter(storage); + legacyExporter = new TestLegacyModelExporter(storage); } [Test] public void ExportFileWithNormalNameTest() { - var item = new TestPathInfo(short_filename); + var item = new TestRealmObject(short_filename); - Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); + Assert.That(item.Filename.Length, Is.LessThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); exportItemAndAssert(item, short_filename); } @@ -41,9 +48,9 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameMultipleTimesTest() { - var item = new TestPathInfo(short_filename); + var item = new TestRealmObject(short_filename); - Assert.That(item.Filename.Length, Is.LessThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); + Assert.That(item.Filename.Length, Is.LessThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); //Export multiple times for (int i = 0; i < 100; i++) @@ -56,24 +63,24 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithSuperLongNameTest() { - int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); + int expectedLength = TestLegacyModelExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); - var item = new TestPathInfo(long_filename); + var item = new TestRealmObject(long_filename); - Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); + Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); exportItemAndAssert(item, expectedName); } [Test] public void ExportFileWithSuperLongNameMultipleTimesTest() { - int expectedLength = TestLegacyExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); + int expectedLength = TestLegacyModelExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); - var item = new TestPathInfo(long_filename); + var item = new TestRealmObject(long_filename); - Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyExporter.MAX_FILENAME_LENGTH)); + Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); //Export multiple times for (int i = 0; i < 100; i++) @@ -83,9 +90,14 @@ namespace osu.Game.Tests.Database } } - private void exportItemAndAssert(IHasNamedFiles item, string expectedName) + private void exportItemAndAssert(TestRealmObject item, string expectedName) { - Assert.DoesNotThrow(() => legacyExporter.Export(item)); + // ReSharper disable once AsyncVoidLambda + Assert.DoesNotThrow(() => + { + Task t = Task.Run(() => legacyExporter.ExportAsync(new TestRealmLive(item))); + t.WaitSafely(); + }); Assert.That(storage.Exists($"exports/{expectedName}{legacyExporter.GetExtension()}"), Is.True); } @@ -96,21 +108,7 @@ namespace osu.Game.Tests.Database storage.Dispose(); } - private class TestPathInfo : IHasNamedFiles - { - public string Filename { get; } - - public IEnumerable Files { get; } = new List(); - - public TestPathInfo(string filename) - { - Filename = filename; - } - - public override string ToString() => Filename; - } - - private class TestLegacyModelExporter : LegacyModelExporter + private class TestLegacyModelExporter : LegacyModelExporter { public TestLegacyModelExporter(Storage storage) : base(storage) @@ -119,7 +117,45 @@ namespace osu.Game.Tests.Database public string GetExtension() => FileExtension; + protected override void ExportToStream(TestRealmObject model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) + { + } + protected override string FileExtension => ".test"; } + + private class TestRealmObject : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey + { + public Guid ID => throw new NotImplementedException(); + public string Filename { get; } + + public IEnumerable Files { get; } = new List(); + + public TestRealmObject(string filename) + { + Filename = filename; + } + + public override string ToString() => Filename; + } + + private class TestRealmLive : Live + { + public override void PerformRead(Action perform) => perform(Value); + + public override TReturn PerformRead(Func perform) => perform(Value); + + public override void PerformWrite(Action perform) => throw new NotImplementedException(); + + public override bool IsManaged => throw new NotImplementedException(); + + public override TestRealmObject Value { get; } + + public TestRealmLive(TestRealmObject model) + : base(Guid.Empty) + { + Value = model; + } + } } } From dd690891175a8597e72005782965c762052a5672 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 9 Apr 2023 15:43:18 +0900 Subject: [PATCH 0510/1400] code quality --- .../{LegacyExporterTest.cs => LegacyModelExporterTest.cs} | 1 - osu.Game/Database/LegacyModelExporter.cs | 2 +- osu.Game/Database/LegacyScoreExporter.cs | 3 ++- osu.Game/Database/LegacySkinExporter.cs | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) rename osu.Game.Tests/Database/{LegacyExporterTest.cs => LegacyModelExporterTest.cs} (99%) diff --git a/osu.Game.Tests/Database/LegacyExporterTest.cs b/osu.Game.Tests/Database/LegacyModelExporterTest.cs similarity index 99% rename from osu.Game.Tests/Database/LegacyExporterTest.cs rename to osu.Game.Tests/Database/LegacyModelExporterTest.cs index c25e14d2ef..27059c3058 100644 --- a/osu.Game.Tests/Database/LegacyExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyModelExporterTest.cs @@ -92,7 +92,6 @@ namespace osu.Game.Tests.Database private void exportItemAndAssert(TestRealmObject item, string expectedName) { - // ReSharper disable once AsyncVoidLambda Assert.DoesNotThrow(() => { Task t = Task.Run(() => legacyExporter.ExportAsync(new TestRealmLive(item))); diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyModelExporter.cs index 7904be7f4f..0e4fefae5c 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyModelExporter.cs @@ -107,7 +107,7 @@ namespace osu.Game.Database .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") .Concat(exportStorage.GetDirectories(string.Empty)); string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - bool success = false; + bool success; ProgressNotification notification = new ProgressNotification { diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index bd7d273a64..e7473c963b 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -13,7 +13,8 @@ namespace osu.Game.Database { public class LegacyScoreExporter : LegacyModelExporter { - public LegacyScoreExporter(Storage storage) : base(storage) + public LegacyScoreExporter(Storage storage) + : base(storage) { } diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 2a531203bc..4775a54c13 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -8,7 +8,8 @@ namespace osu.Game.Database { public class LegacySkinExporter : LegacyArchiveExporter { - public LegacySkinExporter(Storage storage) : base(storage) + public LegacySkinExporter(Storage storage) + : base(storage) { } From c9234829762667d18272bf187885b0804ee51c1d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 10 Apr 2023 13:31:48 +0900 Subject: [PATCH 0511/1400] Add progressive score multiplier for DT --- .../Mods/CatchModDoubleTime.cs | 1 - .../Mods/ManiaModDoubleTime.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs | 1 - .../Mods/TaikoModDoubleTime.cs | 1 - osu.Game/Rulesets/Mods/ModDoubleTime.cs | 17 +++++++++++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs index 57c06e1cd1..83db9f665b 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs index a302f95966..f4b9cf3b88 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => 1; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs index 700a3f44bc..5569df8d95 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs index 89581c57bd..e517439ba4 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModDoubleTime : ModDoubleTime { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 9e4469bf25..733610c040 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -24,5 +24,22 @@ namespace osu.Game.Rulesets.Mods MaxValue = 2, Precision = 0.01, }; + + public override double ScoreMultiplier + { + get + { + // Round to the nearest multiple of 0.1. + double value = (int)(SpeedChange.Value * 10) / 10.0; + + // Offset back to 0. + value -= 1; + + // Each 0.1 multiple changes score multiplier by 0.02. + value /= 5; + + return 1 + value; + } + } } } From 15f6bc155eb49f1fca344e6901d5ec12b8480201 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 10 Apr 2023 13:35:48 +0900 Subject: [PATCH 0512/1400] Add progressive score multiplier for HT --- osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs | 1 - osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs | 1 - osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs | 1 - osu.Game/Rulesets/Mods/ModHalfTime.cs | 14 ++++++++++++++ 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs index ce06b841aa..3afb8c3d89 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModHalfTime : ModHalfTime { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs index 014954dd60..8d48e3acde 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModHalfTime : ModHalfTime { - public override double ScoreMultiplier => 0.5; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs index 4769e7660b..bf65a6c9d3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModHalfTime : ModHalfTime { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs index 68d6305fbf..9ef6fe8649 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModHalfTime : ModHalfTime { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 7d858dca6f..06c7750035 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -24,5 +24,19 @@ namespace osu.Game.Rulesets.Mods MaxValue = 0.99, Precision = 0.01, }; + + public override double ScoreMultiplier + { + get + { + // Round to the nearest multiple of 0.1. + double value = (int)(SpeedChange.Value * 10) / 10.0; + + // Offset back to 0. + value -= 1; + + return 1 + value; + } + } } } From bfb7ead6898424220bc63c73db34397462eba685 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 9 Apr 2023 22:04:07 -0700 Subject: [PATCH 0513/1400] Add failing text box beatmap difficulty count test --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index feab86d3ee..a103cf759f 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -1068,6 +1068,21 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("options disabled", () => !songSelect.ChildrenOfType().Single().Enabled.Value); } + [Test] + public void TestTextBoxBeatmapDifficultyCount() + { + createSongSelect(); + + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmaps"); + + addRulesetImportStep(0); + + AddAssert("3 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "3 matching beatmaps"); + AddStep("delete all beatmaps", () => manager.Delete()); + AddUntilStep("wait for no beatmap", () => Beatmap.IsDefault); + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmaps"); + } + private void waitForInitialSelection() { AddUntilStep("wait for initial selection", () => !Beatmap.IsDefault); From 7f5b99c91b3dad9985bb6e0aaca0d8ad8d1ba84e Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Fri, 7 Apr 2023 22:32:12 -0700 Subject: [PATCH 0514/1400] Fix song select beatmap difficulty count not updating when deleting --- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 +++++++ osu.Game/Screens/Select/SongSelect.cs | 1 + 2 files changed, 8 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 68d3247275..36fc01613e 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -49,6 +49,11 @@ namespace osu.Game.Screens.Select /// public Action? BeatmapSetsChanged; + /// + /// Triggered when the deleted change. + /// + public Action? DeletedBeatmapSetsChanged; + /// /// Triggered after filter conditions have finished being applied to the model hierarchy. /// @@ -353,6 +358,8 @@ namespace osu.Game.Screens.Select if (!Scroll.UserScrolling) ScrollToSelected(true); + + DeletedBeatmapSetsChanged?.Invoke(); }); public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index c5e914b461..41cbfea0fc 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -162,6 +162,7 @@ namespace osu.Game.Screens.Select BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, + DeletedBeatmapSetsChanged = updateVisibleBeatmapCount, FilterApplied = updateVisibleBeatmapCount, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); From ad51f880e04a39cfddfb70f08ab87e08448a9096 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 10 Apr 2023 17:49:29 +0900 Subject: [PATCH 0515/1400] Remove overrides on DC/NC mods --- osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs | 1 - osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs | 1 - osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs | 1 - osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs | 1 - osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs | 1 - osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs | 1 - 8 files changed, 8 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs index cae19e9468..180cb98ed7 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModDaycore : ModDaycore { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs index 9e38913be7..c537897439 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs @@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModNightcore : ModNightcore { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs index bec0a6a1d3..309393b664 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModDaycore : ModDaycore { - public override double ScoreMultiplier => 0.5; } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs index 4cc712060c..748725af9f 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModNightcore : ModNightcore { - public override double ScoreMultiplier => 1; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs index 371dfe6a1a..1de6b9ce55 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModDaycore : ModDaycore { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs index b7838ebaa7..661cc948c5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs @@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Osu.Mods { public class OsuModNightcore : ModNightcore { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs index 84aa5e6bba..f442435d9c 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs @@ -7,6 +7,5 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModDaycore : ModDaycore { - public override double ScoreMultiplier => 0.3; } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs index 7cb14635ff..ad5da3d601 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs @@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModNightcore : ModNightcore { - public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.12 : 1; } } From 641415ca3263fdff295402f965a5562c309ea8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 14:05:32 +0200 Subject: [PATCH 0516/1400] Unify displayed duration format for single/multiple selection --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index 02270d4662..d0a022744f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -121,10 +121,10 @@ namespace osu.Game.Rulesets.Edit addValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); addHeader("Start Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}"); + addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}ms"); addHeader("End Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}"); + addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}ms"); break; } From 60358c720392264ab4b1c51bbca89aa72710300d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 14:13:53 +0200 Subject: [PATCH 0517/1400] Perform first inspector text update immediately Provides better and more consistent initial state for the inspector. --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index d0a022744f..977d00ede2 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -46,6 +46,7 @@ namespace osu.Game.Rulesets.Edit EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, _) => updateInspectorText(); EditorBeatmap.TransactionBegan += updateInspectorText; EditorBeatmap.TransactionEnded += updateInspectorText; + updateInspectorText(); } private ScheduledDelegate? rollingTextUpdate; From 6fec476147b04d30be33bcba642c262fd6a8c811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 14:55:30 +0200 Subject: [PATCH 0518/1400] Simplify snap implementation --- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 73da837d03..bee768ad50 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -129,10 +129,6 @@ namespace osu.Game.Screens.Edit.Compose.Components TooltipText = newRotation.ToLocalisableString(tooltipFormat); } - private float snap(float value, float step) - { - float floor = MathF.Floor(value / step) * step; - return value - floor < step / 2f ? floor : floor + step; - } + private float snap(float value, float step) => MathF.Round(value / step) * step; } } From 73bd0feef58ed190df4317b507a9a4cae882fa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 15:03:33 +0200 Subject: [PATCH 0519/1400] Fix incorrectly implemented localisation --- osu.Game/Localisation/EditorStrings.cs | 8 ++++---- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index beddcfd44e..7c9b52275d 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -100,14 +100,14 @@ namespace osu.Game.Localisation public static LocalisableString TimelineTicks => new TranslatableString(getKey(@"timeline_ticks"), @"Ticks"); /// - /// "0.0°" + /// "{0:0.0}°" /// - public static LocalisableString RotationFormatUnsnapped => new TranslatableString(getKey(@"rotation_format_unsnapped"), @"0.0°"); + public static LocalisableString RotationUnsnapped(float newRotation) => new TranslatableString(getKey(@"rotation_unsnapped"), @"{0:0.0}°", newRotation); /// - /// "0.0° (snapped)" + /// "{0:0.0}° (snapped)" /// - public static LocalisableString RotationFormatSnapped => new TranslatableString(getKey(@"rotation_format_snapped"), @"0.0° (snapped)"); + public static LocalisableString RotationSnapped(float newRotation) => new TranslatableString(getKey(@"rotation_snapped"), @"{0:0.0}° (snapped)", newRotation); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index bee768ad50..305f5bf3c4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -7,7 +7,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.EnumExtensions; -using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; @@ -125,8 +124,7 @@ namespace osu.Game.Screens.Edit.Compose.Components cumulativeRotation.Value = newRotation; HandleRotate?.Invoke(newRotation - oldRotation); - string tooltipFormat = shouldSnap ? EditorStrings.RotationFormatSnapped.ToString() : EditorStrings.RotationFormatUnsnapped.ToString(); - TooltipText = newRotation.ToLocalisableString(tooltipFormat); + TooltipText = shouldSnap ? EditorStrings.RotationSnapped(newRotation) : EditorStrings.RotationUnsnapped(newRotation); } private float snap(float value, float step) => MathF.Round(value / step) * step; From 11fd93a2baec751af641692664cbf3387871839d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 15:19:54 +0200 Subject: [PATCH 0520/1400] Inline disturbing `getGuestMapper()` method Disturbing because name suggests pure method, but it is in fact `void` and also performs side effects by about the most confusing means possible. --- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 27e671ded0..104f861df7 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -214,22 +214,17 @@ namespace osu.Game.Overlays.BeatmapSet if (beatmapInfo?.AuthorID != BeatmapSet?.AuthorID) { APIUser? user = BeatmapSet?.RelatedUsers?.SingleOrDefault(u => u.OnlineID == beatmapInfo?.AuthorID); + if (user != null) - getGuestMapper(user); + { + guestMapperContainer.AddText("mapped by "); + guestMapperContainer.AddUserLink(user); + } } version.Text = beatmapInfo?.DifficultyName ?? string.Empty; } - private void getGuestMapper(APIUser user) - { - guestMapperContainer.With(d => - { - d.AddText("mapped by "); - d.AddUserLink(user); - }); - } - private void updateDifficultyButtons() { Difficulties.Children.ToList().ForEach(diff => diff.State = diff.Beatmap == Beatmap.Value ? DifficultySelectorState.Selected : DifficultySelectorState.NotSelected); From 6e08105e2c37656801dda1d0583525a549f049e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 10 Apr 2023 15:27:10 +0200 Subject: [PATCH 0521/1400] Remove usage of "diff" vernacular --- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 4838f42043..a27c4ddad2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -283,15 +283,15 @@ namespace osu.Game.Tests.Visual.Online } [Test] - public void TestBeatmapSetWithGuestDIff() + public void TestBeatmapSetWithGuestDifficulty() { - AddStep("show map", () => overlay.ShowBeatmapSet(createBeatmapSetWithGuestDiff())); - AddStep("move mouse to host diff", () => + AddStep("show map", () => overlay.ShowBeatmapSet(createBeatmapSetWithGuestDifficulty())); + AddStep("move mouse to host difficulty", () => { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(0)); }); AddAssert("guest mapper information not shown", () => overlay.ChildrenOfType().Single().ChildrenOfType().All(s => s.Text != "BanchoBot")); - AddStep("move mouse to guest diff", () => + AddStep("move mouse to guest difficulty", () => { InputManager.MoveMouseTo(overlay.ChildrenOfType().ElementAt(1)); }); @@ -337,7 +337,7 @@ namespace osu.Game.Tests.Visual.Online return beatmapSet; } - private APIBeatmapSet createBeatmapSetWithGuestDiff() + private APIBeatmapSet createBeatmapSetWithGuestDifficulty() { var set = getBeatmapSet(); From c7dea717931631e02ef80c5222b6eed2b96e458c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 10 Apr 2023 11:26:18 -0700 Subject: [PATCH 0522/1400] Use existing `BeatmapSetsChanged` action --- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 +------ osu.Game/Screens/Select/SongSelect.cs | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 36fc01613e..d6359dd62e 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -49,11 +49,6 @@ namespace osu.Game.Screens.Select /// public Action? BeatmapSetsChanged; - /// - /// Triggered when the deleted change. - /// - public Action? DeletedBeatmapSetsChanged; - /// /// Triggered after filter conditions have finished being applied to the model hierarchy. /// @@ -359,7 +354,7 @@ namespace osu.Game.Screens.Select if (!Scroll.UserScrolling) ScrollToSelected(true); - DeletedBeatmapSetsChanged?.Invoke(); + BeatmapSetsChanged?.Invoke(); }); public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() => diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 41cbfea0fc..c5e914b461 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -162,7 +162,6 @@ namespace osu.Game.Screens.Select BleedBottom = Footer.HEIGHT, SelectionChanged = updateSelectedBeatmap, BeatmapSetsChanged = carouselBeatmapsLoaded, - DeletedBeatmapSetsChanged = updateVisibleBeatmapCount, FilterApplied = updateVisibleBeatmapCount, GetRecommendedBeatmap = s => recommender?.GetRecommendedBeatmap(s), }, c => carouselContainer.Child = c); From f80de08f24e5176bc1d3bb79b994e1e1717d059d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 10 Apr 2023 11:28:23 -0700 Subject: [PATCH 0523/1400] Adjust `BeatmapSetsChanged` xmldoc Co-Authored-By: Dean Herbert --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index d6359dd62e..6ba9843f7b 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Select public float BleedBottom { get; set; } /// - /// Triggered when the loaded change and are completely loaded. + /// Triggered when finish loading, or are subsequently changed. /// public Action? BeatmapSetsChanged; From d0cbe206a949452c6bb4a0116470babc95aa9b36 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 10 Apr 2023 23:37:29 -0700 Subject: [PATCH 0524/1400] Revert back to one number with "matching beatmap difficulties" label --- .../Visual/SongSelect/TestScenePlaySongSelect.cs | 6 +++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 +------ osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index a103cf759f..c9a7cf37a8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -1073,14 +1073,14 @@ namespace osu.Game.Tests.Visual.SongSelect { createSongSelect(); - AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmaps"); + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmap difficulties"); addRulesetImportStep(0); - AddAssert("3 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "3 matching beatmaps"); + AddAssert("3 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "3 matching beatmap difficulties"); AddStep("delete all beatmaps", () => manager.Delete()); AddUntilStep("wait for no beatmap", () => Beatmap.IsDefault); - AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmaps"); + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmap difficulties"); } private void waitForInitialSelection() diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index d5ddc375b7..6ba9843f7b 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -64,12 +64,7 @@ namespace osu.Game.Screens.Select /// /// The total count of non-filtered beatmaps displayed. /// - public int CountDisplayedBeatmaps => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.Beatmaps.Count(b => !b.Filtered.Value)); - - /// - /// The total count of non-filtered beatmap sets displayed. - /// - public int CountDisplayedSets => beatmapSets.Count(s => !s.Filtered.Value); + public int CountDisplayed => beatmapSets.Where(s => !s.Filtered.Value).Sum(s => s.Beatmaps.Count(b => !b.Filtered.Value)); /// /// The currently selected beatmap set. diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7191ff7c2a..09ccee3717 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -864,7 +864,7 @@ namespace osu.Game.Screens.Select { // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // but also in this case we want support for formatting a number within a string). - FilterControl.InformationalText = $"{"matching beatmap".ToQuantity(Carousel.CountDisplayedSets, "#,0")} ({"difficulty".ToQuantity(Carousel.CountDisplayedBeatmaps, "#,0")})"; + FilterControl.InformationalText = $"{"matching beatmap difficulty".ToQuantity(Carousel.CountDisplayed, "#,0")}"; } private bool boundLocalBindables; From 0cc92ce5f926d91978c8903d3883fa70c61cf4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 11 Apr 2023 17:51:01 +0200 Subject: [PATCH 0525/1400] Add failing test case Covering nested object reverts not firing the parent's `RevertResult` event in accordance with what the xmldoc of the event states. --- .../Gameplay/TestScenePoolingRuleset.cs | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs index 0469df1de3..d16f51f36e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs @@ -164,6 +164,36 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("all results reverted", () => playfield.JudgedObjects.Count, () => Is.EqualTo(0)); } + [Test] + public void TestRevertNestedObjects() + { + ManualClock clock = null; + + var beatmap = new Beatmap(); + beatmap.HitObjects.Add(new TestHitObjectWithNested { Duration = 40 }); + + createTest(beatmap, 10, () => new FramedClock(clock = new ManualClock())); + + AddStep("skip to middle of object", () => clock.CurrentTime = (beatmap.HitObjects[0].StartTime + beatmap.HitObjects[0].GetEndTime()) / 2); + AddAssert("2 objects judged", () => playfield.JudgedObjects.Count, () => Is.EqualTo(2)); + + AddStep("skip to before end of object", () => clock.CurrentTime = beatmap.HitObjects[0].GetEndTime() - 1); + AddAssert("3 objects judged", () => playfield.JudgedObjects.Count, () => Is.EqualTo(3)); + + DrawableHitObject drawableHitObject = null; + HashSet revertedHitObjects = new HashSet(); + + AddStep("retrieve drawable hit object", () => drawableHitObject = playfield.ChildrenOfType().Single()); + AddStep("set up revert tracking", () => + { + revertedHitObjects.Clear(); + drawableHitObject.OnRevertResult += (ho, _) => revertedHitObjects.Add(ho.HitObject); + }); + AddStep("skip back to object start", () => clock.CurrentTime = beatmap.HitObjects[0].StartTime); + AddAssert("3 reverts fired", () => revertedHitObjects, () => Has.Count.EqualTo(3)); + AddAssert("no objects judged", () => playfield.JudgedObjects.Count, () => Is.EqualTo(0)); + } + [Test] public void TestApplyHitResultOnKilled() { @@ -258,6 +288,8 @@ namespace osu.Game.Tests.Visual.Gameplay { RegisterPool(poolSize); RegisterPool(poolSize); + RegisterPool(poolSize); + RegisterPool(poolSize); } protected override HitObjectLifetimeEntry CreateLifetimeEntry(HitObject hitObject) => new TestHitObjectLifetimeEntry(hitObject); @@ -388,6 +420,120 @@ namespace osu.Game.Tests.Visual.Gameplay } } + private class TestHitObjectWithNested : TestHitObject + { + protected override void CreateNestedHitObjects(CancellationToken cancellationToken) + { + base.CreateNestedHitObjects(cancellationToken); + + for (int i = 0; i < 3; ++i) + AddNested(new NestedHitObject { StartTime = (float)Duration * (i + 1) / 4 }); + } + } + + private class NestedHitObject : ConvertHitObject + { + } + + private partial class DrawableTestHitObjectWithNested : DrawableHitObject + { + private Container nestedContainer; + + public DrawableTestHitObjectWithNested() + : base(null) + { + } + + [BackgroundDependencyLoader] + private void load() + { + AddRangeInternal(new Drawable[] + { + new Circle + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Red + }, + nestedContainer = new Container + { + RelativeSizeAxes = Axes.Both + } + }); + } + + protected override void OnApply() + { + base.OnApply(); + + Size = new Vector2(200, 50); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + protected override void AddNestedHitObject(DrawableHitObject hitObject) + { + base.AddNestedHitObject(hitObject); + nestedContainer.Add(hitObject); + } + + protected override void ClearNestedHitObjects() + { + base.ClearNestedHitObjects(); + nestedContainer.Clear(false); + } + + protected override void CheckForResult(bool userTriggered, double timeOffset) + { + base.CheckForResult(userTriggered, timeOffset); + if (timeOffset >= 0) + ApplyResult(r => r.Type = r.Judgement.MaxResult); + } + } + + private partial class DrawableNestedHitObject : DrawableHitObject + { + public DrawableNestedHitObject() + : this(null) + { + } + + public DrawableNestedHitObject(NestedHitObject hitObject) + : base(hitObject) + { + Size = new Vector2(15); + Colour = Colour4.White; + RelativePositionAxes = Axes.Both; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(new Circle + { + RelativeSizeAxes = Axes.Both, + }); + } + + protected override void OnApply() + { + base.OnApply(); + + X = (float)((HitObject.StartTime - ParentHitObject!.HitObject.StartTime) / (ParentHitObject.HitObject.GetEndTime() - ParentHitObject.HitObject.StartTime)); + Y = 0.5f; + + LifetimeStart = ParentHitObject.LifetimeStart; + LifetimeEnd = ParentHitObject.LifetimeEnd; + } + + protected override void CheckForResult(bool userTriggered, double timeOffset) + { + base.CheckForResult(userTriggered, timeOffset); + if (timeOffset >= 0) + ApplyResult(r => r.Type = r.Judgement.MaxResult); + } + } + #endregion } } From db86ced4b4077f042af4e865c8bad859c3cfff23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 11 Apr 2023 17:59:33 +0200 Subject: [PATCH 0526/1400] Invoke `RevertResult` on parent DHO when nested DHO is reverted The behaviour described above was removed in 812a4b412a2c1b13a1e1215a00f863ef6fd83e45, thus henceforth contradicting `RevertResult`'s xmldoc. As it is relied on by some external rulesets, bring it back to unbreak them. --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 0c50f8341a..f6c3452e48 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -239,6 +239,7 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNestedDrawableCreated?.Invoke(drawableNested); drawableNested.OnNewResult += onNewResult; + drawableNested.OnRevertResult += onNestedRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; // This is only necessary for non-pooled DHOs. For pooled DHOs, this is handled inside GetPooledDrawableRepresentation(). @@ -312,6 +313,7 @@ namespace osu.Game.Rulesets.Objects.Drawables foreach (var obj in nestedHitObjects) { obj.OnNewResult -= onNewResult; + obj.OnRevertResult -= onNestedRevertResult; obj.ApplyCustomUpdateState -= onApplyCustomUpdateState; } @@ -376,6 +378,8 @@ namespace osu.Game.Rulesets.Objects.Drawables OnRevertResult?.Invoke(this, Result); } + private void onNestedRevertResult(DrawableHitObject drawableHitObject, JudgementResult result) => OnRevertResult?.Invoke(drawableHitObject, result); + private void onApplyCustomUpdateState(DrawableHitObject drawableHitObject, ArmedState state) => ApplyCustomUpdateState?.Invoke(drawableHitObject, state); private void onDefaultsApplied(HitObject hitObject) From e72f103c1759e61c3afa7080f962c639265996c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 11 Apr 2023 21:42:55 +0200 Subject: [PATCH 0527/1400] Do not look up metadata for locally-modified beatmaps on save --- osu.Game/Beatmaps/BeatmapImporter.cs | 6 ++--- osu.Game/Beatmaps/BeatmapManager.cs | 15 ++++++++--- .../Beatmaps/BeatmapOnlineChangeIngest.cs | 2 +- osu.Game/Beatmaps/BeatmapUpdater.cs | 13 +++++----- osu.Game/Beatmaps/MetadataLookupScope.cs | 26 +++++++++++++++++++ osu.Game/OsuGameBase.cs | 2 +- 6 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 osu.Game/Beatmaps/MetadataLookupScope.cs diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 4752a88199..4731a70753 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -35,7 +35,7 @@ namespace osu.Game.Beatmaps protected override string[] HashableFileTypes => new[] { ".osu" }; - public Action<(BeatmapSetInfo beatmapSet, bool isBatch)>? ProcessBeatmap { private get; set; } + public ProcessBeatmapDelegate? ProcessBeatmap { private get; set; } public BeatmapImporter(Storage storage, RealmAccess realm) : base(storage, realm) @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps first.PerformRead(s => { // Re-run processing even in this case. We might have outdated metadata. - ProcessBeatmap?.Invoke((s, false)); + ProcessBeatmap?.Invoke(s, MetadataLookupScope.OnlineFirst); }); return first; } @@ -206,7 +206,7 @@ namespace osu.Game.Beatmaps protected override void PostImport(BeatmapSetInfo model, Realm realm, ImportParameters parameters) { base.PostImport(model, realm, parameters); - ProcessBeatmap?.Invoke((model, parameters.Batch)); + ProcessBeatmap?.Invoke(model, parameters.Batch ? MetadataLookupScope.LocalCacheFirst : MetadataLookupScope.OnlineFirst); } private void validateOnlineIds(BeatmapSetInfo beatmapSet, Realm realm) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index ad56bbbc3a..cab49b7d69 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -42,7 +42,7 @@ namespace osu.Game.Beatmaps private readonly WorkingBeatmapCache workingBeatmapCache; - public Action<(BeatmapSetInfo beatmapSet, bool isBatch)>? ProcessBeatmap { private get; set; } + public ProcessBeatmapDelegate? ProcessBeatmap { private get; set; } public override bool PauseImports { @@ -72,7 +72,7 @@ namespace osu.Game.Beatmaps BeatmapTrackStore = audioManager.GetTrackStore(userResources); beatmapImporter = CreateBeatmapImporter(storage, realm); - beatmapImporter.ProcessBeatmap = args => ProcessBeatmap?.Invoke(args); + beatmapImporter.ProcessBeatmap = (beatmapSet, scope) => ProcessBeatmap?.Invoke(beatmapSet, scope); beatmapImporter.PostNotification = obj => PostNotification?.Invoke(obj); workingBeatmapCache = CreateWorkingBeatmapCache(audioManager, gameResources, userResources, defaultBeatmap, host); @@ -454,7 +454,9 @@ namespace osu.Game.Beatmaps if (transferCollections) beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); - ProcessBeatmap?.Invoke((liveBeatmapSet, false)); + // do not look up metadata. + // this is a locally-modified set now, so looking up metadata is busy work at best and harmful at worst. + ProcessBeatmap?.Invoke(liveBeatmapSet, MetadataLookupScope.None); }); } @@ -542,4 +544,11 @@ namespace osu.Game.Beatmaps public override string HumanisedModelName => "beatmap"; } + + /// + /// Delegate type for beatmap processing callbacks. + /// + /// The beatmap set to be processed. + /// The scope to use when looking up metadata. + public delegate void ProcessBeatmapDelegate(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope); } diff --git a/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs index 98aefd75d3..b160043820 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineChangeIngest.cs @@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps var matchingSet = r.All().FirstOrDefault(s => s.OnlineID == id); if (matchingSet != null) - beatmapUpdater.Queue(matchingSet.ToLive(realm), true); + beatmapUpdater.Queue(matchingSet.ToLive(realm), MetadataLookupScope.OnlineFirst); } }); } diff --git a/osu.Game/Beatmaps/BeatmapUpdater.cs b/osu.Game/Beatmaps/BeatmapUpdater.cs index d7b1fac7b3..af9f32f834 100644 --- a/osu.Game/Beatmaps/BeatmapUpdater.cs +++ b/osu.Game/Beatmaps/BeatmapUpdater.cs @@ -42,24 +42,25 @@ namespace osu.Game.Beatmaps /// Queue a beatmap for background processing. /// /// The managed beatmap set to update. A transaction will be opened to apply changes. - /// Whether metadata from an online source should be preferred. If true, the local cache will be skipped to ensure the freshest data state possible. - public void Queue(Live beatmapSet, bool preferOnlineFetch = false) + /// The preferred scope to use for metadata lookup. + public void Queue(Live beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst) { Logger.Log($"Queueing change for local beatmap {beatmapSet}"); - Task.Factory.StartNew(() => beatmapSet.PerformRead(b => Process(b, preferOnlineFetch)), default, TaskCreationOptions.HideScheduler | TaskCreationOptions.RunContinuationsAsynchronously, updateScheduler); + Task.Factory.StartNew(() => beatmapSet.PerformRead(b => Process(b, lookupScope)), default, TaskCreationOptions.HideScheduler | TaskCreationOptions.RunContinuationsAsynchronously, updateScheduler); } /// /// Run all processing on a beatmap immediately. /// /// The managed beatmap set to update. A transaction will be opened to apply changes. - /// Whether metadata from an online source should be preferred. If true, the local cache will be skipped to ensure the freshest data state possible. - public void Process(BeatmapSetInfo beatmapSet, bool preferOnlineFetch = false) => beatmapSet.Realm.Write(r => + /// The preferred scope to use for metadata lookup. + public void Process(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst) => beatmapSet.Realm.Write(r => { // Before we use below, we want to invalidate. workingBeatmapCache.Invalidate(beatmapSet); - metadataLookup.Update(beatmapSet, preferOnlineFetch); + if (lookupScope != MetadataLookupScope.None) + metadataLookup.Update(beatmapSet, lookupScope == MetadataLookupScope.OnlineFirst); foreach (var beatmap in beatmapSet.Beatmaps) { diff --git a/osu.Game/Beatmaps/MetadataLookupScope.cs b/osu.Game/Beatmaps/MetadataLookupScope.cs new file mode 100644 index 0000000000..e1fbedc26a --- /dev/null +++ b/osu.Game/Beatmaps/MetadataLookupScope.cs @@ -0,0 +1,26 @@ +// 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.Beatmaps +{ + /// + /// Determines which sources (if any at all) should be queried in which order for a beatmap's metadata. + /// + public enum MetadataLookupScope + { + /// + /// Do not attempt to look up the beatmap metadata either in the local cache or online. + /// + None, + + /// + /// Try the local metadata cache first before querying online sources. + /// + LocalCacheFirst, + + /// + /// Query online sources immediately. + /// + OnlineFirst + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 8f27e5dc53..34e31b0d61 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -310,7 +310,7 @@ namespace osu.Game base.Content.Add(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient)); - BeatmapManager.ProcessBeatmap = args => beatmapUpdater.Process(args.beatmapSet, !args.isBatch); + BeatmapManager.ProcessBeatmap = (beatmapSet, scope) => beatmapUpdater.Process(beatmapSet, scope); dependencies.Cache(userCache = new UserLookupCache()); base.Content.Add(userCache); From fbb15fff26ad91ceeccf9facc030fd6e6b503b1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2023 23:03:16 +0900 Subject: [PATCH 0528/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4b89e82729..a93b450ebb 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b9c6c1df9d..0ec65f4daf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 083d8192ea..3862ddacdb 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From c3f3b8db7c8c6e32d10066650eb89f4933d3d94f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2023 23:09:46 +0900 Subject: [PATCH 0529/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0ec65f4daf..578b8512e7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From c0a25144cf458a979348ac8637087eb33428d3a4 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 18 Apr 2023 11:31:56 +0900 Subject: [PATCH 0530/1400] Apply changes to custom ShaderManager --- .../TestSceneDrawableRulesetDependencies.cs | 2 +- .../Testing/TestSceneRulesetDependencies.cs | 4 ++-- .../UI/DrawableRulesetDependencies.cs | 22 +++---------------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs index f8248e88bb..6639b6dd68 100644 --- a/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs +++ b/osu.Game.Tests/Rulesets/TestSceneDrawableRulesetDependencies.cs @@ -164,7 +164,7 @@ namespace osu.Game.Tests.Rulesets this.parentManager = parentManager; } - public override byte[] LoadRaw(string name) => parentManager.LoadRaw(name); + public override byte[] GetRawData(string fileName) => parentManager.GetRawData(fileName); public bool IsDisposed { get; private set; } diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index a5a83d7231..585a3f95e7 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -51,8 +51,8 @@ namespace osu.Game.Tests.Testing { AddStep("ruleset shaders retrieved without error", () => { - Dependencies.Get().LoadRaw(@"sh_TestVertex.vs"); - Dependencies.Get().LoadRaw(@"sh_TestFragment.fs"); + Dependencies.Get().GetRawData(@"sh_TestVertex.vs"); + Dependencies.Get().GetRawData(@"sh_TestFragment.fs"); }); } diff --git a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs index 76d84000f1..e34289c968 100644 --- a/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs +++ b/osu.Game/Rulesets/UI/DrawableRulesetDependencies.cs @@ -206,27 +206,11 @@ namespace osu.Game.Rulesets.UI this.parent = parent; } - // When the debugger is attached, exceptions are expensive. - // Manually work around this by caching failed lookups and falling back straight to parent. - private readonly HashSet<(string, string)> failedLookups = new HashSet<(string, string)>(); + public override IShader? GetCachedShader(string vertex, string fragment) => base.GetCachedShader(vertex, fragment) ?? parent.GetCachedShader(vertex, fragment); - public override IShader Load(string vertex, string fragment) - { - if (!failedLookups.Contains((vertex, fragment))) - { - try - { - return base.Load(vertex, fragment); - } - catch - { - // Shader lookup is very non-standard. Rather than returning null on missing shaders, exceptions are thrown. - failedLookups.Add((vertex, fragment)); - } - } + public override IShaderPart? GetCachedShaderPart(string name) => base.GetCachedShaderPart(name) ?? parent.GetCachedShaderPart(name); - return parent.Load(vertex, fragment); - } + public override byte[]? GetRawData(string fileName) => base.GetRawData(fileName) ?? parent.GetRawData(fileName); } } } From 16df92f405cf466c21459189b9c90689d3b23ca7 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 17 Apr 2023 20:59:02 -0700 Subject: [PATCH 0531/1400] Fix sets not being plural --- osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs b/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs index d822f4976f..a77ee066e4 100644 --- a/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs +++ b/osu.Game/Localisation/FirstRunSetupBeatmapScreenStrings.cs @@ -15,9 +15,9 @@ namespace osu.Game.Localisation public static LocalisableString Header => new TranslatableString(getKey(@"header"), @"Obtaining Beatmaps"); /// - /// ""Beatmaps" are what we call a set of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection." + /// ""Beatmaps" are what we call sets of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection." /// - public static LocalisableString Description => new TranslatableString(getKey(@"description"), @"""Beatmaps"" are what we call a set of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection."); + public static LocalisableString Description => new TranslatableString(getKey(@"description"), @"""Beatmaps"" are what we call sets of playable levels. osu! doesn't come with any beatmaps pre-loaded. This step will help you get started on your beatmap collection."); /// /// "If you are a new player, we recommend playing through the tutorial to get accustomed to the gameplay." From c80a25328d2d5dc0fb8b1d7f710ee275db247e33 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 17 Apr 2023 20:59:41 -0700 Subject: [PATCH 0532/1400] Shorten label to just "matches" --- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 6 +++--- osu.Game/Screens/Select/SongSelect.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index c9a7cf37a8..f094d40caa 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -1073,14 +1073,14 @@ namespace osu.Game.Tests.Visual.SongSelect { createSongSelect(); - AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmap difficulties"); + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matches"); addRulesetImportStep(0); - AddAssert("3 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "3 matching beatmap difficulties"); + AddAssert("3 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "3 matches"); AddStep("delete all beatmaps", () => manager.Delete()); AddUntilStep("wait for no beatmap", () => Beatmap.IsDefault); - AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matching beatmap difficulties"); + AddAssert("0 matching shown", () => songSelect.ChildrenOfType().Single().InformationalText == "0 matches"); } private void waitForInitialSelection() diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 09ccee3717..4d6a5398c5 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -864,7 +864,7 @@ namespace osu.Game.Screens.Select { // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // but also in this case we want support for formatting a number within a string). - FilterControl.InformationalText = $"{"matching beatmap difficulty".ToQuantity(Carousel.CountDisplayed, "#,0")}"; + FilterControl.InformationalText = $"{"match".ToQuantity(Carousel.CountDisplayed, "#,0")}"; } private bool boundLocalBindables; From 760ef1014587638fb2b3eb3a022136cb0d07f396 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 19 Apr 2023 00:04:21 +0900 Subject: [PATCH 0533/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 4b89e82729..3ede0b85da 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b9c6c1df9d..6e8b642abf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 083d8192ea..127994c670 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 776c4cfaad00d1f9f99cfa70792022f68002c5b0 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 19 Apr 2023 18:34:35 -0700 Subject: [PATCH 0534/1400] Ensure `selected` field is correct in `updateSelectionState()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Overlays/Music/PlaylistItem.cs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 4032af7651..4a39cc06c8 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Music var artist = new RomanisableString(metadata.ArtistUnicode, metadata.Artist); titlePart = text.AddText(title, sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)); - titlePart.DrawablePartsRecreated += _ => updateSelectionState(true); + titlePart.DrawablePartsRecreated += _ => updateSelectionState(SelectedSet.Value, instant: true); text.AddText(@" "); // to separate the title from the artist. text.AddText(artist, sprite => @@ -66,25 +66,22 @@ namespace osu.Game.Overlays.Music sprite.Padding = new MarginPadding { Top = 1 }; }); - SelectedSet.BindValueChanged(set => - { - bool newSelected = set.NewValue?.Equals(Model) == true; - - if (newSelected == selected) - return; - - selected = newSelected; - updateSelectionState(false); - }, true); - - updateSelectionState(true); + SelectedSet.BindValueChanged(set => updateSelectionState(set.NewValue, instant: false)); + updateSelectionState(SelectedSet.Value, instant: true); }); } private bool selected; - private void updateSelectionState(bool instant) + private void updateSelectionState(Live selectedSet, bool instant) { + bool newSelected = selectedSet?.Equals(Model) == true; + + if (newSelected == selected && !instant) // instant updates should forcibly set correct state regardless of previous state. + return; + + selected = newSelected; + foreach (Drawable s in titlePart.Drawables) s.FadeColour(selected ? colours.Yellow : Color4.White, instant ? 0 : FADE_DURATION); } From 9f4b1f0f242a95ab2df2e77e2f2670ae5f846364 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Apr 2023 14:30:01 +0900 Subject: [PATCH 0535/1400] Always round editor rotation to integer values --- .../Edit/Compose/Components/SelectionBoxRotationHandle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 305f5bf3c4..c2a3f12efd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { float oldRotation = cumulativeRotation.Value ?? 0; - float newRotation = shouldSnap ? snap(rawCumulativeRotation, snap_step) : rawCumulativeRotation; + float newRotation = shouldSnap ? snap(rawCumulativeRotation, snap_step) : MathF.Round(rawCumulativeRotation); newRotation = (newRotation - 180) % 360 + 180; cumulativeRotation.Value = newRotation; From 1066dfcbf6bddb1378652b22d1d9922f6d4e5eb7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Apr 2023 14:35:12 +0900 Subject: [PATCH 0536/1400] Change default beat divisor to 4 This matches stable, and is a much saner default value. Will apply to new beatmaps and also beatmaps which don't specify a snap value in the `.osu` file. --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3208598f56..63e878b80d 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -167,7 +167,7 @@ namespace osu.Game.Beatmaps /// public double DistanceSpacing { get; set; } = 1.0; - public int BeatDivisor { get; set; } + public int BeatDivisor { get; set; } = 4; public int GridSize { get; set; } From b62de5514c532a3c2df5ef4c311eb5b273578050 Mon Sep 17 00:00:00 2001 From: Haspamelodica Date: Fri, 21 Apr 2023 02:10:24 +0200 Subject: [PATCH 0537/1400] Fixed video importing bug #23259 --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index cab49b7d69..6af6a25579 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -368,7 +368,7 @@ namespace osu.Game.Beatmaps // user requested abort return; - var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.Ordinal))); + var video = b.Files.FirstOrDefault(f => OsuGameBase.VIDEO_EXTENSIONS.Any(ex => f.Filename.EndsWith(ex, StringComparison.OrdinalIgnoreCase))); if (video != null) { diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a9bdd21b64..0e3a62e8fa 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -369,7 +369,7 @@ namespace osu.Game.Beatmaps.Formats // Some very old beatmaps had incorrect type specifications for their backgrounds (ie. using 1 for VIDEO // instead of 0 for BACKGROUND). To handle this gracefully, check the file extension against known supported // video extensions and handle similar to a background if it doesn't match. - if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(filename))) + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(filename).ToUpperInvariant())) { beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index f8308fe431..2eb496a798 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -114,7 +114,7 @@ namespace osu.Game.Beatmaps.Formats // // This avoids potential weird crashes when ffmpeg attempts to parse an image file as a video // (see https://github.com/ppy/osu/issues/22829#issuecomment-1465552451). - if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(path))) + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(path).ToUpperInvariant())) break; storyboard.GetLayer("Video").Add(new StoryboardVideo(path, offset)); diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index 37e15c6127..825b1a5636 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -70,7 +70,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { get { - if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension)) + if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension.ToUpperInvariant())) return FontAwesome.Regular.FileVideo; switch (File.Extension) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 34e31b0d61..2ab6c24af7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached(typeof(OsuGameBase))] public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" }; + public static readonly string[] VIDEO_EXTENSIONS = { ".MP4", ".MOV", ".AVI", ".FLV", ".MPG", ".WMV", ".M4V" }; public const string OSU_PROTOCOL = "osu://"; From e90660c1a48c7eb46447348756ca2b976ca1bbf6 Mon Sep 17 00:00:00 2001 From: Haspamelodica Date: Fri, 21 Apr 2023 02:35:28 +0200 Subject: [PATCH 0538/1400] Switched to lowercase --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 0e3a62e8fa..ef1dbc0488 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -369,7 +369,7 @@ namespace osu.Game.Beatmaps.Formats // Some very old beatmaps had incorrect type specifications for their backgrounds (ie. using 1 for VIDEO // instead of 0 for BACKGROUND). To handle this gracefully, check the file extension against known supported // video extensions and handle similar to a background if it doesn't match. - if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(filename).ToUpperInvariant())) + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(filename).ToLowerInvariant())) { beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; } diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 2eb496a798..df5d3edb55 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -114,7 +114,7 @@ namespace osu.Game.Beatmaps.Formats // // This avoids potential weird crashes when ffmpeg attempts to parse an image file as a video // (see https://github.com/ppy/osu/issues/22829#issuecomment-1465552451). - if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(path).ToUpperInvariant())) + if (!OsuGameBase.VIDEO_EXTENSIONS.Contains(Path.GetExtension(path).ToLowerInvariant())) break; storyboard.GetLayer("Video").Add(new StoryboardVideo(path, offset)); diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs index 825b1a5636..7097102335 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuFileSelector.cs @@ -70,7 +70,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { get { - if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension.ToUpperInvariant())) + if (OsuGameBase.VIDEO_EXTENSIONS.Contains(File.Extension.ToLowerInvariant())) return FontAwesome.Regular.FileVideo; switch (File.Extension) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 2ab6c24af7..34e31b0d61 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -71,7 +71,7 @@ namespace osu.Game [Cached(typeof(OsuGameBase))] public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { - public static readonly string[] VIDEO_EXTENSIONS = { ".MP4", ".MOV", ".AVI", ".FLV", ".MPG", ".WMV", ".M4V" }; + public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" }; public const string OSU_PROTOCOL = "osu://"; From e9fb836e9ccfbd6690ffcf5c6974e2d125a5fb80 Mon Sep 17 00:00:00 2001 From: Haspamelodica Date: Fri, 21 Apr 2023 03:24:11 +0200 Subject: [PATCH 0539/1400] Added tests for video backgrounds --- .../Formats/LegacyBeatmapDecoderTest.cs | 31 +++++++++++++++ .../Formats/LegacyStoryboardDecoderTest.cs | 38 ++++++++++++++++++- .../video-with-lowercase-extension.osb | 5 +++ .../video-with-uppercase-extension.osb | 5 +++ 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Resources/video-with-lowercase-extension.osb create mode 100644 osu.Game.Tests/Resources/video-with-uppercase-extension.osb diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 518981980b..5979f6785e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -21,6 +21,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Skinning; +using osu.Game.Storyboards; using osu.Game.Tests.Resources; using osuTK; using osuTK.Graphics; @@ -160,6 +161,36 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeVideoWithLowercaseExtension() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("video-with-lowercase-extension.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var beatmap = decoder.Decode(stream); + var metadata = beatmap.Metadata; + + Assert.AreEqual("BG.jpg", metadata.BackgroundFile); + } + } + + [Test] + public void TestDecodeVideoWithUppercaseExtension() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("video-with-uppercase-extension.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var beatmap = decoder.Decode(stream); + var metadata = beatmap.Metadata; + + Assert.AreEqual("BG.jpg", metadata.BackgroundFile); + } + } + [Test] public void TestDecodeImageSpecifiedAsVideo() { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 3a776ac225..1bfe134610 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -169,6 +169,40 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeVideoWithLowercaseExtension() + { + var decoder = new LegacyStoryboardDecoder(); + + using (var resStream = TestResources.OpenResource("video-with-lowercase-extension.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var storyboard = decoder.Decode(stream); + + StoryboardLayer video = storyboard.Layers.Single(l => l.Name == "Video"); + Assert.That(video.Elements.Count, Is.EqualTo(1)); + + Assert.AreEqual("Video.avi", ((StoryboardVideo)video.Elements[0]).Path); + } + } + + [Test] + public void TestDecodeVideoWithUppercaseExtension() + { + var decoder = new LegacyStoryboardDecoder(); + + using (var resStream = TestResources.OpenResource("video-with-uppercase-extension.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var storyboard = decoder.Decode(stream); + + StoryboardLayer video = storyboard.Layers.Single(l => l.Name == "Video"); + Assert.That(video.Elements.Count, Is.EqualTo(1)); + + Assert.AreEqual("Video.AVI", ((StoryboardVideo)video.Elements[0]).Path); + } + } + [Test] public void TestDecodeImageSpecifiedAsVideo() { @@ -179,8 +213,8 @@ namespace osu.Game.Tests.Beatmaps.Formats { var storyboard = decoder.Decode(stream); - StoryboardLayer foreground = storyboard.Layers.Single(l => l.Name == "Video"); - Assert.That(foreground.Elements.Count, Is.Zero); + StoryboardLayer video = storyboard.Layers.Single(l => l.Name == "Video"); + Assert.That(video.Elements.Count, Is.Zero); } } diff --git a/osu.Game.Tests/Resources/video-with-lowercase-extension.osb b/osu.Game.Tests/Resources/video-with-lowercase-extension.osb new file mode 100644 index 0000000000..eec09722ed --- /dev/null +++ b/osu.Game.Tests/Resources/video-with-lowercase-extension.osb @@ -0,0 +1,5 @@ +osu file format v14 + +[Events] +0,0,"BG.jpg",0,0 +Video,0,"Video.avi",0,0 diff --git a/osu.Game.Tests/Resources/video-with-uppercase-extension.osb b/osu.Game.Tests/Resources/video-with-uppercase-extension.osb new file mode 100644 index 0000000000..3834a547f2 --- /dev/null +++ b/osu.Game.Tests/Resources/video-with-uppercase-extension.osb @@ -0,0 +1,5 @@ +osu file format v14 + +[Events] +0,0,"BG.jpg",0,0 +Video,0,"Video.AVI",0,0 From 3166f88c17a291724f03b2bb53ca96413864a443 Mon Sep 17 00:00:00 2001 From: Haspamelodica Date: Fri, 21 Apr 2023 10:11:47 +0200 Subject: [PATCH 0540/1400] Removed unneccessary using directive --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 5979f6785e..d898650b66 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -21,7 +21,6 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Skinning; -using osu.Game.Storyboards; using osu.Game.Tests.Resources; using osuTK; using osuTK.Graphics; From 847b63066b9e08255026c3c530ebb5acab9ab5a4 Mon Sep 17 00:00:00 2001 From: Terochi Date: Fri, 21 Apr 2023 21:46:03 +0200 Subject: [PATCH 0541/1400] fix --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index ab754e51f7..7787dd80c1 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -418,10 +418,13 @@ namespace osu.Game.Rulesets.Catch.UI private void clearPlate(DroppedObjectAnimation animation) { - var droppedObjects = caughtObjectContainer.Children.Select(getDroppedObject).ToArray(); + var caughtObjects = caughtObjectContainer.Children.ToArray(); caughtObjectContainer.Clear(false); + //use the already returned PoolableDrawables for new objects + var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); + droppedObjectTarget.AddRange(droppedObjects); foreach (var droppedObject in droppedObjects) @@ -430,13 +433,11 @@ namespace osu.Game.Rulesets.Catch.UI private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation) { - var droppedObject = getDroppedObject(caughtObject); - caughtObjectContainer.Remove(caughtObject, false); - droppedObjectTarget.Add(droppedObject); + droppedObjectTarget.Add(getDroppedObject(caughtObject)); - applyDropAnimation(droppedObject, animation); + applyDropAnimation(caughtObject, animation); } private void applyDropAnimation(Drawable d, DroppedObjectAnimation animation) @@ -456,6 +457,8 @@ namespace osu.Game.Rulesets.Catch.UI break; } + //define lifetime start for dropped objects to be disposed correctly when rewinding replay + d.LifetimeStart = Clock.CurrentTime; d.Expire(); } From bb1ed387ef29958bcc8f8006cebfad2ead9dc8c8 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sat, 22 Apr 2023 10:54:50 +0200 Subject: [PATCH 0542/1400] fixed missed bit and comments --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 7787dd80c1..f77dab56c8 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -422,7 +422,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtObjectContainer.Clear(false); - //use the already returned PoolableDrawables for new objects + // Use the already returned PoolableDrawables for new objects var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); droppedObjectTarget.AddRange(droppedObjects); @@ -435,9 +435,11 @@ namespace osu.Game.Rulesets.Catch.UI { caughtObjectContainer.Remove(caughtObject, false); - droppedObjectTarget.Add(getDroppedObject(caughtObject)); + var droppedObject = getDroppedObject(caughtObject); - applyDropAnimation(caughtObject, animation); + droppedObjectTarget.Add(droppedObject); + + applyDropAnimation(droppedObject, animation); } private void applyDropAnimation(Drawable d, DroppedObjectAnimation animation) @@ -457,7 +459,7 @@ namespace osu.Game.Rulesets.Catch.UI break; } - //define lifetime start for dropped objects to be disposed correctly when rewinding replay + // Define lifetime start for dropped objects to be disposed correctly when rewinding replay d.LifetimeStart = Clock.CurrentTime; d.Expire(); } From 56ab029a58eeff34f1f976fb956b7f042d8c79df Mon Sep 17 00:00:00 2001 From: Hy0tic Date: Sat, 22 Apr 2023 13:30:08 -0400 Subject: [PATCH 0543/1400] fix issue where multipler does not update when adjusting speed for preset mod --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 16602db4be..d611fd3c0b 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -252,7 +252,7 @@ namespace osu.Game.Overlays.Mods if (AllowCustomisation) { - modSettingChangeTracker = new ModSettingChangeTracker(val.NewValue); + modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); modSettingChangeTracker.SettingChanged += _ => updateMultiplier(); } }, true); From 0991c56e1c5cd9f9713ea7c55e9b9ce8fde3c37b Mon Sep 17 00:00:00 2001 From: Renzo Poggio Date: Tue, 25 Apr 2023 00:05:15 -0300 Subject: [PATCH 0544/1400] Add extra check in 'SelectPreviousRandom' Check if the poped beatmap exists within the beatmapSets --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 6ba9843f7b..8c0f67564a 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -540,7 +540,7 @@ namespace osu.Game.Screens.Select { var beatmap = randomSelectedBeatmaps.Pop(); - if (!beatmap.Filtered.Value) + if (!beatmap.Filtered.Value && beatmapSets.Any(beatset => beatset.Beatmaps.Contains(beatmap))) { if (selectedBeatmapSet != null) { From 3919400be2c0d2dddc287ca8bda36677dfb029fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 14:28:56 +0900 Subject: [PATCH 0545/1400] Apply NRT to some storyboard classes --- osu.Game/Storyboards/StoryboardAnimation.cs | 2 -- osu.Game/Storyboards/StoryboardSprite.cs | 13 +++++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Storyboards/StoryboardAnimation.cs b/osu.Game/Storyboards/StoryboardAnimation.cs index 16deac8e9e..1a4b6bb923 100644 --- a/osu.Game/Storyboards/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/StoryboardAnimation.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. -#nullable disable - using osuTK; using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 5b7b194be7..0c28d7bce1 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; using osuTK; @@ -114,7 +111,7 @@ namespace osu.Game.Storyboards public virtual Drawable CreateDrawable() => new DrawableStoryboardSprite(this); - public void ApplyTransforms(Drawable drawable, IEnumerable> triggeredGroups = null) + public void ApplyTransforms(Drawable drawable, IEnumerable>? triggeredGroups = null) { // For performance reasons, we need to apply the commands in order by start time. Not doing so will cause many functions to be interleaved, resulting in O(n^2) complexity. // To achieve this, commands are "generated" as pairs of (command, initFunc, transformFunc) and batched into a contiguous list @@ -156,7 +153,7 @@ namespace osu.Game.Storyboards foreach (var command in commands) { - DrawablePropertyInitializer initFunc = null; + DrawablePropertyInitializer? initFunc = null; if (!initialized) { @@ -169,7 +166,7 @@ namespace osu.Game.Storyboards } } - private IEnumerable.TypedCommand> getCommands(CommandTimelineSelector timelineSelector, IEnumerable> triggeredGroups) + private IEnumerable.TypedCommand> getCommands(CommandTimelineSelector timelineSelector, IEnumerable>? triggeredGroups) { var commands = TimelineGroup.GetCommands(timelineSelector); foreach (var loop in loops) @@ -198,11 +195,11 @@ namespace osu.Game.Storyboards { public double StartTime => command.StartTime; - private readonly DrawablePropertyInitializer initializeProperty; + private readonly DrawablePropertyInitializer? initializeProperty; private readonly DrawableTransformer transform; private readonly CommandTimeline.TypedCommand command; - public GeneratedCommand([NotNull] CommandTimeline.TypedCommand command, [CanBeNull] DrawablePropertyInitializer initializeProperty, [NotNull] DrawableTransformer transform) + public GeneratedCommand(CommandTimeline.TypedCommand command, DrawablePropertyInitializer? initializeProperty, DrawableTransformer transform) { this.command = command; this.initializeProperty = initializeProperty; From dce0c5fac815b4334a921b81989baf2d06e3c57c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 15:14:32 +0900 Subject: [PATCH 0546/1400] Add test coverage of expected behaviour for playback of loops with no explicit end time --- .../Formats/LegacyStoryboardDecoderTest.cs | 19 +++++++++++++++++++ .../animation-loop-no-explicit-end-time.osb | 6 ++++++ 2 files changed, 25 insertions(+) create mode 100644 osu.Game.Tests/Resources/animation-loop-no-explicit-end-time.osb diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 3a776ac225..17e94a8b5f 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -95,6 +95,25 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestLoopWithoutExplicitFadeOut() + { + var decoder = new LegacyStoryboardDecoder(); + + using (var resStream = TestResources.OpenResource("animation-loop-no-explicit-end-time.osb")) + using (var stream = new LineBufferedReader(resStream)) + { + var storyboard = decoder.Decode(stream); + + StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3); + Assert.AreEqual(1, background.Elements.Count); + + Assert.AreEqual(2000, background.Elements[0].StartTime); + Assert.AreEqual(2000, (background.Elements[0] as StoryboardAnimation)?.EarliestTransformTime); + Assert.AreEqual(12000, (background.Elements[0] as StoryboardAnimation)?.GetEndTime()); + } + } + [Test] public void TestCorrectAnimationStartTime() { diff --git a/osu.Game.Tests/Resources/animation-loop-no-explicit-end-time.osb b/osu.Game.Tests/Resources/animation-loop-no-explicit-end-time.osb new file mode 100644 index 0000000000..7afaa445df --- /dev/null +++ b/osu.Game.Tests/Resources/animation-loop-no-explicit-end-time.osb @@ -0,0 +1,6 @@ +[Events] +//Storyboard Layer 0 (Background) +Animation,Background,Centre,"img.jpg",320,240,2,150,LoopForever + F,0,2000,,0,1 + L,2000,10 + F,18,0,1000,1,0 From e330052852a8692c769ed2152a5980a16679b576 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 15:22:11 +0900 Subject: [PATCH 0547/1400] Add second definition of `EndTime` for storyboard elements to account for loops in lifetime --- .../Beatmaps/Formats/LegacyStoryboardDecoderTest.cs | 4 +++- .../Background/TestSceneBackgroundScreenDefault.cs | 1 + .../Storyboards/IStoryboardElementWithDuration.cs | 8 ++++++++ osu.Game/Storyboards/StoryboardSprite.cs | 13 +++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 17e94a8b5f..f78825ffb1 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -110,7 +110,9 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(2000, background.Elements[0].StartTime); Assert.AreEqual(2000, (background.Elements[0] as StoryboardAnimation)?.EarliestTransformTime); - Assert.AreEqual(12000, (background.Elements[0] as StoryboardAnimation)?.GetEndTime()); + + Assert.AreEqual(3000, (background.Elements[0] as StoryboardAnimation)?.GetEndTime()); + Assert.AreEqual(12000, (background.Elements[0] as StoryboardAnimation)?.EndTimeForDisplay); } } diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs index fbdaad1cd8..8f4250799e 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs @@ -311,6 +311,7 @@ namespace osu.Game.Tests.Visual.Background public bool IsDrawable => true; public double StartTime => double.MinValue; public double EndTime => double.MaxValue; + public double EndTimeForDisplay => double.MaxValue; public Drawable CreateDrawable() => new DrawableTestStoryboardElement(); } diff --git a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs index c8daeb3b3d..9eed139ad4 100644 --- a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs @@ -12,9 +12,17 @@ namespace osu.Game.Storyboards { /// /// The time at which the ends. + /// This is consumed to extend the length of a storyboard to ensure all visuals are played to completion. /// double EndTime { get; } + /// + /// The time this element displays until. + /// This is used for lifetime purposes, and includes long playing animations which don't necessarily extend + /// a storyboard's play time. + /// + double EndTimeForDisplay { get; } + /// /// The duration of the StoryboardElement. /// diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 0c28d7bce1..982185d51b 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -81,6 +81,19 @@ namespace osu.Game.Storyboards } } + public double EndTimeForDisplay + { + get + { + double latestEndTime = TimelineGroup.EndTime; + + foreach (var l in loops) + latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations); + + return latestEndTime; + } + } + public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands); private delegate void DrawablePropertyInitializer(Drawable drawable, T value); From a4c6850ab2e64fc2a195744af8b02fd6c61a4726 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 11:34:09 +0200 Subject: [PATCH 0548/1400] made the SampleControlPoint and DifficultyControlPoint obsolete --- .../Legacy/DistanceObjectPatternGenerator.cs | 11 ++-- osu.Game.Rulesets.Osu/Objects/Slider.cs | 32 +++++++--- .../Beatmaps/TaikoBeatmapConverter.cs | 11 ++-- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 3 + osu.Game/Rulesets/Objects/HitObject.cs | 61 ++++++++++++------- .../Rulesets/Objects/Legacy/ConvertSlider.cs | 15 ++++- .../Objects/Types/IHasSliderVelocity.cs | 15 +++++ 7 files changed, 105 insertions(+), 43 deletions(-) create mode 100644 osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 2bdd0e16ad..9e031c2b4d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -49,15 +49,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy Debug.Assert(distanceData != null); TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); - DifficultyControlPoint difficultyPoint = hitObject.DifficultyControlPoint; double beatLength; -#pragma warning disable 618 - if (difficultyPoint is LegacyBeatmapDecoder.LegacyDifficultyControlPoint legacyDifficultyPoint) -#pragma warning restore 618 - beatLength = timingPoint.BeatLength * legacyDifficultyPoint.BpmMultiplier; + if (hitObject.LegacyBpmMultiplier.HasValue) + beatLength = timingPoint.BeatLength * hitObject.LegacyBpmMultiplier.Value; + else if (hitObject is IHasSliderVelocity hasSliderVelocity) + beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else - beatLength = timingPoint.BeatLength / difficultyPoint.SliderVelocity; + beatLength = timingPoint.BeatLength; SpanCount = repeatsData?.SpanCount() ?? 1; StartTime = (int)Math.Round(hitObject.StartTime); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 6c2be8a49a..6952033aec 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; +using System.Text.Json.Serialization; using System.Threading; using Newtonsoft.Json; using osu.Framework.Caching; @@ -15,13 +16,14 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; +using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { - public class Slider : OsuHitObject, IHasPathWithRepeats + public class Slider : OsuHitObject, IHasPathWithRepeats, IHasSliderVelocity { public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; @@ -134,6 +136,13 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool OnlyJudgeNestedObjects = true; + public double SliderVelocity { get; set; } = 1; + + /// + /// Whether to generate ticks on this . + /// + public bool GenerateTicks = true; + [JsonIgnore] public SliderHeadCircle HeadCircle { get; protected set; } @@ -151,15 +160,24 @@ namespace osu.Game.Rulesets.Osu.Objects base.ApplyDefaultsToSelf(controlPointInfo, difficulty); TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); -#pragma warning disable 618 - var legacyDifficultyPoint = DifficultyControlPoint as LegacyBeatmapDecoder.LegacyDifficultyControlPoint; -#pragma warning restore 618 - double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * DifficultyControlPoint.SliderVelocity; - bool generateTicks = legacyDifficultyPoint?.GenerateTicks ?? true; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; - TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; + TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; + } + + protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) + { + base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty); + + DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; +#pragma warning disable 618 + var legacyDifficultyPoint = difficultyControlPoint as LegacyBeatmapDecoder.LegacyDifficultyControlPoint; +#pragma warning restore 618 + + SliderVelocity = difficultyControlPoint.SliderVelocity; + GenerateTicks = legacyDifficultyPoint?.GenerateTicks ?? true; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 6a35e9376b..362ddccaf1 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -177,15 +177,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps double distance = distanceData.Distance * spans * LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); - DifficultyControlPoint difficultyPoint = obj.DifficultyControlPoint; double beatLength; -#pragma warning disable 618 - if (difficultyPoint is LegacyBeatmapDecoder.LegacyDifficultyControlPoint legacyDifficultyPoint) -#pragma warning restore 618 - beatLength = timingPoint.BeatLength * legacyDifficultyPoint.BpmMultiplier; + if (obj.LegacyBpmMultiplier.HasValue) + beatLength = timingPoint.BeatLength * obj.LegacyBpmMultiplier.Value; + else if (obj is IHasSliderVelocity hasSliderVelocity) + beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else - beatLength = timingPoint.BeatLength / difficultyPoint.SliderVelocity; + beatLength = timingPoint.BeatLength; double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a9bdd21b64..c17eea0e85 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -85,7 +85,10 @@ namespace osu.Game.Beatmaps.Formats this.beatmap.HitObjects = this.beatmap.HitObjects.OrderBy(h => h.StartTime).ToList(); foreach (var hitObject in this.beatmap.HitObjects) + { + hitObject.ApplyLegacyInfo(this.beatmap.ControlPointInfo, this.beatmap.Difficulty); hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.Difficulty); + } } /// diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 25f538d211..aea564a4b9 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -16,6 +16,7 @@ using osu.Framework.Lists; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; @@ -80,6 +81,12 @@ namespace osu.Game.Rulesets.Objects public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT; public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT; + /// + /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. + /// DO NOT USE THIS UNLESS 100% SURE. + /// + public double? LegacyBpmMultiplier { get; private set; } + /// /// Whether this is in Kiai time. /// @@ -105,25 +112,6 @@ namespace osu.Game.Rulesets.Objects /// The cancellation token. public void ApplyDefaults(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty, CancellationToken cancellationToken = default) { - var legacyInfo = controlPointInfo as LegacyControlPointInfo; - - if (legacyInfo != null) - DifficultyControlPoint = (DifficultyControlPoint)legacyInfo.DifficultyPointAt(StartTime).DeepClone(); - else if (ReferenceEquals(DifficultyControlPoint, DifficultyControlPoint.DEFAULT)) - DifficultyControlPoint = new DifficultyControlPoint(); - - DifficultyControlPoint.Time = StartTime; - - ApplyDefaultsToSelf(controlPointInfo, difficulty); - - // This is done here after ApplyDefaultsToSelf as we may require custom defaults to be applied to have an accurate end time. - if (legacyInfo != null) - SampleControlPoint = (SampleControlPoint)legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency).DeepClone(); - else if (ReferenceEquals(SampleControlPoint, SampleControlPoint.DEFAULT)) - SampleControlPoint = new SampleControlPoint(); - - SampleControlPoint.Time = this.GetEndTime() + control_point_leniency; - nestedHitObjects.Clear(); CreateNestedHitObjects(cancellationToken); @@ -164,9 +152,6 @@ namespace osu.Game.Rulesets.Objects foreach (var nested in nestedHitObjects) nested.StartTime += offset; - - DifficultyControlPoint.Time = time.NewValue; - SampleControlPoint.Time = this.GetEndTime() + control_point_leniency; } } @@ -178,6 +163,38 @@ namespace osu.Game.Rulesets.Objects HitWindows?.SetDifficulty(difficulty.OverallDifficulty); } + /// + /// Applies legacy information to this HitObject. + /// This method gets called at the end of before applying defaults. + /// + /// The control points. + /// The difficulty settings to use. + /// The cancellation token. + public void ApplyLegacyInfo(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty, CancellationToken cancellationToken = default) + { + var legacyInfo = controlPointInfo as LegacyControlPointInfo; + + DifficultyControlPoint difficultyControlPoint = legacyInfo != null ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; +#pragma warning disable 618 + if (difficultyControlPoint is LegacyBeatmapDecoder.LegacyDifficultyControlPoint legacyDifficultyControlPoint) +#pragma warning restore 618 + LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier; + + ApplyLegacyInfoToSelf(controlPointInfo, difficulty); + + // This is done here after ApplyLegacyInfoToSelf as we may require custom defaults to be applied to have an accurate end time. + SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT; + + foreach (var hitSampleInfo in Samples) + { + sampleControlPoint.ApplyTo(hitSampleInfo); + } + } + + protected virtual void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) + { + } + protected virtual void CreateNestedHitObjects(CancellationToken cancellationToken) { } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index bd2713a7d1..11e1f0beae 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -9,10 +9,11 @@ using Newtonsoft.Json; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Objects.Legacy { - internal abstract class ConvertSlider : ConvertHitObject, IHasPathWithRepeats, IHasLegacyLastTickOffset + internal abstract class ConvertSlider : ConvertHitObject, IHasPathWithRepeats, IHasLegacyLastTickOffset, IHasSliderVelocity { /// /// Scoring distance with a speed-adjusted beat length of 1 second. @@ -40,17 +41,27 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Velocity = 1; + public double SliderVelocity { get; set; } = 1; + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * DifficultyControlPoint.SliderVelocity; + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; } + protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) + { + base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty); + + DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; + SliderVelocity = difficultyControlPoint.SliderVelocity; + } + public double LegacyLastTickOffset => 36; } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs new file mode 100644 index 0000000000..a7195dab4b --- /dev/null +++ b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs @@ -0,0 +1,15 @@ +// 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.Rulesets.Objects.Types; + +/// +/// A HitObject that has a slider velocity multiplier. +/// +public interface IHasSliderVelocity +{ + /// + /// The slider velocity multiplier. + /// + double SliderVelocity { get; set; } +} From ea1e6e9798b7773bdf130febf4026edbd1caac52 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 12:12:46 +0200 Subject: [PATCH 0549/1400] Add LegacyContext --- .../Legacy/DistanceObjectPatternGenerator.cs | 5 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 13 +-- .../Beatmaps/TaikoBeatmapConverter.cs | 5 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 16 +++- osu.Game/Beatmaps/Legacy/LegacyContext.cs | 32 +++++++ osu.Game/Context/IContext.cs | 10 +++ osu.Game/Context/IHasContext.cs | 88 +++++++++++++++++++ osu.Game/Rulesets/Objects/HitObject.cs | 15 +--- 8 files changed, 155 insertions(+), 29 deletions(-) create mode 100644 osu.Game/Beatmaps/Legacy/LegacyContext.cs create mode 100644 osu.Game/Context/IContext.cs create mode 100644 osu.Game/Context/IHasContext.cs diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 9e031c2b4d..b3a68269f7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; +using osu.Game.Beatmaps.Legacy; using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy @@ -51,8 +52,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); double beatLength; - if (hitObject.LegacyBpmMultiplier.HasValue) - beatLength = timingPoint.BeatLength * hitObject.LegacyBpmMultiplier.Value; + if (hitObject.HasContext()) + beatLength = timingPoint.BeatLength * hitObject.GetContext().BpmMultiplier; else if (hitObject is IHasSliderVelocity hasSliderVelocity) beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 6952033aec..4010218f6e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -138,11 +138,6 @@ namespace osu.Game.Rulesets.Osu.Objects public double SliderVelocity { get; set; } = 1; - /// - /// Whether to generate ticks on this . - /// - public bool GenerateTicks = true; - [JsonIgnore] public SliderHeadCircle HeadCircle { get; protected set; } @@ -162,9 +157,10 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; + bool generateTicks = !HasContext() || GetContext().GenerateTicks; Velocity = scoringDistance / timingPoint.BeatLength; - TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; + TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; } protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) @@ -172,12 +168,7 @@ namespace osu.Game.Rulesets.Osu.Objects base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty); DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; -#pragma warning disable 618 - var legacyDifficultyPoint = difficultyControlPoint as LegacyBeatmapDecoder.LegacyDifficultyControlPoint; -#pragma warning restore 618 - SliderVelocity = difficultyControlPoint.SliderVelocity; - GenerateTicks = legacyDifficultyPoint?.GenerateTicks ?? true; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 362ddccaf1..ef73ffd517 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -16,6 +16,7 @@ using JetBrains.Annotations; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; +using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Taiko.Beatmaps { @@ -179,8 +180,8 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); double beatLength; - if (obj.LegacyBpmMultiplier.HasValue) - beatLength = timingPoint.BeatLength * obj.LegacyBpmMultiplier.Value; + if (obj.HasContext()) + beatLength = timingPoint.BeatLength * obj.GetContext().BpmMultiplier; else if (obj is IHasSliderVelocity hasSliderVelocity) beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index c17eea0e85..6f948e4d23 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -15,6 +15,7 @@ using osu.Game.Beatmaps.Legacy; using osu.Game.Beatmaps.Timing; using osu.Game.IO; using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Legacy; namespace osu.Game.Beatmaps.Formats @@ -86,11 +87,24 @@ namespace osu.Game.Beatmaps.Formats foreach (var hitObject in this.beatmap.HitObjects) { - hitObject.ApplyLegacyInfo(this.beatmap.ControlPointInfo, this.beatmap.Difficulty); + applyLegacyInfoToHitObject(hitObject); hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.Difficulty); } } + private void applyLegacyInfoToHitObject(HitObject hitObject) + { + var legacyInfo = beatmap.ControlPointInfo as LegacyControlPointInfo; + + DifficultyControlPoint difficultyControlPoint = legacyInfo != null ? legacyInfo.DifficultyPointAt(hitObject.StartTime) : DifficultyControlPoint.DEFAULT; +#pragma warning disable 618 + if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint) +#pragma warning restore 618 + hitObject.SetContext(new LegacyContext(legacyDifficultyControlPoint.BpmMultiplier, legacyDifficultyControlPoint.GenerateTicks)); + + hitObject.ApplyLegacyInfo(beatmap.ControlPointInfo, beatmap.Difficulty); + } + /// /// Some `BeatmapInfo` members have default values that differ from the default values used by stable. /// In addition, legacy beatmaps will sometimes not contain some configuration keys, in which case diff --git a/osu.Game/Beatmaps/Legacy/LegacyContext.cs b/osu.Game/Beatmaps/Legacy/LegacyContext.cs new file mode 100644 index 0000000000..eeb02bdcb7 --- /dev/null +++ b/osu.Game/Beatmaps/Legacy/LegacyContext.cs @@ -0,0 +1,32 @@ +// 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.Context; + +namespace osu.Game.Beatmaps.Legacy; + +public class LegacyContext : IContext +{ + public LegacyContext(double bpmMultiplier, bool generateTicks) + { + BpmMultiplier = bpmMultiplier; + GenerateTicks = generateTicks; + } + + /// + /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. + /// DO NOT USE THIS UNLESS 100% SURE. + /// + public double BpmMultiplier { get; } + + /// + /// Whether or not slider ticks should be generated at this control point. + /// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991). + /// + public bool GenerateTicks { get; } + + public IContext Copy() + { + return new LegacyContext(BpmMultiplier, GenerateTicks); + } +} diff --git a/osu.Game/Context/IContext.cs b/osu.Game/Context/IContext.cs new file mode 100644 index 0000000000..f70cdea9f8 --- /dev/null +++ b/osu.Game/Context/IContext.cs @@ -0,0 +1,10 @@ +namespace osu.Game.Context; + +public interface IContext +{ + /// + /// Makes a deep copy of this context. + /// + /// The deep copy of this context. + public IContext Copy(); +} diff --git a/osu.Game/Context/IHasContext.cs b/osu.Game/Context/IHasContext.cs new file mode 100644 index 0000000000..bee81ea555 --- /dev/null +++ b/osu.Game/Context/IHasContext.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; + +namespace osu.Game.Context +{ + public abstract class ContextContainer + { + /// + /// The contexts of this container. + /// The objects always have the type of their key. + /// + private readonly Dictionary contexts; + + protected ContextContainer() + { + contexts = new Dictionary(); + } + + /// + /// Checks whether this object has the context with type T. + /// + /// The type to check the context of. + /// Whether the context object with type T exists in this object. + public bool HasContext() where T : IContext + { + return contexts.ContainsKey(typeof(T)); + } + + /// + /// Gets the context with type T. + /// + /// The type to get the context of. + /// If the context does not exist in this hit object. + /// The context object with type T. + public T GetContext() where T : IContext + { + return (T)contexts[typeof(T)]; + } + + /// + /// Tries to get the context with type T. + /// + /// The found context with type T. + /// The type to get the context of. + /// Whether the context exists in this object. + public bool TryGetContext(out T context) where T : IContext + { + if (contexts.TryGetValue(typeof(T), out var context2)) + { + context = (T)context2; + return true; + } + + context = default!; + return false; + } + + /// + /// Sets the context object of type T. + /// + /// The context type to set. + /// The context object to store in this object. + public void SetContext(T context) where T : IContext + { + contexts[typeof(T)] = context; + } + + /// + /// Removes the context of type T from this object. + /// + /// The type to remove the context of. + /// Whether a context was removed. + public bool RemoveContext() where T : IContext + { + return RemoveContext(typeof(T)); + } + + /// + /// Removes the context of type T from this object. + /// + /// The type to remove the context of. + /// Whether a context was removed. + public bool RemoveContext(Type t) + { + return contexts.Remove(t); + } + } +} diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index aea564a4b9..fb7a5739b4 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -18,6 +18,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Legacy; +using osu.Game.Context; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -30,7 +31,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 class HitObject : ContextContainer { /// /// A small adjustment to the start time of control points to account for rounding/precision errors. @@ -81,12 +82,6 @@ namespace osu.Game.Rulesets.Objects public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT; public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT; - /// - /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. - /// DO NOT USE THIS UNLESS 100% SURE. - /// - public double? LegacyBpmMultiplier { get; private set; } - /// /// Whether this is in Kiai time. /// @@ -174,12 +169,6 @@ namespace osu.Game.Rulesets.Objects { var legacyInfo = controlPointInfo as LegacyControlPointInfo; - DifficultyControlPoint difficultyControlPoint = legacyInfo != null ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; -#pragma warning disable 618 - if (difficultyControlPoint is LegacyBeatmapDecoder.LegacyDifficultyControlPoint legacyDifficultyControlPoint) -#pragma warning restore 618 - LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier; - ApplyLegacyInfoToSelf(controlPointInfo, difficulty); // This is done here after ApplyLegacyInfoToSelf as we may require custom defaults to be applied to have an accurate end time. From 891b87a5ff97e9eaeb7a0de15472217e97b2540c Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 12:52:21 +0200 Subject: [PATCH 0550/1400] remove ApplyLegacyInfo method --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 8 ----- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 36 ++++++++++++++++--- osu.Game/Rulesets/Objects/HitObject.cs | 26 -------------- .../Rulesets/Objects/Legacy/ConvertSlider.cs | 8 ----- 4 files changed, 32 insertions(+), 46 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4010218f6e..a90d60cd1b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -163,14 +163,6 @@ namespace osu.Game.Rulesets.Osu.Objects TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; } - protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) - { - base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty); - - DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; - SliderVelocity = difficultyControlPoint.SliderVelocity; - } - protected override void CreateNestedHitObjects(CancellationToken cancellationToken) { base.CreateNestedHitObjects(cancellationToken); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 6f948e4d23..dad23df282 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -17,6 +17,7 @@ using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Legacy; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Beatmaps.Formats { @@ -27,6 +28,11 @@ namespace osu.Game.Beatmaps.Formats /// public const int EARLY_VERSION_TIMING_OFFSET = 24; + /// + /// A small adjustment to the start time of control points to account for rounding/precision errors. + /// + private const double control_point_leniency = 1; + internal static RulesetStore RulesetStore; private Beatmap beatmap; @@ -87,12 +93,11 @@ namespace osu.Game.Beatmaps.Formats foreach (var hitObject in this.beatmap.HitObjects) { - applyLegacyInfoToHitObject(hitObject); - hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.Difficulty); + applyLegacyInfoAndDefaults(hitObject); } } - private void applyLegacyInfoToHitObject(HitObject hitObject) + private void applyLegacyInfoAndDefaults(HitObject hitObject) { var legacyInfo = beatmap.ControlPointInfo as LegacyControlPointInfo; @@ -102,7 +107,30 @@ namespace osu.Game.Beatmaps.Formats #pragma warning restore 618 hitObject.SetContext(new LegacyContext(legacyDifficultyControlPoint.BpmMultiplier, legacyDifficultyControlPoint.GenerateTicks)); - hitObject.ApplyLegacyInfo(beatmap.ControlPointInfo, beatmap.Difficulty); + if (hitObject is IHasSliderVelocity hasSliderVelocity) + hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity; + + hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); + + SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT; + + foreach (var hitSampleInfo in hitObject.Samples) + { + sampleControlPoint.ApplyTo(hitSampleInfo); + } + + if (hitObject is not IHasRepeats hasRepeats) return; + + for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) + { + double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency; + sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(time) : SampleControlPoint.DEFAULT; + + foreach (var hitSampleInfo in hasRepeats.NodeSamples[i]) + { + sampleControlPoint.ApplyTo(hitSampleInfo); + } + } } /// diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index fb7a5739b4..2298a7ef12 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -158,32 +158,6 @@ namespace osu.Game.Rulesets.Objects HitWindows?.SetDifficulty(difficulty.OverallDifficulty); } - /// - /// Applies legacy information to this HitObject. - /// This method gets called at the end of before applying defaults. - /// - /// The control points. - /// The difficulty settings to use. - /// The cancellation token. - public void ApplyLegacyInfo(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty, CancellationToken cancellationToken = default) - { - var legacyInfo = controlPointInfo as LegacyControlPointInfo; - - ApplyLegacyInfoToSelf(controlPointInfo, difficulty); - - // This is done here after ApplyLegacyInfoToSelf as we may require custom defaults to be applied to have an accurate end time. - SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(this.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT; - - foreach (var hitSampleInfo in Samples) - { - sampleControlPoint.ApplyTo(hitSampleInfo); - } - } - - protected virtual void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) - { - } - protected virtual void CreateNestedHitObjects(CancellationToken cancellationToken) { } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 11e1f0beae..47aabf1599 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -54,14 +54,6 @@ namespace osu.Game.Rulesets.Objects.Legacy Velocity = scoringDistance / timingPoint.BeatLength; } - protected override void ApplyLegacyInfoToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) - { - base.ApplyLegacyInfoToSelf(controlPointInfo, difficulty); - - DifficultyControlPoint difficultyControlPoint = controlPointInfo is LegacyControlPointInfo legacyInfo ? legacyInfo.DifficultyPointAt(StartTime) : DifficultyControlPoint.DEFAULT; - SliderVelocity = difficultyControlPoint.SliderVelocity; - } - public double LegacyLastTickOffset => 36; } } From bf1951fc38200c8372df7ada3ce19bc8c4a9443a Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 12:54:45 +0200 Subject: [PATCH 0551/1400] Fix incorrect xmldoc --- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index c454439c5c..6cd4d74a31 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// - /// The speed multiplier at this control point. + /// The default sample bank at this control point. /// public string SampleBank { @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.ControlPoints } /// - /// The default sample bank at this control point. + /// The default sample volume at this control point. /// public readonly BindableInt SampleVolumeBindable = new BindableInt(100) { From 97910d6be6b96bcb56d77d8489f41f80cd58f1b4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 13:06:37 +0200 Subject: [PATCH 0552/1400] remove unused directives --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 1 - osu.Game/Rulesets/Objects/HitObject.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 1 - 3 files changed, 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index a90d60cd1b..73ac184c57 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -15,7 +15,6 @@ using osu.Framework.Caching; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 2298a7ef12..0502610eab 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -16,8 +16,6 @@ using osu.Framework.Lists; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.Legacy; using osu.Game.Context; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 47aabf1599..f602cbac09 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -9,7 +9,6 @@ using Newtonsoft.Json; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Objects.Legacy { From dd2c289ce96ed4c874f901476bef18e0c4657a6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 20:22:12 +0900 Subject: [PATCH 0553/1400] Remove pointless default value --- osu.Game/Screens/Play/ArgonKeyCounter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs index 70fe2e3a65..a978f001d5 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounter.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -56,7 +56,6 @@ namespace osu.Game.Screens.Play Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Font = OsuFont.Torus.With(size: count_font_size * scale_factor, weight: FontWeight.Bold), - Text = "0" }, }; From 76309586330690aee88bfc4b7f6ac6b70cdbf751 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 20:24:36 +0900 Subject: [PATCH 0554/1400] Stop using `Drawable.Name` to convey actual UI information --- osu.Game/Screens/Play/ArgonKeyCounter.cs | 2 +- osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs | 2 +- osu.Game/Screens/Play/HUD/KeyCounter.cs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs index a978f001d5..6818b30823 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounter.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Play Position = new Vector2(0, -13) * scale_factor, Font = OsuFont.Torus.With(size: name_font_size * scale_factor, weight: FontWeight.Bold), Colour = colours.Blue0, - Text = Name + Text = Trigger.Name }, countText = new OsuSpriteText { diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs index 69a3e53dfc..f7ac72035f 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounter.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play.HUD { new OsuSpriteText { - Text = Name, + Text = Trigger.Name, Font = OsuFont.Numeric.With(size: 12), Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Play/HUD/KeyCounter.cs b/osu.Game/Screens/Play/HUD/KeyCounter.cs index 2a4ab1993a..7cdd6b025f 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounter.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounter.cs @@ -54,8 +54,6 @@ namespace osu.Game.Screens.Play.HUD Trigger.OnActivate += Activate; Trigger.OnDeactivate += Deactivate; - - Name = trigger.Name; } private void increment() From 0c3a01595362d1e995dfe46d7fbd0d1c4bd8c814 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 21:37:17 +0900 Subject: [PATCH 0555/1400] Fix key counter test not testing the full binding of `IsCounting` --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 1e35c24e97..aabc25d660 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -19,21 +19,21 @@ namespace osu.Game.Tests.Visual.Gameplay { public TestSceneKeyCounter() { - KeyCounterDisplay kc = new DefaultKeyCounterDisplay + KeyCounterDisplay defaultDisplay = new DefaultKeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, Position = new Vector2(0, 72.7f) }; - KeyCounterDisplay argonKc = new ArgonKeyCounterDisplay + KeyCounterDisplay argonDisplay = new ArgonKeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, Position = new Vector2(0, -72.7f) }; - kc.AddRange(new InputTrigger[] + defaultDisplay.AddRange(new InputTrigger[] { new KeyCounterKeyboardTrigger(Key.X), new KeyCounterKeyboardTrigger(Key.X), @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Gameplay new KeyCounterMouseTrigger(MouseButton.Right), }); - argonKc.AddRange(new InputTrigger[] + argonDisplay.AddRange(new InputTrigger[] { new KeyCounterKeyboardTrigger(Key.X), new KeyCounterKeyboardTrigger(Key.X), @@ -49,32 +49,29 @@ namespace osu.Game.Tests.Visual.Gameplay new KeyCounterMouseTrigger(MouseButton.Right), }); - var testCounter = (DefaultKeyCounter)kc.Counters.First(); + var testCounter = (DefaultKeyCounter)defaultDisplay.Counters.First(); AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); - kc.Add(new KeyCounterKeyboardTrigger(key)); - argonKc.Add(new KeyCounterKeyboardTrigger(key)); + defaultDisplay.Add(new KeyCounterKeyboardTrigger(key)); + argonDisplay.Add(new KeyCounterKeyboardTrigger(key)); }); - Key testKey = ((KeyCounterKeyboardTrigger)kc.Counters.First().Trigger).Key; - - void addPressKeyStep() - { - AddStep($"Press {testKey} key", () => InputManager.Key(testKey)); - } + Key testKey = ((KeyCounterKeyboardTrigger)defaultDisplay.Counters.First().Trigger).Key; addPressKeyStep(); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1); addPressKeyStep(); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2); - AddStep("Disable counting", () => testCounter.IsCounting.Value = false); + AddStep("Disable counting", () => defaultDisplay.IsCounting.Value = false); addPressKeyStep(); AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2); - Add(kc); - Add(argonKc); + Add(defaultDisplay); + Add(argonDisplay); + + void addPressKeyStep() => AddStep($"Press {testKey} key", () => InputManager.Key(testKey)); } } } From 0a861ffcee21bae0b235b88b2455e1f2d3bfe2d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 21:22:55 +0900 Subject: [PATCH 0556/1400] Restructure key counters to use a common flow --- .../Screens/Play/ArgonKeyCounterDisplay.cs | 14 ++++----- .../Play/HUD/DefaultKeyCounterDisplay.cs | 29 +++++++++---------- .../Screens/Play/HUD/KeyCounterDisplay.cs | 8 +++-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs b/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs index a62ac3d39a..984c2a7287 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounterDisplay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens.Play.HUD; @@ -13,13 +12,11 @@ namespace osu.Game.Screens.Play { private const int duration = 100; - private readonly FillFlowContainer keyFlow; - - public override IEnumerable Counters => keyFlow; + protected override FillFlowContainer KeyFlow { get; } public ArgonKeyCounterDisplay() { - InternalChild = keyFlow = new FillFlowContainer + InternalChild = KeyFlow = new FillFlowContainer { Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, @@ -32,13 +29,12 @@ namespace osu.Game.Screens.Play { base.Update(); - Size = keyFlow.Size; + Size = KeyFlow.Size; } - public override void Add(InputTrigger trigger) => - keyFlow.Add(new ArgonKeyCounter(trigger)); + protected override KeyCounter CreateCounter(InputTrigger trigger) => new ArgonKeyCounter(trigger); protected override void UpdateVisibility() - => keyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); + => KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); } } diff --git a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs index 14d7f56093..e459574243 100644 --- a/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultKeyCounterDisplay.cs @@ -1,7 +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 System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK.Graphics; @@ -13,13 +13,11 @@ namespace osu.Game.Screens.Play.HUD private const int duration = 100; private const double key_fade_time = 80; - private readonly FillFlowContainer keyFlow; - - public override IEnumerable Counters => keyFlow; + protected override FillFlowContainer KeyFlow { get; } public DefaultKeyCounterDisplay() { - InternalChild = keyFlow = new FillFlowContainer + InternalChild = KeyFlow = new FillFlowContainer { Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, @@ -33,20 +31,19 @@ namespace osu.Game.Screens.Play.HUD // Don't use autosize as it will shrink to zero when KeyFlow is hidden. // In turn this can cause the display to be masked off screen and never become visible again. - Size = keyFlow.Size; + Size = KeyFlow.Size; } - public override void Add(InputTrigger trigger) => - keyFlow.Add(new DefaultKeyCounter(trigger) - { - FadeTime = key_fade_time, - KeyDownTextColor = KeyDownTextColor, - KeyUpTextColor = KeyUpTextColor, - }); + protected override KeyCounter CreateCounter(InputTrigger trigger) => new DefaultKeyCounter(trigger) + { + FadeTime = key_fade_time, + KeyDownTextColor = KeyDownTextColor, + KeyUpTextColor = KeyUpTextColor, + }; protected override void UpdateVisibility() => // Isolate changing visibility of the key counters from fading this component. - keyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); + KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration); private Color4 keyDownTextColor = Color4.DarkGray; @@ -58,7 +55,7 @@ namespace osu.Game.Screens.Play.HUD if (value != keyDownTextColor) { keyDownTextColor = value; - foreach (var child in keyFlow) + foreach (var child in KeyFlow.Cast()) child.KeyDownTextColor = value; } } @@ -74,7 +71,7 @@ namespace osu.Game.Screens.Play.HUD if (value != keyUpTextColor) { keyUpTextColor = value; - foreach (var child in keyFlow) + foreach (var child in KeyFlow.Cast()) child.KeyUpTextColor = value; } } diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index 49c0da6793..e218155af2 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -29,7 +29,9 @@ namespace osu.Game.Screens.Play.HUD /// /// The s contained in this . /// - public abstract IEnumerable Counters { get; } + public IEnumerable Counters => KeyFlow; + + protected abstract FillFlowContainer KeyFlow { get; } /// /// Whether the actions reported by all s within this should be counted. @@ -53,13 +55,15 @@ namespace osu.Game.Screens.Play.HUD /// /// Add a to this display. /// - public abstract void Add(InputTrigger trigger); + public void Add(InputTrigger trigger) => KeyFlow.Add(CreateCounter(trigger)); /// /// Add a range of to this display. /// public void AddRange(IEnumerable triggers) => triggers.ForEach(Add); + protected abstract KeyCounter CreateCounter(InputTrigger trigger); + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { From 6b4032e34b57fba897a4f8906a9097c6543acb30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 21:31:39 +0900 Subject: [PATCH 0557/1400] Add missing binding of `IsCounting` with contained counters --- osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs index e218155af2..05427d3a32 100644 --- a/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/KeyCounterDisplay.cs @@ -55,7 +55,14 @@ namespace osu.Game.Screens.Play.HUD /// /// Add a to this display. /// - public void Add(InputTrigger trigger) => KeyFlow.Add(CreateCounter(trigger)); + public void Add(InputTrigger trigger) + { + var keyCounter = CreateCounter(trigger); + + KeyFlow.Add(keyCounter); + + IsCounting.BindTo(keyCounter.IsCounting); + } /// /// Add a range of to this display. From e08d7daffd7c5f582f98a43cad3f2fd2d64829bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Apr 2023 21:43:14 +0900 Subject: [PATCH 0558/1400] Don't show decimal point in tooltip --- osu.Game/Localisation/EditorStrings.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 7c9b52275d..20258b9c35 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -100,14 +100,14 @@ namespace osu.Game.Localisation public static LocalisableString TimelineTicks => new TranslatableString(getKey(@"timeline_ticks"), @"Ticks"); /// - /// "{0:0.0}°" + /// "{0:0}°" /// - public static LocalisableString RotationUnsnapped(float newRotation) => new TranslatableString(getKey(@"rotation_unsnapped"), @"{0:0.0}°", newRotation); + public static LocalisableString RotationUnsnapped(float newRotation) => new TranslatableString(getKey(@"rotation_unsnapped"), @"{0:0}°", newRotation); /// - /// "{0:0.0}° (snapped)" + /// "{0:0}° (snapped)" /// - public static LocalisableString RotationSnapped(float newRotation) => new TranslatableString(getKey(@"rotation_snapped"), @"{0:0.0}° (snapped)", newRotation); + public static LocalisableString RotationSnapped(float newRotation) => new TranslatableString(getKey(@"rotation_snapped"), @"{0:0}° (snapped)", newRotation); private static string getKey(string key) => $@"{prefix}:{key}"; } From c37875bee824e8c00bbc0d07273dbd98cbef5930 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 15:53:36 +0200 Subject: [PATCH 0559/1400] remove hitobject SampleControlPoint usage from LegacyBeatmapEncoder --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 072e442dea..04786cc9fb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -92,7 +92,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"AudioLeadIn: {beatmap.BeatmapInfo.AudioLeadIn}")); writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); writer.WriteLine(FormattableString.Invariant($"Countdown: {(int)beatmap.BeatmapInfo.Countdown}")); - writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank((beatmap.HitObjects.FirstOrDefault()?.SampleControlPoint ?? SampleControlPoint.DEFAULT).SampleBank)}")); + writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(((beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePoints?.FirstOrDefault() ?? SampleControlPoint.DEFAULT).SampleBank)}")); writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); writer.WriteLine(FormattableString.Invariant($"Mode: {onlineRulesetID}")); writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}")); @@ -268,7 +268,12 @@ namespace osu.Game.Beatmaps.Formats { foreach (var hitObject in hitObjects) { - yield return hitObject.SampleControlPoint; + if (hitObject.Samples.Count > 0) + { + int volume = hitObject.Samples.Max(o => o.Volume); + int customIndex = hitObject.Samples.OfType().Max(o => o.CustomSampleBank); + yield return new LegacyBeatmapDecoder.LegacySampleControlPoint { Time = hitObject.GetEndTime(), SampleVolume = volume, CustomSampleBank = customIndex }; + } foreach (var nested in collectSampleControlPoints(hitObject.NestedHitObjects)) yield return nested; From a6346171575e76ba0bf1b043040bbd0db8188b4e Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 16:01:06 +0200 Subject: [PATCH 0560/1400] Fix file header notice --- osu.Game/Context/{IHasContext.cs => ContextContainer.cs} | 5 ++++- osu.Game/Context/IContext.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) rename osu.Game/Context/{IHasContext.cs => ContextContainer.cs} (94%) diff --git a/osu.Game/Context/IHasContext.cs b/osu.Game/Context/ContextContainer.cs similarity index 94% rename from osu.Game/Context/IHasContext.cs rename to osu.Game/Context/ContextContainer.cs index bee81ea555..7ff0280bcf 100644 --- a/osu.Game/Context/IHasContext.cs +++ b/osu.Game/Context/ContextContainer.cs @@ -1,4 +1,7 @@ -using System; +// 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.Context diff --git a/osu.Game/Context/IContext.cs b/osu.Game/Context/IContext.cs index f70cdea9f8..61b1b11f43 100644 --- a/osu.Game/Context/IContext.cs +++ b/osu.Game/Context/IContext.cs @@ -1,4 +1,7 @@ -namespace osu.Game.Context; +// 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.Context; public interface IContext { From ebe1d852f53a80f3775f0ff602e95e8a74f3ca65 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 16:01:43 +0200 Subject: [PATCH 0561/1400] remove other usages of hitobject SampleControlPoint --- osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs | 2 +- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 6 +++--- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 8 +------- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 1 - osu.Game/Rulesets/UI/Playfield.cs | 4 ++-- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs b/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs index 5b59a81f91..a2ae1764dd 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckMutedObjects.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Edit.Checks yield break; // Samples that allow themselves to be overridden by control points have a volume of 0. - int maxVolume = sampledHitObject.Samples.Max(sample => sample.Volume > 0 ? sample.Volume : sampledHitObject.SampleControlPoint.SampleVolume); + int maxVolume = sampledHitObject.Samples.Max(sample => sample.Volume); double samplePlayTime = sampledHitObject.GetEndTime(); EdgeType edgeType = getEdgeAtTime(hitObject, samplePlayTime); diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index f810f51027..91dd7754d0 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -74,9 +74,9 @@ namespace osu.Game.Rulesets.Edit /// Whether this call is committing a value for HitObject.StartTime and continuing with further adjustments. protected void BeginPlacement(bool commitStart = false) { - var nearestSampleControlPoint = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.SampleControlPoint?.DeepClone() as SampleControlPoint; - - HitObject.SampleControlPoint = nearestSampleControlPoint ?? new SampleControlPoint(); + // Take the hitnormal sample of the last hit object + var lastHitNormal = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); + HitObject.Samples.Add(lastHitNormal); placementHandler.BeginPlacement(HitObject); if (commitStart) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f6c3452e48..79fc778287 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -357,13 +357,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (samples.Length <= 0) return; - if (HitObject.SampleControlPoint == null) - { - throw new InvalidOperationException($"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - } - - Samples.Samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); + Samples.Samples = samples.Cast().ToArray(); } private void onSamplesChanged(object sender, NotifyCollectionChangedEventArgs e) => LoadSamples(); diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index e1c03e49e3..d4510a4519 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -52,7 +52,6 @@ namespace osu.Game.Rulesets.UI return; var samples = nextObject.Samples - .Select(s => nextObject.SampleControlPoint.ApplyTo(s)) .Cast() .ToArray(); diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b1c3b78e67..6016a53918 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -293,10 +293,10 @@ namespace osu.Game.Rulesets.UI { // prepare sample pools ahead of time so we're not initialising at runtime. foreach (var sample in hitObject.Samples) - prepareSamplePool(hitObject.SampleControlPoint.ApplyTo(sample)); + prepareSamplePool(sample); foreach (var sample in hitObject.AuxiliarySamples) - prepareSamplePool(hitObject.SampleControlPoint.ApplyTo(sample)); + prepareSamplePool(sample); foreach (var nestedObject in hitObject.NestedHitObjects) preloadSamples(nestedObject); From 065464d90cae0c7ea887be51b7ca171011f70560 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 18:12:53 +0200 Subject: [PATCH 0562/1400] Fixed DifficultyPointPiece --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 9 ++- .../Rulesets/Objects/Legacy/ConvertSlider.cs | 9 ++- .../Objects/Types/IHasSliderVelocity.cs | 4 + .../Timeline/DifficultyPointPiece.cs | 23 ++++-- .../Timeline/HitObjectPointPiece.cs | 77 +++++++++---------- .../Components/Timeline/SamplePointPiece.cs | 5 +- .../Timeline/TimelineHitObjectBlueprint.cs | 45 ++++------- 7 files changed, 90 insertions(+), 82 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 73ac184c57..efb98ba888 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -135,7 +136,13 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool OnlyJudgeNestedObjects = true; - public double SliderVelocity { get; set; } = 1; + public BindableDouble SliderVelocityBindable = new BindableDouble(1); + + public double SliderVelocity + { + get => SliderVelocityBindable.Value; + set => SliderVelocityBindable.Value = value; + } [JsonIgnore] public SliderHeadCircle HeadCircle { get; protected set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index f602cbac09..94d21a06ed 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -40,7 +41,13 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Velocity = 1; - public double SliderVelocity { get; set; } = 1; + public BindableDouble SliderVelocityBindable = new BindableDouble(1); + + public double SliderVelocity + { + get => SliderVelocityBindable.Value; + set => SliderVelocityBindable.Value = value; + } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty) { diff --git a/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs index a7195dab4b..c0ac5036ee 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; + namespace osu.Game.Rulesets.Objects.Types; /// @@ -12,4 +14,6 @@ public interface IHasSliderVelocity /// The slider velocity multiplier. /// double SliderVelocity { get; set; } + + BindableNumber SliderVelocityBindable { get; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index d3cdd461ea..4741b75641 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -13,12 +13,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Screens.Edit.Timing; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { @@ -29,13 +31,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly BindableNumber speedMultiplier; public DifficultyPointPiece(HitObject hitObject) - : base(hitObject.DifficultyControlPoint) { HitObject = hitObject; - speedMultiplier = hitObject.DifficultyControlPoint.SliderVelocityBindable.GetBoundCopy(); + speedMultiplier = (hitObject as IHasSliderVelocity)?.SliderVelocityBindable.GetBoundCopy(); } + protected override Color4 GetRepresentingColour(OsuColour colours) => colours.Lime1; + protected override void LoadComplete() { base.LoadComplete(); @@ -78,7 +81,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline Spacing = new Vector2(0, 15), Children = new Drawable[] { - sliderVelocitySlider = new IndeterminateSliderWithTextBoxInput("Velocity", new DifficultyControlPoint().SliderVelocityBindable) + sliderVelocitySlider = new IndeterminateSliderWithTextBoxInput("Velocity", new BindableDouble(1) + { + Precision = 0.01, + MinValue = 0.1, + MaxValue = 10 + }) { KeyboardStep = 0.1f }, @@ -94,11 +102,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // if the piece belongs to a currently selected object, assume that the user wants to change all selected objects. // if the piece belongs to an unselected object, operate on that object alone, independently of the selection. - var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).ToArray(); - var relevantControlPoints = relevantObjects.Select(h => h.DifficultyControlPoint).ToArray(); + var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).Where(o => o is IHasSliderVelocity).ToArray(); // even if there are multiple objects selected, we can still display a value if they all have the same value. - var selectedPointBindable = relevantControlPoints.Select(point => point.SliderVelocity).Distinct().Count() == 1 ? relevantControlPoints.First().SliderVelocityBindable : null; + var selectedPointBindable = relevantObjects.Select(point => ((IHasSliderVelocity)point).SliderVelocity).Distinct().Count() == 1 ? ((IHasSliderVelocity)relevantObjects.First()).SliderVelocityBindable : null; if (selectedPointBindable != null) { @@ -117,7 +124,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline foreach (var h in relevantObjects) { - h.DifficultyControlPoint.SliderVelocity = val.NewValue.Value; + ((IHasSliderVelocity)h).SliderVelocity = val.NewValue.Value; beatmap.Update(h); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs index 5b0a5729c8..bd699c2e88 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs @@ -7,59 +7,54 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; -namespace osu.Game.Screens.Edit.Compose.Components.Timeline +namespace osu.Game.Screens.Edit.Compose.Components.Timeline; + +public partial class HitObjectPointPiece : CircularContainer { - public partial class HitObjectPointPiece : CircularContainer + protected OsuSpriteText Label { get; private set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - private readonly ControlPoint point; + AutoSizeAxes = Axes.Both; - protected OsuSpriteText Label { get; private set; } + Color4 colour = GetRepresentingColour(colours); - protected HitObjectPointPiece(ControlPoint point) + InternalChildren = new Drawable[] { - this.point = point; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.Both; - - Color4 colour = point.GetRepresentingColour(colours); - - InternalChildren = new Drawable[] + new Container { - new Container + AutoSizeAxes = Axes.X, + Height = 16, + Masking = true, + CornerRadius = 8, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Children = new Drawable[] { - AutoSizeAxes = Axes.X, - Height = 16, - Masking = true, - CornerRadius = 8, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Children = new Drawable[] + new Box { - new Box - { - Colour = colour, - RelativeSizeAxes = Axes.Both, - }, - Label = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Padding = new MarginPadding(5), - Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold), - Colour = colours.B5, - } + Colour = colour, + RelativeSizeAxes = Axes.Both, + }, + Label = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding(5), + Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold), + Colour = colours.B5, } - }, - }; - } + } + }, + }; + + protected virtual Color4 GetRepresentingColour(OsuColour colours) + { + return colours.Yellow; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs index 314137a565..50278bffc0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs @@ -13,10 +13,12 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Timing; using osuTK; +using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components.Timeline { @@ -28,13 +30,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly BindableNumber volume; public SamplePointPiece(HitObject hitObject) - : base(hitObject.SampleControlPoint) { HitObject = hitObject; volume = hitObject.SampleControlPoint.SampleVolumeBindable.GetBoundCopy(); bank = hitObject.SampleControlPoint.SampleBankBindable.GetBoundCopy(); } + protected override Color4 GetRepresentingColour(OsuColour colours) => colours.Pink; + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 4e5087c004..de659cddb8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -102,6 +102,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }, } }, + sampleOverrideDisplay = new SamplePointPiece(Item) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.TopCentre + }, }); if (item is IHasDuration) @@ -111,6 +116,16 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline OnDragHandled = e => OnDragHandled?.Invoke(e) }); } + + if (item is IHasSliderVelocity) + { + AddInternal(difficultyOverrideDisplay = new DifficultyPointPiece(Item) + { + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomCentre + } + ); + } } protected override void LoadComplete() @@ -208,36 +223,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (Item is IHasRepeats repeats) updateRepeats(repeats); } - - if (!ReferenceEquals(difficultyControlPoint, Item.DifficultyControlPoint)) - { - difficultyControlPoint = Item.DifficultyControlPoint; - difficultyOverrideDisplay?.Expire(); - - if (Item.DifficultyControlPoint != null && Item is IHasDistance) - { - AddInternal(difficultyOverrideDisplay = new DifficultyPointPiece(Item) - { - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomCentre - }); - } - } - - if (!ReferenceEquals(sampleControlPoint, Item.SampleControlPoint)) - { - sampleControlPoint = Item.SampleControlPoint; - sampleOverrideDisplay?.Expire(); - - if (Item.SampleControlPoint != null) - { - AddInternal(sampleOverrideDisplay = new SamplePointPiece(Item) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.TopCentre - }); - } - } } private void updateRepeats(IHasRepeats repeats) From c23a7b014eb7a6a4b984bafc85459044cf29323e Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 18:17:07 +0200 Subject: [PATCH 0563/1400] add missing } --- .../Edit/Compose/Components/Timeline/HitObjectPointPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs index bd699c2e88..f7854705a4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs @@ -52,6 +52,7 @@ public partial class HitObjectPointPiece : CircularContainer } }, }; + } protected virtual Color4 GetRepresentingColour(OsuColour colours) { From 66eda40cdf1911c2c4139c00fa9ebc8478058168 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 18:22:22 +0200 Subject: [PATCH 0564/1400] fix implementations of IHasSliderVelocity --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index efb98ba888..e8eb197186 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool OnlyJudgeNestedObjects = true; - public BindableDouble SliderVelocityBindable = new BindableDouble(1); + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); public double SliderVelocity { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 94d21a06ed..7ddd372dc9 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public double Velocity = 1; - public BindableDouble SliderVelocityBindable = new BindableDouble(1); + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); public double SliderVelocity { From 755ad25dbe22987fd1cd5e0c851adf1f99698640 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 18:27:20 +0200 Subject: [PATCH 0565/1400] clean code --- .../Components/Timeline/TimelineHitObjectBlueprint.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index de659cddb8..1c36bec53e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }, } }, - sampleOverrideDisplay = new SamplePointPiece(Item) + new SamplePointPiece(Item) { Anchor = Anchor.BottomLeft, Origin = Anchor.TopCentre @@ -119,7 +119,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (item is IHasSliderVelocity) { - AddInternal(difficultyOverrideDisplay = new DifficultyPointPiece(Item) + AddInternal(new DifficultyPointPiece(Item) { Anchor = Anchor.TopLeft, Origin = Anchor.BottomCentre @@ -202,12 +202,6 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline colouredComponents.Colour = OsuColour.ForegroundTextColourFor(averageColour); } - private SamplePointPiece? sampleOverrideDisplay; - private DifficultyPointPiece? difficultyOverrideDisplay; - - private DifficultyControlPoint difficultyControlPoint = null!; - private SampleControlPoint sampleControlPoint = null!; - protected override void Update() { base.Update(); From e4b64bdc3e0b3e3074c76a8286e986acfdeedb57 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 25 Apr 2023 19:06:29 +0200 Subject: [PATCH 0566/1400] clean up code stuff --- .../Patterns/Legacy/DistanceObjectPatternGenerator.cs | 1 - osu.Game.Rulesets.Osu/Objects/Slider.cs | 1 - .../Components/Timeline/TimelineHitObjectBlueprint.cs | 9 ++++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index b3a68269f7..2427812ecd 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Legacy; using osu.Game.Utils; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index e8eb197186..247cf94f59 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -8,7 +8,6 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; -using System.Text.Json.Serialization; using System.Threading; using Newtonsoft.Json; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 1c36bec53e..c2106e0598 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -120,11 +120,10 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (item is IHasSliderVelocity) { AddInternal(new DifficultyPointPiece(Item) - { - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomCentre - } - ); + { + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomCentre + }); } } From 753fa09356a2864060d0c8eb2dd95a29a7041785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 25 Apr 2023 20:10:11 +0200 Subject: [PATCH 0567/1400] Fix test failures due to type mismatch --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index eecead5415..ae46dda750 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); + private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 7bbfc6a62b..0439656aae 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Gameplay // best way to check without exposing. private Drawable hideTarget => hudOverlay.KeyCounter; - private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); + private Drawable keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType>().Single(); [Test] public void TestComboCounterIncrementing() From 196b5b41eb07f7e0377c84b0d8ca381386dbc541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 25 Apr 2023 20:17:52 +0200 Subject: [PATCH 0568/1400] Also disable counting on argon display in test Mostly for my own peace of mind. --- osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index aabc25d660..22f7111f68 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -64,7 +64,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1); addPressKeyStep(); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2); - AddStep("Disable counting", () => defaultDisplay.IsCounting.Value = false); + AddStep("Disable counting", () => + { + argonDisplay.IsCounting.Value = false; + defaultDisplay.IsCounting.Value = false; + }); addPressKeyStep(); AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2); From 0841e73a39ba4c383a62e8897ed55b653f66be1a Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 25 Apr 2023 21:05:40 +0200 Subject: [PATCH 0569/1400] Improved readability and sounds --- osu.Game.Tests/Mods/ModSettingsTest.cs | 29 +++----- osu.Game/OsuGameBase.cs | 35 ++++++---- osu.Game/Rulesets/Mods/Mod.cs | 95 +++++++++++--------------- 3 files changed, 69 insertions(+), 90 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index d943f0ffb1..b3f6f8da7d 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -43,18 +43,18 @@ namespace osu.Game.Tests.Mods var modDouble = new TestNonMatchingSettingTypeModDouble { TestSetting = { Value = setting_change } }; var modBool = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = (int)setting_change } }; + var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = (int)setting_change / 2 } }; - modDouble.CopySharedSettings(modBool); - modDouble.CopySharedSettings(modInt); - modBool.CopySharedSettings(modDouble); - modBool.CopySharedSettings(modInt); - modInt.CopySharedSettings(modDouble); - modInt.CopySharedSettings(modBool); + modDouble.CopyCommonSettings(modBool); + modDouble.CopyCommonSettings(modInt); + modBool.CopyCommonSettings(modDouble); + modBool.CopyCommonSettings(modInt); + modInt.CopyCommonSettings(modDouble); + modInt.CopyCommonSettings(modBool); Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); - Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change)); + Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change / 2)); } [Test] @@ -63,23 +63,12 @@ namespace osu.Game.Tests.Mods var modBoolTrue = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = true, Value = false } }; var modBoolFalse = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - modBoolFalse.CopySharedSettings(modBoolTrue); + modBoolFalse.CopyCommonSettings(modBoolTrue); Assert.That(modBoolFalse.TestSetting.Default, Is.EqualTo(false)); Assert.That(modBoolFalse.TestSetting.Value, Is.EqualTo(modBoolTrue.TestSetting.Value)); } - [Test] - public void TestValueResetsToDefaultWhenCopied() - { - var modDouble = new TestNonMatchingSettingTypeModDouble(); - var modBool = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - - modBool.CopySharedSettings(modDouble); - - Assert.That(modBool.TestSetting.Value, Is.EqualTo(modBool.TestSetting.Default)); - } - private class TestNonMatchingSettingTypeModDouble : TestNonMatchingSettingTypeMod { public override string Acronym => "NMD"; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index de1f2e810c..f6cda62cc3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -58,7 +58,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; -using File = System.IO.File; using RuntimeInfo = osu.Framework.RuntimeInfo; namespace osu.Game @@ -71,7 +70,7 @@ namespace osu.Game [Cached(typeof(OsuGameBase))] public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider { - public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv" }; + public static readonly string[] VIDEO_EXTENSIONS = { ".mp4", ".mov", ".avi", ".flv", ".mpg", ".wmv", ".m4v" }; public const string OSU_PROTOCOL = "osu://"; @@ -626,20 +625,30 @@ namespace osu.Game return; } + var previouslySelectedCommonMods = new List(SelectedMods.Value.Count); + var convertedCommonMods = new List(SelectedMods.Value.Count); + + foreach (var mod in SelectedMods.Value) + { + var convertedMod = instance.CreateModFromAcronym(mod.Acronym); + + if (convertedMod == null) + continue; + + previouslySelectedCommonMods.Add(mod); + + convertedMod.CopyCommonSettings(mod); + convertedCommonMods.Add(convertedMod); + } + + if (!SelectedMods.Disabled) + // Select common mods to play the deselect samples for other mods + SelectedMods.Value = previouslySelectedCommonMods; + AvailableMods.Value = dict; if (!SelectedMods.Disabled) - { - //converting mods from one ruleset to the other, while also keeping their shared settings unchanged - SelectedMods.Value = SelectedMods.Value.Select(oldMod => - { - Mod newMod = instance.CreateModFromAcronym(oldMod.Acronym); - - newMod?.CopySharedSettings(oldMod); - - return newMod; - }).Where(m => m != null).ToArray(); - } + SelectedMods.Value = convertedCommonMods; void revertRulesetChange() => Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); } diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 623a734b82..97434ce493 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -115,21 +115,25 @@ namespace osu.Game.Rulesets.Mods [JsonIgnore] public virtual Type[] IncompatibleMods => Array.Empty(); - private IReadOnlyList? settingsBacking; + private IReadOnlyDictionary? settingsBacking; /// - /// A list of the all settings within this mod. + /// All settings within this mod. /// - internal IReadOnlyList Settings => + internal IEnumerable SettingsBindables => Settings.Values; + + /// + /// Provides mapping of names to s of all settings within this mod. + /// + internal IReadOnlyDictionary Settings => settingsBacking ??= this.GetSettingsSourceProperties() - .Select(p => p.Item2.GetValue(this)) - .Cast() - .ToList(); + .Select(p => p.Item2) + .ToDictionary(property => property.Name.ToSnakeCase(), property => (IBindable)property.GetValue(this)!); /// /// Whether all settings in this mod are set to their default state. /// - protected virtual bool UsesDefaultConfiguration => Settings.All(s => s.IsDefault); + protected virtual bool UsesDefaultConfiguration => SettingsBindables.All(s => s.IsDefault); /// /// Creates a copy of this initialised to a default state. @@ -160,60 +164,37 @@ namespace osu.Game.Rulesets.Mods } /// - /// Copies all mod setting values sharing same from into this instance. + /// When converting mods from one ruleset to the other, this method makes sure + /// to also copy the values of all settings sharing same between the two instances. /// - /// The mod to copy properties from. - internal void CopySharedSettings(Mod source) + /// Copied values are unchanged, even if they have different clamping ranges. + /// The mod to extract settings from. + public void CopyCommonSettings(Mod source) { - const string value = nameof(Bindable.Value); + if (source.UsesDefaultConfiguration) + return; - Dictionary sourceSettings = new Dictionary(); - - foreach (var (_, sourceProperty) in source.GetSettingsSourceProperties()) + foreach (var (name, targetSetting) in Settings) { - sourceSettings.Add(sourceProperty.Name.ToSnakeCase(), sourceProperty.GetValue(source)!); + if (!source.Settings.TryGetValue(name, out IBindable? sourceSetting)) + continue; + + if (sourceSetting.IsDefault) + continue; + + if (getBindableGenericType(targetSetting) != getBindableGenericType(sourceSetting)) + continue; + + // TODO: special case for handling number types + + PropertyInfo property = targetSetting.GetType().GetProperty(nameof(Bindable.Value))!; + property.SetValue(targetSetting, property.GetValue(sourceSetting)); } - foreach (var (_, targetProperty) in this.GetSettingsSourceProperties()) - { - object targetSetting = targetProperty.GetValue(this)!; - - if (!sourceSettings.TryGetValue(targetProperty.Name.ToSnakeCase(), out object? sourceSetting)) - continue; - - if (((IBindable)sourceSetting).IsDefault) - { - // reset to default value if the source is default - targetSetting.GetType().GetMethod(nameof(Bindable.SetDefault))!.Invoke(targetSetting, null); - continue; - } - - bool hasSameGenericArgument = getGenericBaseType(targetSetting, typeof(Bindable<>))!.GenericTypeArguments.Single() == - getGenericBaseType(sourceSetting, typeof(Bindable<>))!.GenericTypeArguments.Single(); - - if (!hasSameGenericArgument) - continue; - - Type? targetBindableNumberType = getGenericBaseType(targetSetting, typeof(BindableNumber<>)); - Type? sourceBindableNumberType = getGenericBaseType(sourceSetting, typeof(BindableNumber<>)); - - if (targetBindableNumberType == null || sourceBindableNumberType == null) - { - setValue(targetSetting, value, getValue(sourceSetting, value)); - continue; - } - - setValue(targetSetting, value, Convert.ChangeType(getValue(sourceSetting, value), targetBindableNumberType.GenericTypeArguments.Single())); - } - - object? getValue(object setting, string name) => - setting.GetType().GetProperty(name)!.GetValue(setting); - - void setValue(object setting, string name, object? newValue) => - setting.GetType().GetProperty(name)!.SetValue(setting, newValue); - - Type? getGenericBaseType(object setting, Type genericType) => - setting.GetType().GetTypeInheritance().FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == genericType); + Type getBindableGenericType(IBindable setting) => + setting.GetType().GetTypeInheritance() + .First(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Bindable<>)) + .GenericTypeArguments.Single(); } /// @@ -250,7 +231,7 @@ namespace osu.Game.Rulesets.Mods if (ReferenceEquals(this, other)) return true; return GetType() == other.GetType() && - Settings.SequenceEqual(other.Settings, ModSettingsEqualityComparer.Default); + SettingsBindables.SequenceEqual(other.SettingsBindables, ModSettingsEqualityComparer.Default); } public override int GetHashCode() @@ -259,7 +240,7 @@ namespace osu.Game.Rulesets.Mods hashCode.Add(GetType()); - foreach (var setting in Settings) + foreach (var setting in SettingsBindables) hashCode.Add(setting.GetUnderlyingSettingValue()); return hashCode.ToHashCode(); From 8e297dc60a18a9d7057d4b7525ec8cd6189bb504 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 25 Apr 2023 21:28:03 +0200 Subject: [PATCH 0570/1400] Added safety measures for invalid mod combinations --- osu.Game/OsuGameBase.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f6cda62cc3..0473f2665b 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -641,6 +641,16 @@ namespace osu.Game convertedCommonMods.Add(convertedMod); } + if (!ModUtils.CheckValidForGameplay(convertedCommonMods, out var invalid)) + { + invalid.ForEach(mod => + { + int index = convertedCommonMods.IndexOf(mod); + convertedCommonMods.RemoveAt(index); + previouslySelectedCommonMods.RemoveAt(index); + }); + } + if (!SelectedMods.Disabled) // Select common mods to play the deselect samples for other mods SelectedMods.Value = previouslySelectedCommonMods; From 1efc78c0f8a7c3b17062c9a90318da3ef41a986c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2023 13:28:51 +0900 Subject: [PATCH 0571/1400] Actually use new end time property when setting lifetimes --- osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index e598c79b08..be77c9a98e 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -85,7 +85,7 @@ namespace osu.Game.Storyboards.Drawables Loop = animation.LoopType == AnimationLoopType.LoopForever; LifetimeStart = animation.StartTime; - LifetimeEnd = animation.EndTime; + LifetimeEnd = animation.EndTimeForDisplay; } [Resolved] diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index f9b09ed57c..400d33481c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -82,7 +82,7 @@ namespace osu.Game.Storyboards.Drawables Position = sprite.InitialPosition; LifetimeStart = sprite.StartTime; - LifetimeEnd = sprite.EndTime; + LifetimeEnd = sprite.EndTimeForDisplay; } [Resolved] From cb7b246e3352c08b73119b88fb0966e118720e2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 Apr 2023 15:27:58 +0900 Subject: [PATCH 0572/1400] Fix naming and update in line with nullability --- osu.Game/Rulesets/Mods/ModFailCondition.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFailCondition.cs b/osu.Game/Rulesets/Mods/ModFailCondition.cs index 63cebc9747..97789b7f5a 100644 --- a/osu.Game/Rulesets/Mods/ModFailCondition.cs +++ b/osu.Game/Rulesets/Mods/ModFailCondition.cs @@ -19,18 +19,19 @@ namespace osu.Game.Rulesets.Mods public virtual bool PerformFail() => true; public virtual bool RestartOnFail => Restart.Value; - private event Action failureTriggered; + + private Action? triggerFailureDelegate; public void ApplyToHealthProcessor(HealthProcessor healthProcessor) { - failureTriggered = healthProcessor.TriggerFailure; + triggerFailureDelegate = healthProcessor.TriggerFailure; healthProcessor.FailConditions += FailCondition; } /// /// Immediately triggers a failure on the loaded . /// - protected void TriggerFailure() => failureTriggered?.Invoke(); + protected void TriggerFailure() => triggerFailureDelegate?.Invoke(); /// /// Determines whether should trigger a failure. Called every time a From bfd81b77fa58ce67acefe3264ba05fadb8abf97a Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 26 Apr 2023 17:40:25 +0900 Subject: [PATCH 0573/1400] provide more Accuracy Mode for `ModAccuracyChallenge` --- .../Rulesets/Mods/ModAccuracyChallenge.cs | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index d4223a80c2..03149fd8c8 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Configuration; +using osu.Game.Localisation.HUD; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Judgements; @@ -42,30 +43,44 @@ namespace osu.Game.Rulesets.Mods Value = 0.9, }; - private ScoreProcessor scoreProcessor = null!; + [SettingSource("Accuracy Mode", "The Accuracy mode that will be used to Judge.")] + public Bindable AccuracyJudgeMode { get; } = new Bindable(); - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) => this.scoreProcessor = scoreProcessor; + private readonly Bindable currentAccuracy = new Bindable(); + + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + switch (AccuracyJudgeMode.Value) + { + case AccuracyMode.Standard: + currentAccuracy.BindTo(scoreProcessor.Accuracy); + break; + + case AccuracyMode.MaximumAchievable: + currentAccuracy.BindTo(scoreProcessor.MaximumAccuracy); + break; + } + + currentAccuracy.BindValueChanged(s => + { + if (s.NewValue < MinimumAccuracy.Value) + { + TriggerFailure(); + } + }); + } public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) + protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => false; + + public enum AccuracyMode { - if (!result.Type.AffectsAccuracy()) - return false; + [LocalisableDescription(typeof(GameplayAccuracyCounterStrings), nameof(GameplayAccuracyCounterStrings.AccuracyDisplayModeStandard))] + Standard, - return getAccuracyWithImminentResultAdded(result) < MinimumAccuracy.Value; - } - - private double getAccuracyWithImminentResultAdded(JudgementResult result) - { - var score = new ScoreInfo { Ruleset = scoreProcessor.Ruleset.RulesetInfo }; - - // This is super ugly, but if we don't do it this way we will not have the most recent result added to the accuracy value. - // Hopefully we can improve this in the future. - scoreProcessor.PopulateScore(score); - score.Statistics[result.Type]++; - - return scoreProcessor.ComputeAccuracy(score); + [LocalisableDescription(typeof(GameplayAccuracyCounterStrings), nameof(GameplayAccuracyCounterStrings.AccuracyDisplayModeMax))] + MaximumAchievable, } } } From 332c199dc2b0cdabe76e56dc8696d6ee52f58fa9 Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 26 Apr 2023 10:46:29 +0200 Subject: [PATCH 0574/1400] further simplification --- osu.Game/Rulesets/Mods/Mod.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 97434ce493..0af8717264 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using AutoMapper.Internal; using Newtonsoft.Json; using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; @@ -182,7 +181,10 @@ namespace osu.Game.Rulesets.Mods if (sourceSetting.IsDefault) continue; - if (getBindableGenericType(targetSetting) != getBindableGenericType(sourceSetting)) + var targetType = targetSetting.GetType(); + var sourceType = sourceSetting.GetType(); + + if (!targetType.IsAssignableFrom(sourceType) && !sourceType.IsAssignableFrom(targetType)) continue; // TODO: special case for handling number types @@ -190,11 +192,6 @@ namespace osu.Game.Rulesets.Mods PropertyInfo property = targetSetting.GetType().GetProperty(nameof(Bindable.Value))!; property.SetValue(targetSetting, property.GetValue(sourceSetting)); } - - Type getBindableGenericType(IBindable setting) => - setting.GetType().GetTypeInheritance() - .First(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Bindable<>)) - .GenericTypeArguments.Single(); } /// From e27c4dfa101fe132f76614e32815c6a34ba455bc Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 11:46:05 +0200 Subject: [PATCH 0575/1400] Invoke ApplyDefaultsToSelf --- osu.Game/Rulesets/Objects/HitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 0502610eab..7702635057 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -105,6 +105,8 @@ namespace osu.Game.Rulesets.Objects /// The cancellation token. public void ApplyDefaults(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty, CancellationToken cancellationToken = default) { + ApplyDefaultsToSelf(controlPointInfo, difficulty); + nestedHitObjects.Clear(); CreateNestedHitObjects(cancellationToken); From 6c7094868163c7aeda18116d352739ba8309d57c Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 13:10:57 +0200 Subject: [PATCH 0576/1400] Remove IContext & add IHasGenerateTicks --- .../Legacy/DistanceObjectPatternGenerator.cs | 4 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 8 +- .../Beatmaps/TaikoBeatmapConverter.cs | 4 +- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +- osu.Game/Beatmaps/Legacy/LegacyContext.cs | 32 ------- osu.Game/Context/ContextContainer.cs | 91 ------------------- osu.Game/Context/IContext.cs | 13 --- osu.Game/Rulesets/Objects/HitObject.cs | 9 +- .../Objects/Types/IHasGenerateTicks.cs | 17 ++++ 9 files changed, 37 insertions(+), 147 deletions(-) delete mode 100644 osu.Game/Beatmaps/Legacy/LegacyContext.cs delete mode 100644 osu.Game/Context/ContextContainer.cs delete mode 100644 osu.Game/Context/IContext.cs create mode 100644 osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 2427812ecd..20f39deed7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); double beatLength; - if (hitObject.HasContext()) - beatLength = timingPoint.BeatLength * hitObject.GetContext().BpmMultiplier; + if (hitObject.LegacyBpmMultiplier.HasValue) + beatLength = timingPoint.BeatLength * hitObject.LegacyBpmMultiplier.Value; else if (hitObject is IHasSliderVelocity hasSliderVelocity) beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 247cf94f59..dd75a86f96 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -15,14 +15,13 @@ using osu.Framework.Caching; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { - public class Slider : OsuHitObject, IHasPathWithRepeats, IHasSliderVelocity + public class Slider : OsuHitObject, IHasPathWithRepeats, IHasSliderVelocity, IHasGenerateTicks { public double EndTime => StartTime + this.SpanCount() * Path.Distance / Velocity; @@ -143,6 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects set => SliderVelocityBindable.Value = value; } + public bool GenerateTicks { get; set; } + [JsonIgnore] public SliderHeadCircle HeadCircle { get; protected set; } @@ -162,10 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; - bool generateTicks = !HasContext() || GetContext().GenerateTicks; Velocity = scoringDistance / timingPoint.BeatLength; - TickDistance = generateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; + TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index ef73ffd517..2cf1d7a6ab 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -180,8 +180,8 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); double beatLength; - if (obj.HasContext()) - beatLength = timingPoint.BeatLength * obj.GetContext().BpmMultiplier; + if (obj.LegacyBpmMultiplier.HasValue) + beatLength = timingPoint.BeatLength * obj.LegacyBpmMultiplier.Value; else if (obj is IHasSliderVelocity hasSliderVelocity) beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocity; else diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index dad23df282..9a1935f929 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -105,7 +105,11 @@ namespace osu.Game.Beatmaps.Formats #pragma warning disable 618 if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint) #pragma warning restore 618 - hitObject.SetContext(new LegacyContext(legacyDifficultyControlPoint.BpmMultiplier, legacyDifficultyControlPoint.GenerateTicks)); + { + hitObject.LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier; + if (hitObject is IHasGenerateTicks hasGenerateTicks) + hasGenerateTicks.GenerateTicks = legacyDifficultyControlPoint.GenerateTicks; + } if (hitObject is IHasSliderVelocity hasSliderVelocity) hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity; diff --git a/osu.Game/Beatmaps/Legacy/LegacyContext.cs b/osu.Game/Beatmaps/Legacy/LegacyContext.cs deleted file mode 100644 index eeb02bdcb7..0000000000 --- a/osu.Game/Beatmaps/Legacy/LegacyContext.cs +++ /dev/null @@ -1,32 +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.Context; - -namespace osu.Game.Beatmaps.Legacy; - -public class LegacyContext : IContext -{ - public LegacyContext(double bpmMultiplier, bool generateTicks) - { - BpmMultiplier = bpmMultiplier; - GenerateTicks = generateTicks; - } - - /// - /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. - /// DO NOT USE THIS UNLESS 100% SURE. - /// - public double BpmMultiplier { get; } - - /// - /// Whether or not slider ticks should be generated at this control point. - /// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991). - /// - public bool GenerateTicks { get; } - - public IContext Copy() - { - return new LegacyContext(BpmMultiplier, GenerateTicks); - } -} diff --git a/osu.Game/Context/ContextContainer.cs b/osu.Game/Context/ContextContainer.cs deleted file mode 100644 index 7ff0280bcf..0000000000 --- a/osu.Game/Context/ContextContainer.cs +++ /dev/null @@ -1,91 +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.Context -{ - public abstract class ContextContainer - { - /// - /// The contexts of this container. - /// The objects always have the type of their key. - /// - private readonly Dictionary contexts; - - protected ContextContainer() - { - contexts = new Dictionary(); - } - - /// - /// Checks whether this object has the context with type T. - /// - /// The type to check the context of. - /// Whether the context object with type T exists in this object. - public bool HasContext() where T : IContext - { - return contexts.ContainsKey(typeof(T)); - } - - /// - /// Gets the context with type T. - /// - /// The type to get the context of. - /// If the context does not exist in this hit object. - /// The context object with type T. - public T GetContext() where T : IContext - { - return (T)contexts[typeof(T)]; - } - - /// - /// Tries to get the context with type T. - /// - /// The found context with type T. - /// The type to get the context of. - /// Whether the context exists in this object. - public bool TryGetContext(out T context) where T : IContext - { - if (contexts.TryGetValue(typeof(T), out var context2)) - { - context = (T)context2; - return true; - } - - context = default!; - return false; - } - - /// - /// Sets the context object of type T. - /// - /// The context type to set. - /// The context object to store in this object. - public void SetContext(T context) where T : IContext - { - contexts[typeof(T)] = context; - } - - /// - /// Removes the context of type T from this object. - /// - /// The type to remove the context of. - /// Whether a context was removed. - public bool RemoveContext() where T : IContext - { - return RemoveContext(typeof(T)); - } - - /// - /// Removes the context of type T from this object. - /// - /// The type to remove the context of. - /// Whether a context was removed. - public bool RemoveContext(Type t) - { - return contexts.Remove(t); - } - } -} diff --git a/osu.Game/Context/IContext.cs b/osu.Game/Context/IContext.cs deleted file mode 100644 index 61b1b11f43..0000000000 --- a/osu.Game/Context/IContext.cs +++ /dev/null @@ -1,13 +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.Context; - -public interface IContext -{ - /// - /// Makes a deep copy of this context. - /// - /// The deep copy of this context. - public IContext Copy(); -} diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 7702635057..aaeffa49fc 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -16,7 +16,6 @@ using osu.Framework.Lists; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Context; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Objects /// HitObjects may contain more properties for which you should be checking through the IHas* types. /// /// - public class HitObject : ContextContainer + public class HitObject { /// /// A small adjustment to the start time of control points to account for rounding/precision errors. @@ -80,6 +79,12 @@ namespace osu.Game.Rulesets.Objects public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT; public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT; + /// + /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. + /// DO NOT USE THIS UNLESS 100% SURE. + /// + public double? LegacyBpmMultiplier { get; set; } + /// /// Whether this is in Kiai time. /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs new file mode 100644 index 0000000000..5de7d348c5 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs @@ -0,0 +1,17 @@ +// 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.Rulesets.Objects.Types +{ + /// + /// A type of which may or may not generate ticks. + /// + public interface IHasGenerateTicks + { + /// + /// Whether or not slider ticks should be generated at this control point. + /// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991). + /// + public bool GenerateTicks { get; set; } + } +} From 39d9f0c3f5d689506a0971d22d9e40fab01ecee4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 13:22:13 +0200 Subject: [PATCH 0577/1400] removing using --- .../Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 20f39deed7..91b7be6e8f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Beatmaps.Legacy; using osu.Game.Utils; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy From 87ca0f5335ebd07abe29c3958bf2b5cd88f947ef Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 13:45:58 +0200 Subject: [PATCH 0578/1400] Update SamplePointPiece.cs --- .../Components/Timeline/SamplePointPiece.cs | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs index 50278bffc0..b02cfb505e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/SamplePointPiece.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; -using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Objects; @@ -26,14 +26,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { public readonly HitObject HitObject; - private readonly Bindable bank; - private readonly BindableNumber volume; + private readonly BindableList samplesBindable; public SamplePointPiece(HitObject hitObject) { HitObject = hitObject; - volume = hitObject.SampleControlPoint.SampleVolumeBindable.GetBoundCopy(); - bank = hitObject.SampleControlPoint.SampleBankBindable.GetBoundCopy(); + samplesBindable = hitObject.SamplesBindable.GetBoundCopy(); } protected override Color4 GetRepresentingColour(OsuColour colours) => colours.Pink; @@ -41,8 +39,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [BackgroundDependencyLoader] private void load() { - volume.BindValueChanged(_ => updateText()); - bank.BindValueChanged(_ => updateText(), true); + samplesBindable.BindCollectionChanged((_, _) => updateText(), true); } protected override bool OnClick(ClickEvent e) @@ -53,7 +50,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateText() { - Label.Text = $"{bank.Value} {volume.Value}"; + Label.Text = $"{GetBankValue(samplesBindable)} {GetVolumeValue(samplesBindable)}"; + } + + public static string? GetBankValue(IEnumerable samples) + { + return samples.FirstOrDefault()?.Bank; + } + + public static int GetVolumeValue(ICollection samples) + { + return samples.Count == 0 ? 0 : samples.Max(o => o.Volume); } public Popover GetPopover() => new SampleEditPopover(HitObject); @@ -92,7 +99,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { Label = "Bank Name", }, - volume = new IndeterminateSliderWithTextBoxInput("Volume", new SampleControlPoint().SampleVolumeBindable) + volume = new IndeterminateSliderWithTextBoxInput("Volume", new BindableInt(100) + { + MinValue = 0, + MaxValue = 100, + }) } } }; @@ -103,14 +114,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // if the piece belongs to a currently selected object, assume that the user wants to change all selected objects. // if the piece belongs to an unselected object, operate on that object alone, independently of the selection. var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).ToArray(); - var relevantControlPoints = relevantObjects.Select(h => h.SampleControlPoint).ToArray(); + var relevantSamples = relevantObjects.Select(h => h.Samples).ToArray(); // even if there are multiple objects selected, we can still display sample volume or bank if they all have the same value. - string? commonBank = getCommonBank(relevantControlPoints); + string? commonBank = getCommonBank(relevantSamples); if (!string.IsNullOrEmpty(commonBank)) bank.Current.Value = commonBank; - int? commonVolume = getCommonVolume(relevantControlPoints); + int? commonVolume = getCommonVolume(relevantSamples); if (commonVolume != null) volume.Current.Value = commonVolume.Value; @@ -120,9 +131,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline updateBankFor(relevantObjects, val.NewValue); updateBankPlaceholderText(relevantObjects); }); - // on commit, ensure that the value is correct by sourcing it from the objects' control points again. + // on commit, ensure that the value is correct by sourcing it from the objects' samples again. // this ensures that committing empty text causes a revert to the previous value. - bank.OnCommit += (_, _) => bank.Current.Value = getCommonBank(relevantControlPoints); + bank.OnCommit += (_, _) => bank.Current.Value = getCommonBank(relevantSamples); volume.Current.BindValueChanged(val => updateVolumeFor(relevantObjects, val.NewValue)); } @@ -133,8 +144,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(volume)); } - private static string? getCommonBank(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleBank).Distinct().Count() == 1 ? relevantControlPoints.First().SampleBank : null; - private static int? getCommonVolume(SampleControlPoint[] relevantControlPoints) => relevantControlPoints.Select(point => point.SampleVolume).Distinct().Count() == 1 ? relevantControlPoints.First().SampleVolume : null; + private static string? getCommonBank(IList[] relevantSamples) => relevantSamples.Select(GetBankValue).Distinct().Count() == 1 ? GetBankValue(relevantSamples.First()) : null; + private static int? getCommonVolume(IList[] relevantSamples) => relevantSamples.Select(GetVolumeValue).Distinct().Count() == 1 ? GetVolumeValue(relevantSamples.First()) : null; private void updateBankFor(IEnumerable objects, string? newBank) { @@ -145,7 +156,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline foreach (var h in objects) { - h.SampleControlPoint.SampleBank = newBank; + for (int i = 0; i < h.Samples.Count; i++) + { + h.Samples[i] = h.Samples[i].With(newBank: newBank); + } + beatmap.Update(h); } @@ -154,7 +169,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateBankPlaceholderText(IEnumerable objects) { - string? commonBank = getCommonBank(objects.Select(h => h.SampleControlPoint).ToArray()); + string? commonBank = getCommonBank(objects.Select(h => h.Samples).ToArray()); bank.PlaceholderText = string.IsNullOrEmpty(commonBank) ? "(multiple)" : string.Empty; } @@ -167,7 +182,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline foreach (var h in objects) { - h.SampleControlPoint.SampleVolume = newVolume.Value; + for (int i = 0; i < h.Samples.Count; i++) + { + h.Samples[i] = h.Samples[i].With(newVolume: newVolume.Value); + } + beatmap.Update(h); } From d97daee96be2c10f90709cc30beceb1f369ae225 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 13:55:39 +0200 Subject: [PATCH 0579/1400] remove all non-test usage of SampleControlPoint --- .../Objects/Drawables/DrawableHoldNote.cs | 8 +------- .../Blueprints/Sliders/SliderSelectionBlueprint.cs | 10 ---------- osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs | 1 - .../Objects/Drawables/DrawableSlider.cs | 10 ++-------- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs | 7 ++++--- 7 files changed, 9 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6e1c6cf80f..372ef1e164 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -350,13 +350,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { // Note: base.LoadSamples() isn't called since the slider plays the tail's hitsounds for the time being. - if (HitObject.SampleControlPoint == null) - { - throw new InvalidOperationException($"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - } - - slidingSample.Samples = HitObject.CreateSlidingSamples().Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); + slidingSample.Samples = HitObject.CreateSlidingSamples().Cast().ToArray(); } public override void StopAllSamples() diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index e444287b73..8cf64a6a7e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -311,17 +311,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders var splitControlPoints = controlPoints.Take(index + 1).ToList(); controlPoints.RemoveRange(0, index); - // Turn the control points which were split off into a new slider. - var samplePoint = (SampleControlPoint)HitObject.SampleControlPoint.DeepClone(); - var difficultyPoint = (DifficultyControlPoint)HitObject.DifficultyControlPoint.DeepClone(); - var newSlider = new Slider { StartTime = HitObject.StartTime, Position = HitObject.Position + splitControlPoints[0].Position, NewCombo = HitObject.NewCombo, - SampleControlPoint = samplePoint, - DifficultyControlPoint = difficultyPoint, LegacyLastTickOffset = HitObject.LegacyLastTickOffset, Samples = HitObject.Samples.Select(s => s.With()).ToList(), RepeatCount = HitObject.RepeatCount, @@ -378,15 +372,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders Vector2 position = HitObject.Position + HitObject.Path.PositionAt(pathPosition); - var samplePoint = (SampleControlPoint)HitObject.SampleControlPoint.DeepClone(); - samplePoint.Time = time; - editorBeatmap.Add(new HitCircle { StartTime = time, Position = position, NewCombo = i == 0 && HitObject.NewCombo, - SampleControlPoint = samplePoint, Samples = HitObject.HeadCircle.Samples.Select(s => s.With()).ToList() }); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 6d5280e528..2a6d6ce4c3 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -362,7 +362,6 @@ namespace osu.Game.Rulesets.Osu.Edit StartTime = firstHitObject.StartTime, Position = firstHitObject.Position, NewCombo = firstHitObject.NewCombo, - SampleControlPoint = firstHitObject.SampleControlPoint, Samples = firstHitObject.Samples, }; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index a7b02596d5..664a8146e7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -133,14 +133,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { // Note: base.LoadSamples() isn't called since the slider plays the tail's hitsounds for the time being. - if (HitObject.SampleControlPoint == null) - { - throw new InvalidOperationException($"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - } - - Samples.Samples = HitObject.TailSamples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); - slidingSample.Samples = HitObject.CreateSlidingSamples().Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); + Samples.Samples = HitObject.TailSamples.Cast().ToArray(); + slidingSample.Samples = HitObject.CreateSlidingSamples().Cast().ToArray(); } public override void StopAllSamples() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index a5193f1b6e..0ceda1d4b0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.LoadSamples(); - spinningSample.Samples = HitObject.CreateSpinningSamples().Select(s => HitObject.SampleControlPoint.ApplyTo(s)).Cast().ToArray(); + spinningSample.Samples = HitObject.CreateSpinningSamples().Cast().ToArray(); spinningSample.Frequency.Value = spinning_sample_initial_frequency; } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index ed6f8a9a6a..55924c19c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Objects return new[] { - SampleControlPoint.ApplyTo(referenceSample).With("spinnerspin") + referenceSample.With("spinnerspin") }; } } diff --git a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs index 4809791af8..92f2b74568 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrumSampleTriggerSource.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Game.Audio; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; @@ -17,12 +18,12 @@ namespace osu.Game.Rulesets.Taiko.UI public void Play(HitType hitType) { - var hitObject = GetMostValidObject(); + var hitSample = GetMostValidObject()?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); - if (hitObject == null) + if (hitSample == null) return; - PlaySamples(new ISampleInfo[] { hitObject.SampleControlPoint.GetSampleInfo(hitType == HitType.Rim ? HitSampleInfo.HIT_CLAP : HitSampleInfo.HIT_NORMAL) }); + PlaySamples(new ISampleInfo[] { new HitSampleInfo(hitType == HitType.Rim ? HitSampleInfo.HIT_CLAP : HitSampleInfo.HIT_NORMAL, hitSample.Bank, volume: hitSample.Volume) }); } public override void Play() => throw new InvalidOperationException(@"Use override with HitType parameter instead"); From c6fc1806595df9be3e3cb738fae20a0efaa8839d Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 14:21:52 +0200 Subject: [PATCH 0580/1400] remove all test usages of SampleControlPoint --- .../Editor/TestSceneObjectMerging.cs | 3 +- .../Editor/TestSceneSliderSplitting.cs | 10 ++----- .../Editor/TestSceneSliderStreamConversion.cs | 3 +- .../Formats/LegacyBeatmapDecoderTest.cs | 6 ++-- .../Editing/TestSceneEditorClipboard.cs | 4 --- .../Visual/Editing/TestSceneEditorSaving.cs | 10 ------- ...estSceneHitObjectSamplePointAdjustments.cs | 29 ++++++++++++------- .../TestSceneGameplaySampleTriggerSource.cs | 6 ++-- osu.Game/Audio/HitSampleInfo.cs | 5 ++-- osu.Game/Rulesets/Objects/HitObject.cs | 1 - 10 files changed, 32 insertions(+), 45 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs index e7ac38c20e..b05c755bfd 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectMerging.cs @@ -138,8 +138,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor var mergedSlider = (Slider)EditorBeatmap.SelectedHitObjects.First(); return slider1 is not null && mergedSlider.HeadCircle.Samples.SequenceEqual(slider1.HeadCircle.Samples) && mergedSlider.TailCircle.Samples.SequenceEqual(slider1.TailCircle.Samples) - && mergedSlider.Samples.SequenceEqual(slider1.Samples) - && mergedSlider.SampleControlPoint.IsRedundant(slider1.SampleControlPoint); + && mergedSlider.Samples.SequenceEqual(slider1.Samples); }); AddAssert("slider end is at same completion for last slider", () => diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs index 6cb77c7b92..a104433ea9 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs @@ -181,10 +181,8 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { if (slider is null) return; - slider.SampleControlPoint.SampleBank = "soft"; - slider.SampleControlPoint.SampleVolume = 70; - sample = new HitSampleInfo("hitwhistle"); - slider.Samples.Add(sample); + sample = new HitSampleInfo("hitwhistle", "soft", volume: 70); + slider.Samples.Add(sample.With()); }); AddStep("select added slider", () => @@ -207,9 +205,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddAssert("sliders have hitsounds", hasHitsounds); bool hasHitsounds() => sample is not null && - EditorBeatmap.HitObjects.All(o => o.SampleControlPoint.SampleBank == "soft" && - o.SampleControlPoint.SampleVolume == 70 && - o.Samples.Contains(sample)); + EditorBeatmap.HitObjects.All(o => o.Samples.Contains(sample)); } private bool sliderCreatedFor(Slider s, double startTime, double endTime, params (Vector2 pos, PathType? pathType)[] expectedControlPoints) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index 53465d43c9..a162d9a491 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -199,8 +199,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor Precision.AlmostEquals(circle.StartTime, time, 1) && Precision.AlmostEquals(circle.Position, position, 0.01f) && circle.NewCombo == startsNewCombo - && circle.Samples.SequenceEqual(slider.HeadCircle.Samples) - && circle.SampleControlPoint.IsRedundant(slider.SampleControlPoint); + && circle.Samples.SequenceEqual(slider.HeadCircle.Samples); } private bool sliderRestored(Slider slider) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 518981980b..622a1837eb 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -480,7 +480,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("Gameplay/soft-hitnormal8", getTestableSampleInfo(hitObjects[4]).LookupNames.First()); } - static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.Samples[0]; } [Test] @@ -498,7 +498,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("Gameplay/normal-hitnormal3", getTestableSampleInfo(hitObjects[2]).LookupNames.First()); } - static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.Samples[0]; } [Test] @@ -518,7 +518,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume); } - static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); + static HitSampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.Samples[0]; } [Test] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs index d26bb6bb8a..3c98a83fa0 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs @@ -95,10 +95,6 @@ namespace osu.Game.Tests.Visual.Editing var path = slider.Path; return path.ControlPoints.Count == 2 && path.ControlPoints.SequenceEqual(addedObject.Path.ControlPoints); }); - - // see `HitObject.control_point_leniency`. - AddAssert("sample control point has correct time", () => Precision.AlmostEquals(slider.SampleControlPoint.Time, slider.GetEndTime(), 1)); - AddAssert("difficulty control point has correct time", () => slider.DifficultyControlPoint.Time == slider.StartTime); } [Test] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs index b396b382ff..64c48e74cf 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs @@ -122,19 +122,9 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("Beatmap has correct timing point", () => EditorBeatmap.ControlPointInfo.TimingPoints.Single().Time == 500); - // After placement these must be non-default as defaults are read-only. - AddAssert("Placed object has non-default control points", () => - !ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) && - !ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT)); - ReloadEditorToSameBeatmap(); AddAssert("Beatmap still has correct timing point", () => EditorBeatmap.ControlPointInfo.TimingPoints.Single().Time == 500); - - // After placement these must be non-default as defaults are read-only. - AddAssert("Placed object still has non-default control points", () => - !ReferenceEquals(EditorBeatmap.HitObjects[0].SampleControlPoint, SampleControlPoint.DEFAULT) && - !ReferenceEquals(EditorBeatmap.HitObjects[0].DifficultyControlPoint, DifficultyControlPoint.DEFAULT)); } [Test] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index e8dcc6f19b..7403cad52f 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -7,6 +7,7 @@ using System.Linq; using Humanizer; using NUnit.Framework; using osu.Framework.Testing; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; @@ -39,10 +40,9 @@ namespace osu.Game.Tests.Visual.Editing { StartTime = 0, Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2, - SampleControlPoint = new SampleControlPoint + Samples = new List { - SampleBank = "normal", - SampleVolume = 80 + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 80) } }); @@ -50,10 +50,9 @@ namespace osu.Game.Tests.Visual.Editing { StartTime = 500, Position = (OsuPlayfield.BASE_SIZE + new Vector2(100, 0)) / 2, - SampleControlPoint = new SampleControlPoint + Samples = new List { - SampleBank = "soft", - SampleVolume = 60 + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft", volume: 60) } }); }); @@ -96,7 +95,12 @@ namespace osu.Game.Tests.Visual.Editing AddStep("unify sample volume", () => { foreach (var h in EditorBeatmap.HitObjects) - h.SampleControlPoint.SampleVolume = 50; + { + for (int i = 0; i < h.Samples.Count; i++) + { + h.Samples[i] = h.Samples[i].With(newVolume: 50); + } + } }); AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); @@ -136,7 +140,12 @@ namespace osu.Game.Tests.Visual.Editing AddStep("unify sample bank", () => { foreach (var h in EditorBeatmap.HitObjects) - h.SampleControlPoint.SampleBank = "soft"; + { + for (int i = 0; i < h.Samples.Count; i++) + { + h.Samples[i] = h.Samples[i].With(newBank: "soft"); + } + } }); AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); @@ -248,7 +257,7 @@ namespace osu.Game.Tests.Visual.Editing private void hitObjectHasSampleVolume(int objectIndex, int volume) => AddAssert($"{objectIndex.ToOrdinalWords()} has volume {volume}", () => { var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); - return h.SampleControlPoint.SampleVolume == volume; + return h.Samples.All(o => o.Volume == volume); }); private void setBankViaPopover(string bank) => AddStep($"set bank {bank} via popover", () => @@ -265,7 +274,7 @@ namespace osu.Game.Tests.Visual.Editing private void hitObjectHasSampleBank(int objectIndex, string bank) => AddAssert($"{objectIndex.ToOrdinalWords()} has bank {bank}", () => { var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); - return h.SampleControlPoint.SampleBank == bank; + return h.Samples.All(o => o.Bank == bank); }); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 31133f00d9..114c554d28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -73,8 +73,7 @@ namespace osu.Game.Tests.Visual.Gameplay new HitCircle { StartTime = t += spacing, - Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }, - SampleControlPoint = new SampleControlPoint { SampleBank = "soft" }, + Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft") }, }, new HitCircle { @@ -84,8 +83,7 @@ namespace osu.Game.Tests.Visual.Gameplay { StartTime = t += spacing, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 }), - Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE) }, - SampleControlPoint = new SampleControlPoint { SampleBank = "soft" }, + Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, "soft") }, }, }); diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index efa5562cb8..e9c06152cc 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Utils; namespace osu.Game.Audio @@ -32,7 +33,7 @@ namespace osu.Game.Audio /// /// The bank to load the sample from. /// - public readonly string? Bank; + public readonly string Bank; /// /// An optional suffix to provide priority lookup. Falls back to non-suffixed . @@ -47,7 +48,7 @@ namespace osu.Game.Audio public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 0) { Name = name; - Bank = bank; + Bank = bank ?? SampleControlPoint.DEFAULT_BANK; Suffix = suffix; Volume = volume; } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index aaeffa49fc..73ecc28404 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -76,7 +76,6 @@ namespace osu.Game.Rulesets.Objects /// public virtual IList AuxiliarySamples => ImmutableList.Empty; - public SampleControlPoint SampleControlPoint = SampleControlPoint.DEFAULT; public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT; /// From 5accb05f45d81d3e7fc385cdb53053d9aa9ee2c6 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 14:28:48 +0200 Subject: [PATCH 0581/1400] fix invalidoperation exception --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 04786cc9fb..a4783046c4 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -271,7 +271,9 @@ namespace osu.Game.Beatmaps.Formats if (hitObject.Samples.Count > 0) { int volume = hitObject.Samples.Max(o => o.Volume); - int customIndex = hitObject.Samples.OfType().Max(o => o.CustomSampleBank); + int customIndex = hitObject.Samples.Any(o => o is ConvertHitObjectParser.LegacyHitSampleInfo) + ? hitObject.Samples.OfType().Max(o => o.CustomSampleBank) + : 0; yield return new LegacyBeatmapDecoder.LegacySampleControlPoint { Time = hitObject.GetEndTime(), SampleVolume = volume, CustomSampleBank = customIndex }; } From 1b4f4372d5304553768c8b83bd6d460bad5acfc0 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 14:32:12 +0200 Subject: [PATCH 0582/1400] fixed sample control point applying --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 9a1935f929..6b9e21f916 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -118,10 +118,7 @@ namespace osu.Game.Beatmaps.Formats SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT; - foreach (var hitSampleInfo in hitObject.Samples) - { - sampleControlPoint.ApplyTo(hitSampleInfo); - } + hitObject.Samples = hitObject.Samples.Select(o => sampleControlPoint.ApplyTo(o)).ToList(); if (hitObject is not IHasRepeats hasRepeats) return; @@ -130,10 +127,7 @@ namespace osu.Game.Beatmaps.Formats double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency; sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(time) : SampleControlPoint.DEFAULT; - foreach (var hitSampleInfo in hasRepeats.NodeSamples[i]) - { - sampleControlPoint.ApplyTo(hitSampleInfo); - } + hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(o => sampleControlPoint.ApplyTo(o)).ToList(); } } From 9f8d7bccbab8e011ca69288476fae517a62b1c38 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 17:34:02 +0200 Subject: [PATCH 0583/1400] fix usings --- .../Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs | 1 - osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 1 - .../Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 8cf64a6a7e..6685507ee0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Audio; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 2cf1d7a6ab..362ddccaf1 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -16,7 +16,6 @@ using JetBrains.Annotations; using osu.Game.Audio; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.Legacy; namespace osu.Game.Rulesets.Taiko.Beatmaps { diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index 7403cad52f..7a0418cfec 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -4,12 +4,12 @@ #nullable disable using System.Linq; +using System.Collections.Generic; using Humanizer; using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Audio; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets; From c44f71a7374f370831a72b3c13d0343368e6f86b Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 17:55:38 +0200 Subject: [PATCH 0584/1400] remove all regular usage of DifficultyControlPoint --- .../Edit/Blueprints/Components/EditablePath.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 15 ++++++++++++--- .../Sliders/SliderPlacementBlueprint.cs | 8 +++----- .../Beatmaps/TaikoBeatmapConverter.cs | 4 +++- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 13 +++++++++++-- ...estSceneHitObjectDifficultyPointAdjustments.cs | 5 +---- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 5 ++++- .../Rulesets/Edit/DistancedHitObjectComposer.cs | 3 ++- osu.Game/Rulesets/Objects/HitObject.cs | 2 +- .../Timeline/TimelineHitObjectBlueprint.cs | 12 ++++-------- 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs index 74d6565600..7a577f8a83 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components public void UpdateHitObjectFromPath(JuiceStream hitObject) { // The SV setting may need to be changed for the current path. - var svBindable = hitObject.DifficultyControlPoint.SliderVelocityBindable; + var svBindable = hitObject.SliderVelocityBindable; double svToVelocityFactor = hitObject.Velocity / svBindable.Value; double requiredVelocity = path.ComputeRequiredVelocity(); diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 96e2d5c4e5..f8af161ad5 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using Newtonsoft.Json; +using osu.Framework.Bindables; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -16,7 +17,7 @@ using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Catch.Objects { - public class JuiceStream : CatchHitObject, IHasPathWithRepeats + public class JuiceStream : CatchHitObject, IHasPathWithRepeats, IHasSliderVelocity { /// /// Positional distance that results in a duration of one second, before any speed adjustments. @@ -27,6 +28,14 @@ namespace osu.Game.Rulesets.Catch.Objects public int RepeatCount { get; set; } + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); + + public double SliderVelocity + { + get => SliderVelocityBindable.Value; + set => SliderVelocityBindable.Value = value; + } + [JsonIgnore] private double velocityFactor; @@ -34,10 +43,10 @@ namespace osu.Game.Rulesets.Catch.Objects private double tickDistanceFactor; [JsonIgnore] - public double Velocity => velocityFactor * DifficultyControlPoint.SliderVelocity; + public double Velocity => velocityFactor * SliderVelocity; [JsonIgnore] - public double TickDistance => tickDistanceFactor * DifficultyControlPoint.SliderVelocity; + public double TickDistance => tickDistanceFactor * SliderVelocity; /// /// The length of one span of this . diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 77393efeb3..50514865e1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -83,11 +82,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders case SliderPlacementState.Initial: BeginPlacement(); - var nearestDifficultyPoint = editorBeatmap.HitObjects - .LastOrDefault(h => h is Slider && h.GetEndTime() < HitObject.StartTime)? - .DifficultyControlPoint?.DeepClone() as DifficultyControlPoint; + double? nearestSliderVelocity = (editorBeatmap.HitObjects + .LastOrDefault(h => h is Slider && h.GetEndTime() < HitObject.StartTime) as Slider)?.SliderVelocity; - HitObject.DifficultyControlPoint = nearestDifficultyPoint ?? new DifficultyControlPoint(); + HitObject.SliderVelocity = nearestSliderVelocity ?? 1; HitObject.Position = ToLocalSpace(result.ScreenSpacePosition); // Replacing the DifficultyControlPoint above doesn't trigger any kind of invalidation. diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 362ddccaf1..05fb314342 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -64,7 +64,9 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps foreach (HitObject hitObject in original.HitObjects) { - double nextScrollSpeed = hitObject.DifficultyControlPoint.SliderVelocity; + if (hitObject is not IHasSliderVelocity hasSliderVelocity) continue; + + double nextScrollSpeed = hasSliderVelocity.SliderVelocity; EffectControlPoint currentEffectPoint = converted.ControlPointInfo.EffectPointAt(hitObject.StartTime); if (!Precision.AlmostEquals(lastScrollSpeed, nextScrollSpeed, acceptableDifference: currentEffectPoint.ScrollSpeedBindable.Precision)) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 3325eda7cf..5613bb190a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -5,6 +5,7 @@ using osu.Game.Rulesets.Objects.Types; using System.Threading; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; @@ -15,7 +16,7 @@ using osuTK; namespace osu.Game.Rulesets.Taiko.Objects { - public class DrumRoll : TaikoStrongableHitObject, IHasPath + public class DrumRoll : TaikoStrongableHitObject, IHasPath, IHasSliderVelocity { /// /// Drum roll distance that results in a duration of 1 speed-adjusted beat length. @@ -35,6 +36,14 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double Velocity { get; private set; } + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); + + public double SliderVelocity + { + get => SliderVelocityBindable.Value; + set => SliderVelocityBindable.Value = value; + } + /// /// Numer of ticks per beat length. /// @@ -52,7 +61,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_distance * difficulty.SliderMultiplier * DifficultyControlPoint.SliderVelocity; + double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; tickSpacing = timingPoint.BeatLength / TickRate; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index ab82678eb9..f34e286f50 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -61,10 +61,7 @@ namespace osu.Game.Tests.Visual.Editing new PathControlPoint(new Vector2(100, 0)) } }, - DifficultyControlPoint = new DifficultyControlPoint - { - SliderVelocity = 2 - } + SliderVelocity = 2 }); }); } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index a4783046c4..a681429d02 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -249,7 +249,10 @@ namespace osu.Game.Beatmaps.Formats yield break; foreach (var hitObject in hitObjects) - yield return hitObject.DifficultyControlPoint; + { + if (hitObject is IHasSliderVelocity hasSliderVelocity) + yield return new DifficultyControlPoint { Time = hitObject.StartTime, SliderVelocity = hasSliderVelocity.SliderVelocity }; + } } void extractDifficultyControlPoints(IEnumerable hitObjects) diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index aa47b4f424..5aa9e3c179 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -23,6 +23,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.OSD; using osu.Game.Overlays.Settings.Sections; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Screens.Edit.Components.TernaryButtons; namespace osu.Game.Rulesets.Edit @@ -239,7 +240,7 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity ? referenceObject.DifficultyControlPoint.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 + return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor); } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 73ecc28404..4822ec3919 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Objects /// public virtual IList AuxiliarySamples => ImmutableList.Empty; - public DifficultyControlPoint DifficultyControlPoint = DifficultyControlPoint.DEFAULT; + public DifficultyControlPoint DifficultyControlPoint { get; set; } = DifficultyControlPoint.DEFAULT; /// /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index c2106e0598..61a3931839 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -15,7 +15,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Framework.Utils; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; @@ -373,17 +372,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline case IHasRepeats repeatHitObject: double proposedDuration = time - hitObject.StartTime; - if (e.CurrentState.Keyboard.ShiftPressed) + if (e.CurrentState.Keyboard.ShiftPressed && hitObject is IHasSliderVelocity hasSliderVelocity) { - if (ReferenceEquals(hitObject.DifficultyControlPoint, DifficultyControlPoint.DEFAULT)) - hitObject.DifficultyControlPoint = new DifficultyControlPoint(); + double newVelocity = hasSliderVelocity.SliderVelocity * (repeatHitObject.Duration / proposedDuration); - double newVelocity = hitObject.DifficultyControlPoint.SliderVelocity * (repeatHitObject.Duration / proposedDuration); - - if (Precision.AlmostEquals(newVelocity, hitObject.DifficultyControlPoint.SliderVelocity)) + if (Precision.AlmostEquals(newVelocity, hasSliderVelocity.SliderVelocity)) return; - hitObject.DifficultyControlPoint.SliderVelocity = newVelocity; + hasSliderVelocity.SliderVelocity = newVelocity; beatmap.Update(hitObject); } else From 76df5fd3e27ddb2149182b5586ab1eff1634f7c4 Mon Sep 17 00:00:00 2001 From: sw1tchbl4d3 Date: Wed, 26 Apr 2023 18:05:47 +0200 Subject: [PATCH 0585/1400] Limit taiko playfield aspect ratio to 5:4 - 16:9 --- .../Mods/TaikoModClassic.cs | 2 +- .../UI/DrawableTaikoRuleset.cs | 8 ++++--- .../UI/TaikoPlayfieldAdjustmentContainer.cs | 22 ++++++++++++++----- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs index d0361b1c8d..cdeaafde10 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModClassic.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { var drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset; - drawableTaikoRuleset.LockPlayfieldMaxAspect.Value = false; + drawableTaikoRuleset.LockPlayfieldAspectRange.Value = false; var playfield = (TaikoPlayfield)drawableRuleset.Playfield; playfield.ClassicHitTargetPosition.Value = true; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index a08877e2dd..64d406a308 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Taiko.UI { public new BindableDouble TimeRange => base.TimeRange; - public readonly BindableBool LockPlayfieldMaxAspect = new BindableBool(true); + public readonly BindableBool LockPlayfieldAspectRange = new BindableBool(true); public new TaikoInputManager KeyBindingInputManager => (TaikoInputManager)base.KeyBindingInputManager; @@ -69,7 +69,9 @@ namespace osu.Game.Rulesets.Taiko.UI const float scroll_rate = 10; // Since the time range will depend on a positional value, it is referenced to the x480 pixel space. - float ratio = DrawHeight / 480; + // Width is used because it defines how many notes fit on the playfield. + // We clamp the ratio to the maximum aspect ratio to keep scroll speed consistent on widths lower than the default. + float ratio = Math.Max(DrawSize.X / 768f, TaikoPlayfieldAdjustmentContainer.MAXIMUM_ASPECT); TimeRange.Value = (Playfield.HitObjectContainer.DrawWidth / ratio) * scroll_rate; } @@ -92,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.UI public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new TaikoPlayfieldAdjustmentContainer { - LockPlayfieldMaxAspect = { BindTarget = LockPlayfieldMaxAspect } + LockPlayfieldAspectRange = { BindTarget = LockPlayfieldAspectRange } }; protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs index 42732d90e4..3587783104 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfieldAdjustmentContainer.cs @@ -11,9 +11,11 @@ namespace osu.Game.Rulesets.Taiko.UI public partial class TaikoPlayfieldAdjustmentContainer : PlayfieldAdjustmentContainer { private const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768; - private const float default_aspect = 16f / 9f; - public readonly IBindable LockPlayfieldMaxAspect = new BindableBool(true); + public const float MAXIMUM_ASPECT = 16f / 9f; + public const float MINIMUM_ASPECT = 5f / 4f; + + public readonly IBindable LockPlayfieldAspectRange = new BindableBool(true); protected override void Update() { @@ -26,12 +28,22 @@ namespace osu.Game.Rulesets.Taiko.UI // // As a middle-ground, the aspect ratio can still be adjusted in the downwards direction but has a maximum limit. // This is still a bit weird, because readability changes with window size, but it is what it is. - if (LockPlayfieldMaxAspect.Value && Parent.ChildSize.X / Parent.ChildSize.Y > default_aspect) - height *= Math.Clamp(Parent.ChildSize.X / Parent.ChildSize.Y, 0.4f, 4) / default_aspect; + if (LockPlayfieldAspectRange.Value) + { + float currentAspect = Parent.ChildSize.X / Parent.ChildSize.Y; + if (currentAspect > MAXIMUM_ASPECT) + height *= currentAspect / MAXIMUM_ASPECT; + else if (currentAspect < MINIMUM_ASPECT) + height *= currentAspect / MINIMUM_ASPECT; + } + + // Limit the maximum relative height of the playfield to one-third of available area to avoid it masking out on extreme resolutions. + height = Math.Min(height, 1f / 3f); Height = height; - // Position the taiko playfield exactly one playfield from the top of the screen. + // Position the taiko playfield exactly one playfield from the top of the screen, if there is enough space for it. + // Note that the relative height cannot exceed one-third - if that limit is hit, the playfield will be exactly centered. RelativePositionAxes = Axes.Y; Y = height; } From 354cd238742546522b78b74bd03238b49180551e Mon Sep 17 00:00:00 2001 From: OliBomby Date: Wed, 26 Apr 2023 18:17:02 +0200 Subject: [PATCH 0586/1400] removed all usage of hitobject's DifficultyControlPoint --- .../TestSceneJuiceStreamPlacementBlueprint.cs | 4 ++-- .../TestSceneJuiceStreamSelectionBlueprint.cs | 4 ++-- .../TestSceneObjectOrderedHitPolicy.cs | 2 +- .../TestSceneSliderFollowCircleInput.cs | 3 +-- .../TestSceneSliderInput.cs | 3 +-- .../TestSceneStartTimeOrderedHitPolicy.cs | 2 +- ...tSceneHitObjectComposerDistanceSnapping.cs | 22 ++++++------------- .../Editing/TestSceneEditorClipboard.cs | 1 - ...ceneHitObjectDifficultyPointAdjustments.cs | 8 +++---- osu.Game/Rulesets/Objects/HitObject.cs | 2 -- 10 files changed, 19 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index 18d3d29bdc..2426f8c886 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor AddAssert("end time is correct", () => Precision.AlmostEquals(lastObject.EndTime, times[1])); AddAssert("start position is correct", () => Precision.AlmostEquals(lastObject.OriginalX, positions[0])); AddAssert("end position is correct", () => Precision.AlmostEquals(lastObject.EndX, positions[1])); - AddAssert("default slider velocity", () => lastObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault); + AddAssert("default slider velocity", () => lastObject.SliderVelocityBindable.IsDefault); } [Test] @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor addPlacementSteps(times, positions); addPathCheckStep(times, positions); - AddAssert("slider velocity changed", () => !lastObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault); + AddAssert("slider velocity changed", () => !lastObject.SliderVelocityBindable.IsDefault); } [Test] diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index f25b66c360..beba5811fe 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -108,11 +108,11 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor double[] times = { 100, 300 }; float[] positions = { 200, 300 }; addBlueprintStep(times, positions); - AddAssert("default slider velocity", () => hitObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault); + AddAssert("default slider velocity", () => hitObject.SliderVelocityBindable.IsDefault); addDragStartStep(times[1], positions[1]); AddMouseMoveStep(times[1], 400); - AddAssert("slider velocity changed", () => !hitObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault); + AddAssert("slider velocity changed", () => !hitObject.SliderVelocityBindable.IsDefault); } [Test] diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs index 5d9316a21b..ee70441688 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneObjectOrderedHitPolicy.cs @@ -439,7 +439,7 @@ namespace osu.Game.Rulesets.Osu.Tests { public TestSlider() { - DifficultyControlPoint = new DifficultyControlPoint { SliderVelocity = 0.1f }; + SliderVelocity = 0.1f; DefaultsApplied += _ => { diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs index a32f0a13b8..fc2e6d1f72 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderFollowCircleInput.cs @@ -7,7 +7,6 @@ using NUnit.Framework; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Replays; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -47,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Tests { StartTime = time_slider_start, Position = new Vector2(0, 0), - DifficultyControlPoint = new DifficultyControlPoint { SliderVelocity = velocity }, + SliderVelocity = velocity, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 5f27cdc191..d83926ab9b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -8,7 +8,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Replays; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -350,7 +349,7 @@ namespace osu.Game.Rulesets.Osu.Tests { StartTime = time_slider_start, Position = new Vector2(0, 0), - DifficultyControlPoint = new DifficultyControlPoint { SliderVelocity = 0.1f }, + SliderVelocity = 0.1f, Path = new SliderPath(PathType.PerfectCurve, new[] { Vector2.Zero, diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs index 29e6fc4301..f4257a9ee7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneStartTimeOrderedHitPolicy.cs @@ -399,7 +399,7 @@ namespace osu.Game.Rulesets.Osu.Tests { public TestSlider() { - DifficultyControlPoint = new DifficultyControlPoint { SliderVelocity = 0.1f }; + SliderVelocity = 0.1f; DefaultsApplied += _ => { diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index f556f6e2fe..6399507aa0 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Edit; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; @@ -74,12 +75,9 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSpeedMultiplierDoesNotChangeDistanceSnap(float multiplier) { - assertSnapDistance(100, new HitObject + assertSnapDistance(100, new Slider { - DifficultyControlPoint = new DifficultyControlPoint - { - SliderVelocity = multiplier - } + SliderVelocity = multiplier }, false); } @@ -87,12 +85,9 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSpeedMultiplierDoesChangeDistanceSnap(float multiplier) { - assertSnapDistance(100 * multiplier, new HitObject + assertSnapDistance(100 * multiplier, new Slider { - DifficultyControlPoint = new DifficultyControlPoint - { - SliderVelocity = multiplier - } + SliderVelocity = multiplier }, true); } @@ -114,12 +109,9 @@ namespace osu.Game.Tests.Editing const float base_distance = 100; const float slider_velocity = 1.2f; - var referenceObject = new HitObject + var referenceObject = new Slider { - DifficultyControlPoint = new DifficultyControlPoint - { - SliderVelocity = slider_velocity - } + SliderVelocity = slider_velocity }; assertSnapDistance(base_distance * slider_velocity, referenceObject, true); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs index 3c98a83fa0..c4c05278b5 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorClipboard.cs @@ -6,7 +6,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Testing; -using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index f34e286f50..3b998b4219 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -8,10 +8,10 @@ using Humanizer; using NUnit.Framework; using osu.Framework.Testing; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; @@ -97,8 +97,8 @@ namespace osu.Game.Tests.Visual.Editing { AddStep("unify slider velocity", () => { - foreach (var h in EditorBeatmap.HitObjects) - h.DifficultyControlPoint.SliderVelocity = 1.5; + foreach (var h in EditorBeatmap.HitObjects.OfType()) + h.SliderVelocity = 1.5; }); AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); @@ -182,7 +182,7 @@ namespace osu.Game.Tests.Visual.Editing private void hitObjectHasVelocity(int objectIndex, double velocity) => AddAssert($"{objectIndex.ToOrdinalWords()} has velocity {velocity}", () => { var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); - return h.DifficultyControlPoint.SliderVelocity == velocity; + return h is IHasSliderVelocity hasSliderVelocity && hasSliderVelocity.SliderVelocity == velocity; }); } } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 4822ec3919..095ec1ff1b 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -76,8 +76,6 @@ namespace osu.Game.Rulesets.Objects /// public virtual IList AuxiliarySamples => ImmutableList.Empty; - public DifficultyControlPoint DifficultyControlPoint { get; set; } = DifficultyControlPoint.DEFAULT; - /// /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. /// DO NOT USE THIS UNLESS 100% SURE. From 3c6141f233d0eb829c831fea7d838f7f2da2ecbd Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 27 Apr 2023 17:08:29 +0300 Subject: [PATCH 0587/1400] Add `ModSearch` --- osu.Game/Overlays/Mods/ModSearch.cs | 8 ++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Overlays/Mods/ModSearch.cs diff --git a/osu.Game/Overlays/Mods/ModSearch.cs b/osu.Game/Overlays/Mods/ModSearch.cs new file mode 100644 index 0000000000..c96be4d817 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModSearch.cs @@ -0,0 +1,8 @@ +// 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.Overlays.Mods; + +public partial class ModSearch +{ +} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 16602db4be..edf16c09fb 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -188,8 +188,8 @@ namespace osu.Game.Overlays.Mods { MainAreaContent.Add(new Container { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, AutoSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Margin = new MarginPadding { Horizontal = 100 }, @@ -197,7 +197,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.Centre, Origin = Anchor.Centre - }, + } }); } From b795e8ac5a25eac8619bee8fbfe510d2edd91573 Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 27 Apr 2023 17:26:35 +0300 Subject: [PATCH 0588/1400] Use `ModSearch` in `ModeSelectOverlay` --- osu.Game/Overlays/Mods/ModSearch.cs | 4 +++- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSearch.cs b/osu.Game/Overlays/Mods/ModSearch.cs index c96be4d817..0a82d967af 100644 --- a/osu.Game/Overlays/Mods/ModSearch.cs +++ b/osu.Game/Overlays/Mods/ModSearch.cs @@ -1,8 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics.Containers; + namespace osu.Game.Overlays.Mods; -public partial class ModSearch +public partial class ModSearch : Container { } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index edf16c09fb..31f2c87100 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -110,6 +110,8 @@ namespace osu.Game.Overlays.Mods private DifficultyMultiplierDisplay? multiplierDisplay; + private ModSearch? modSearch; + protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -201,6 +203,16 @@ namespace osu.Game.Overlays.Mods }); } + MainAreaContent.Add(new Container + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.X, + Height = ModsEffectDisplay.HEIGHT, + Margin = new MarginPadding { Horizontal = 100 }, + Child = modSearch = new ModSearch() + }); + FooterContent.Child = footerButtonFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, From f5c652325a55402d71dfb3182dea9769906f5d1b Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Thu, 27 Apr 2023 23:44:18 +0300 Subject: [PATCH 0589/1400] Create UpdateableCountryText.cs --- .../Users/Drawables/UpdateableCountryText.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 osu.Game/Users/Drawables/UpdateableCountryText.cs diff --git a/osu.Game/Users/Drawables/UpdateableCountryText.cs b/osu.Game/Users/Drawables/UpdateableCountryText.cs new file mode 100644 index 0000000000..60174505a5 --- /dev/null +++ b/osu.Game/Users/Drawables/UpdateableCountryText.cs @@ -0,0 +1,67 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Input.Events; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osu.Framework.Extensions; + +namespace osu.Game.Users.Drawables +{ + public partial class UpdateableCountryText : ModelBackedDrawable + { + public CountryCode CountryCode + { + get => Model; + set => Model = value; + } + + public bool ShowPlaceholderOnUnknown = true; + + public Action? Action; + + protected override Drawable? CreateDrawable(CountryCode countryCode) + { + if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown) + return null; + + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), + Margin = new MarginPadding { Left = 5 }, + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Text = countryCode.GetDescription(), + }, + new HoverClickSounds() + } + }; + } + + [Resolved] + private RankingsOverlay? rankingsOverlay { get; set; } + + public UpdateableCountryText(CountryCode countryCode = CountryCode.Unknown) + { + CountryCode = countryCode; + } + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + rankingsOverlay?.ShowCountry(CountryCode); + return true; + } + } + +} \ No newline at end of file From b13201fb792801e87b5a9148abd2a9ec6a011976 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 01:14:42 +0300 Subject: [PATCH 0590/1400] UpdateableCountryText rewrite --- .../Users/Drawables/UpdateableCountryText.cs | 55 ++++++------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/osu.Game/Users/Drawables/UpdateableCountryText.cs b/osu.Game/Users/Drawables/UpdateableCountryText.cs index 60174505a5..fd749da707 100644 --- a/osu.Game/Users/Drawables/UpdateableCountryText.cs +++ b/osu.Game/Users/Drawables/UpdateableCountryText.cs @@ -7,6 +7,7 @@ using osu.Framework.Input.Events; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; @@ -14,53 +15,31 @@ using osu.Framework.Extensions; namespace osu.Game.Users.Drawables { - public partial class UpdateableCountryText : ModelBackedDrawable + public partial class UpdateableCountryText : OsuHoverContainer { - public CountryCode CountryCode - { - get => Model; - set => Model = value; - } public bool ShowPlaceholderOnUnknown = true; - public Action? Action; - - protected override Drawable? CreateDrawable(CountryCode countryCode) - { - if (countryCode == CountryCode.Unknown && !ShowPlaceholderOnUnknown) - return null; - - return new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), - Margin = new MarginPadding { Left = 5 }, - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Text = countryCode.GetDescription(), - }, - new HoverClickSounds() - } - }; - } - [Resolved] private RankingsOverlay? rankingsOverlay { get; set; } - - public UpdateableCountryText(CountryCode countryCode = CountryCode.Unknown) + public UpdateableCountryText() { - CountryCode = countryCode; + AutoSizeAxes = Axes.Both; } - protected override bool OnClick(ClickEvent e) + + // [BackgroundDependencyLoader] + public void load(CountryCode countryCode) { - Action?.Invoke(); - rankingsOverlay?.ShowCountry(CountryCode); - return true; + Action = () => + { + rankingsOverlay?.ShowCountry(countryCode); + }; + + Child = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), + Text = countryCode.GetDescription(), + }; } } From e9843f20665a00da524cc240a1ea307d00d548d2 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 01:16:50 +0300 Subject: [PATCH 0591/1400] replace country text object --- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index d04329430b..811628c3c1 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Header private ExternalLinkButton openUserExternally = null!; private OsuSpriteText titleText = null!; private UpdateableFlag userFlag = null!; - private OsuSpriteText userCountryText = null!; + private UpdateableCountryText userCountryText = null!; private GroupBadgeFlow groupBadgeFlow = null!; private ToggleCoverButton coverToggle = null!; @@ -156,9 +156,8 @@ namespace osu.Game.Overlays.Profile.Header Size = new Vector2(28, 20), ShowPlaceholderOnUnknown = false, }, - userCountryText = new OsuSpriteText + userCountryText = new UpdateableCountryText { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), Margin = new MarginPadding { Left = 5 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, @@ -201,7 +200,7 @@ namespace osu.Game.Overlays.Profile.Header usernameText.Text = user?.Username ?? string.Empty; openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}"; userFlag.CountryCode = user?.CountryCode ?? default; - userCountryText.Text = (user?.CountryCode ?? default).GetDescription(); + userCountryText.load(user?.CountryCode ?? default); supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = Color4Extensions.FromHex(user?.Colour ?? "fff"); From 092377fdaa234738a79eeb409cea0e5722c154a4 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 01:47:14 +0300 Subject: [PATCH 0592/1400] moving UpdateableCountryText --- .../Profile/Header/TopHeaderContainer.cs | 41 +++++++++++++++++ .../Users/Drawables/UpdateableCountryText.cs | 46 ------------------- 2 files changed, 41 insertions(+), 46 deletions(-) delete mode 100644 osu.Game/Users/Drawables/UpdateableCountryText.cs diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 811628c3c1..54c84e08b8 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -19,6 +19,20 @@ using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; + +using System; +// using osu.Framework.Allocation; +using osu.Framework.Input.Events; +// using osu.Framework.Graphics; +// using osu.Framework.Graphics.Containers; +// using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +// using osu.Game.Graphics.Sprites; +// using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; +using osu.Framework.Graphics.Sprites; +// using osu.Framework.Extensions; + namespace osu.Game.Overlays.Profile.Header { public partial class TopHeaderContainer : CompositeDrawable @@ -158,6 +172,7 @@ namespace osu.Game.Overlays.Profile.Header }, userCountryText = new UpdateableCountryText { + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), Margin = new MarginPadding { Left = 5 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, @@ -228,5 +243,31 @@ namespace osu.Game.Overlays.Profile.Header Masking = true; } } + + private partial class UpdateableCountryText : OsuHoverContainer + { + public bool ShowPlaceholderOnUnknown = true; + public FontUsage Font = default; + [Resolved] + private RankingsOverlay? rankingsOverlay { get; set; } + public UpdateableCountryText() + { + AutoSizeAxes = Axes.Both; + } + + public void load(CountryCode countryCode) + { + Action = () => + { + rankingsOverlay?.ShowCountry(countryCode); + }; + + Child = new OsuSpriteText + { + Font = Font, + Text = countryCode.GetDescription(), + }; + } + } } } diff --git a/osu.Game/Users/Drawables/UpdateableCountryText.cs b/osu.Game/Users/Drawables/UpdateableCountryText.cs deleted file mode 100644 index fd749da707..0000000000 --- a/osu.Game/Users/Drawables/UpdateableCountryText.cs +++ /dev/null @@ -1,46 +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 osu.Framework.Allocation; -using osu.Framework.Input.Events; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays; -using osu.Framework.Extensions; - -namespace osu.Game.Users.Drawables -{ - public partial class UpdateableCountryText : OsuHoverContainer - { - - public bool ShowPlaceholderOnUnknown = true; - - [Resolved] - private RankingsOverlay? rankingsOverlay { get; set; } - public UpdateableCountryText() - { - AutoSizeAxes = Axes.Both; - } - - // [BackgroundDependencyLoader] - public void load(CountryCode countryCode) - { - Action = () => - { - rankingsOverlay?.ShowCountry(countryCode); - }; - - Child = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), - Text = countryCode.GetDescription(), - }; - } - } - -} \ No newline at end of file From 4d144cd5b5fb3e787fd51b75cef459bfab56fbf4 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 02:06:13 +0300 Subject: [PATCH 0593/1400] clearing the code --- .../Profile/Header/TopHeaderContainer.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 54c84e08b8..3485037925 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -9,8 +9,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; @@ -20,19 +22,6 @@ using osu.Game.Users.Drawables; using osuTK; -using System; -// using osu.Framework.Allocation; -using osu.Framework.Input.Events; -// using osu.Framework.Graphics; -// using osu.Framework.Graphics.Containers; -// using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -// using osu.Game.Graphics.Sprites; -// using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays; -using osu.Framework.Graphics.Sprites; -// using osu.Framework.Extensions; - namespace osu.Game.Overlays.Profile.Header { public partial class TopHeaderContainer : CompositeDrawable @@ -246,10 +235,12 @@ namespace osu.Game.Overlays.Profile.Header private partial class UpdateableCountryText : OsuHoverContainer { - public bool ShowPlaceholderOnUnknown = true; + public FontUsage Font = default; + [Resolved] private RankingsOverlay? rankingsOverlay { get; set; } + public UpdateableCountryText() { AutoSizeAxes = Axes.Both; From 17730f05bcf42c6af0c8876c46ae218adf71bb32 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 05:47:05 +0300 Subject: [PATCH 0594/1400] remove UpdateableCountryText --- .../Profile/Header/TopHeaderContainer.cs | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 3485037925..01fbf137d8 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -21,7 +21,6 @@ using osu.Game.Users; using osu.Game.Users.Drawables; using osuTK; - namespace osu.Game.Overlays.Profile.Header { public partial class TopHeaderContainer : CompositeDrawable @@ -41,7 +40,6 @@ namespace osu.Game.Overlays.Profile.Header private ExternalLinkButton openUserExternally = null!; private OsuSpriteText titleText = null!; private UpdateableFlag userFlag = null!; - private UpdateableCountryText userCountryText = null!; private GroupBadgeFlow groupBadgeFlow = null!; private ToggleCoverButton coverToggle = null!; @@ -204,7 +202,6 @@ namespace osu.Game.Overlays.Profile.Header usernameText.Text = user?.Username ?? string.Empty; openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}"; userFlag.CountryCode = user?.CountryCode ?? default; - userCountryText.load(user?.CountryCode ?? default); supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = Color4Extensions.FromHex(user?.Colour ?? "fff"); @@ -232,33 +229,5 @@ namespace osu.Game.Overlays.Profile.Header Masking = true; } } - - private partial class UpdateableCountryText : OsuHoverContainer - { - - public FontUsage Font = default; - - [Resolved] - private RankingsOverlay? rankingsOverlay { get; set; } - - public UpdateableCountryText() - { - AutoSizeAxes = Axes.Both; - } - - public void load(CountryCode countryCode) - { - Action = () => - { - rankingsOverlay?.ShowCountry(countryCode); - }; - - Child = new OsuSpriteText - { - Font = Font, - Text = countryCode.GetDescription(), - }; - } - } } } From 4b0ee392f6d5bb6ec29a0c014fdc199543475e40 Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 05:48:54 +0300 Subject: [PATCH 0595/1400] add OsuHoverContainer --- .../Profile/Header/TopHeaderContainer.cs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 01fbf137d8..618e487dc3 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -33,6 +33,9 @@ namespace osu.Game.Overlays.Profile.Header [Resolved] private IAPIProvider api { get; set; } = null!; + [Resolved] + private RankingsOverlay? rankingsOverlay { get; set; } + private UserCoverBackground cover = null!; private SupporterIcon supporterTag = null!; private UpdateableAvatar avatar = null!; @@ -40,6 +43,8 @@ namespace osu.Game.Overlays.Profile.Header private ExternalLinkButton openUserExternally = null!; private OsuSpriteText titleText = null!; private UpdateableFlag userFlag = null!; + private OsuHoverContainer userCountryContainer = null!; + private OsuSpriteText userCountryText = null!; private GroupBadgeFlow groupBadgeFlow = null!; private ToggleCoverButton coverToggle = null!; @@ -157,13 +162,20 @@ namespace osu.Game.Overlays.Profile.Header Size = new Vector2(28, 20), ShowPlaceholderOnUnknown = false, }, - userCountryText = new UpdateableCountryText + userCountryContainer = new OsuHoverContainer { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), Margin = new MarginPadding { Left = 5 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - } + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + userCountryText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), + }, + }, + }, } }, } @@ -202,6 +214,8 @@ namespace osu.Game.Overlays.Profile.Header usernameText.Text = user?.Username ?? string.Empty; openUserExternally.Link = $@"{api.WebsiteRootUrl}/users/{user?.Id ?? 0}"; userFlag.CountryCode = user?.CountryCode ?? default; + userCountryText.Text = (user?.CountryCode ?? default).GetDescription(); + userCountryContainer.Action = () => rankingsOverlay?.ShowCountry(user?.CountryCode ?? default); supporterTag.SupportLevel = user?.SupportLevel ?? 0; titleText.Text = user?.Title ?? string.Empty; titleText.Colour = Color4Extensions.FromHex(user?.Colour ?? "fff"); From ae85e2a3ff94a6c43282bf7ea084baff1cc060f9 Mon Sep 17 00:00:00 2001 From: Ethan Date: Fri, 28 Apr 2023 19:51:10 +0800 Subject: [PATCH 0596/1400] Update LoginForm.cs --- osu.Game/Overlays/Login/LoginForm.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index af145c418c..5f27db90e9 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -42,10 +42,14 @@ namespace osu.Game.Overlays.Login private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) { Direction = FillDirection.Vertical; - Spacing = new Vector2(0, 5); + Spacing = new Vector2(0, SettingsSection.ITEM_SPACING); AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - + Padding = new MarginPadding + { + Top = 5, + Bottom = 24, + }; ErrorTextFlowContainer errorText; LinkFlowContainer forgottenPaswordLink; @@ -81,7 +85,11 @@ namespace osu.Game.Overlays.Login }, forgottenPaswordLink = new LinkFlowContainer { - Padding = new MarginPadding { Left = SettingsPanel.CONTENT_MARGINS }, + Padding = new MarginPadding + { + Left = SettingsPanel.CONTENT_MARGINS, + Bottom = SettingsSection.ITEM_SPACING + }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, From 6929be49b707568074899d822c4df0d3e053cc2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 28 Apr 2023 22:35:55 +0900 Subject: [PATCH 0597/1400] Change condition for exclusive fullscreen notice to only show when using the correct renderer This avoids the notice showing when running on windows, but using the newer renderers (where the underlying logic hasn't been tested properly and can result in false-positives). Supersedes https://github.com/ppy/osu-framework/pull/5759 as a more correct implementation. --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 2765d2b437..a46205d40d 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -256,7 +256,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics return; } - if (host.Window is WindowsWindow) + if (host.Renderer is IWindowsRenderer) { switch (fullscreenCapability.Value) { From f7c84030ac3c6cd1156f496540169840ed73421d Mon Sep 17 00:00:00 2001 From: OliBomby Date: Fri, 28 Apr 2023 17:22:34 +0200 Subject: [PATCH 0598/1400] remove bank default value --- osu.Game/Audio/HitSampleInfo.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index e9c06152cc..efa5562cb8 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Utils; namespace osu.Game.Audio @@ -33,7 +32,7 @@ namespace osu.Game.Audio /// /// The bank to load the sample from. /// - public readonly string Bank; + public readonly string? Bank; /// /// An optional suffix to provide priority lookup. Falls back to non-suffixed . @@ -48,7 +47,7 @@ namespace osu.Game.Audio public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 0) { Name = name; - Bank = bank ?? SampleControlPoint.DEFAULT_BANK; + Bank = bank; Suffix = suffix; Volume = volume; } From 2d6c0d2900be5779bc1ceea643458372c403daeb Mon Sep 17 00:00:00 2001 From: _ltn <46729135+rltn@users.noreply.github.com> Date: Fri, 28 Apr 2023 19:24:07 +0300 Subject: [PATCH 0599/1400] use of Child instead of Children --- .../Overlays/Profile/Header/TopHeaderContainer.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 618e487dc3..de678cb5d1 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -164,16 +163,13 @@ namespace osu.Game.Overlays.Profile.Header }, userCountryContainer = new OsuHoverContainer { - Margin = new MarginPadding { Left = 5 }, - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, - Children = new Drawable[] + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 5 }, + Child = userCountryText = new OsuSpriteText { - userCountryText = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), - }, + Font = OsuFont.GetFont(size: 14f, weight: FontWeight.Regular), }, }, } From 607a04ae7319b823da095c948be9897767ff84bd Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 28 Apr 2023 17:45:00 +0300 Subject: [PATCH 0600/1400] Fix the issue --- osu.Game/Screens/Edit/Editor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index d89392f757..b5d304a031 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -210,7 +210,10 @@ namespace osu.Game.Screens.Edit // this is a bit haphazard, but guards against setting the lease Beatmap bindable if // the editor has already been exited. if (!ValidForPush) + { + beatmapManager.Delete(loadableBeatmap.BeatmapSetInfo); return; + } } try From c5357d30ab0c545a7eb4dd652eeefcb828c1f433 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 28 Apr 2023 20:36:31 +0300 Subject: [PATCH 0601/1400] Add test --- .../Navigation/TestSceneBeatmapEditor.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs new file mode 100644 index 0000000000..67835ed0f5 --- /dev/null +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs @@ -0,0 +1,57 @@ +// 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.Linq; +using System.Threading.Tasks; +using DeepEqual.Syntax; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Screens.Edit; +using osu.Game.Screens.Menu; + +namespace osu.Game.Tests.Visual.Navigation +{ + public partial class TestSceneBeatmapEditor : OsuGameTestScene + { + [Test] + public void TestCancelNavigationToEditor() + { + BeatmapSetInfo[] beatmapSets = Array.Empty(); + + AddStep("Timestamp current beatmapsets", () => + { + Game.Realm.Run(realm => + { + beatmapSets = realm.All().Where(x => !x.DeletePending).ToArray(); + }); + }); + + AddStep("Open editor and close it while loading", () => + { + var task = Task.Run(async () => + { + await Task.Delay(100); + Game.ScreenStack.CurrentScreen.Exit(); + }); + + Game.ScreenStack.Push(new EditorLoader()); + }); + + AddUntilStep("wait for editor", () => Game.ScreenStack.CurrentScreen is MainMenu); + + BeatmapSetInfo[] currentSetInfos = Array.Empty(); + + AddStep("Get current beatmaps", () => + { + Game.Realm.Run(realm => + { + currentSetInfos = realm.All().Where(x => !x.DeletePending).ToArray(); + }); + }); + + AddAssert("dummy beatmap didn't appear", () => currentSetInfos.IsDeepEqual(beatmapSets)); + } + } +} From d9b3c97179d2f9fd5114909fcb323208ff630f22 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 28 Apr 2023 21:23:00 +0300 Subject: [PATCH 0602/1400] Fix testing --- .../Navigation/TestSceneBeatmapEditor.cs | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs index 67835ed0f5..9760fc2c97 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs @@ -1,9 +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 System; using System.Linq; -using System.Threading.Tasks; using DeepEqual.Syntax; using NUnit.Framework; using osu.Framework.Screens; @@ -18,7 +16,7 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestCancelNavigationToEditor() { - BeatmapSetInfo[] beatmapSets = Array.Empty(); + BeatmapSetInfo[]? beatmapSets = null; AddStep("Timestamp current beatmapsets", () => { @@ -28,20 +26,26 @@ namespace osu.Game.Tests.Visual.Navigation }); }); - AddStep("Open editor and close it while loading", () => + AddStep("Set current beatmap to default", () => { - var task = Task.Run(async () => - { - await Task.Delay(100); - Game.ScreenStack.CurrentScreen.Exit(); - }); + Game.Beatmap.SetDefault(); + }); + AddStep("Open editor loader", () => + { Game.ScreenStack.Push(new EditorLoader()); }); + AddUntilStep("wait for editor", () => Game.ScreenStack.CurrentScreen is EditorLoader); + + AddStep("close editor while loading", () => + { + Game.ScreenStack.CurrentScreen.Exit(); + }); + AddUntilStep("wait for editor", () => Game.ScreenStack.CurrentScreen is MainMenu); - BeatmapSetInfo[] currentSetInfos = Array.Empty(); + BeatmapSetInfo[]? currentSetInfos = null; AddStep("Get current beatmaps", () => { @@ -51,7 +55,7 @@ namespace osu.Game.Tests.Visual.Navigation }); }); - AddAssert("dummy beatmap didn't appear", () => currentSetInfos.IsDeepEqual(beatmapSets)); + AddAssert("dummy beatmap didn't appear", () => currentSetInfos.IsDeepEqual(beatmapSets) && currentSetInfos is not null); } } } From 428b5fad3c45a545820d3fec8e06e9ce05803020 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 10:34:50 +0900 Subject: [PATCH 0603/1400] Rename test scene to explicitly mention navigation testing --- ...ceneBeatmapEditor.cs => TestSceneBeatmapEditorNavigation.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Navigation/{TestSceneBeatmapEditor.cs => TestSceneBeatmapEditorNavigation.cs} (96%) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs similarity index 96% rename from osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs rename to osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 9760fc2c97..e1fba1d630 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditor.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -11,7 +11,7 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.Navigation { - public partial class TestSceneBeatmapEditor : OsuGameTestScene + public partial class TestSceneBeatmapEditorNavigation : OsuGameTestScene { [Test] public void TestCancelNavigationToEditor() From a6f01861124b3ba119c830c43178af95945864ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 10:49:25 +0900 Subject: [PATCH 0604/1400] Improve legibility and code quality of new test --- .../TestSceneBeatmapEditorNavigation.cs | 48 ++++++------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index e1fba1d630..c76758e6c6 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -16,46 +16,26 @@ namespace osu.Game.Tests.Visual.Navigation [Test] public void TestCancelNavigationToEditor() { - BeatmapSetInfo[]? beatmapSets = null; + BeatmapSetInfo[] beatmapSets = null!; - AddStep("Timestamp current beatmapsets", () => + AddStep("Fetch initial beatmaps", () => { - Game.Realm.Run(realm => - { - beatmapSets = realm.All().Where(x => !x.DeletePending).ToArray(); - }); + beatmapSets = Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); }); - AddStep("Set current beatmap to default", () => + AddStep("Set current beatmap to default", () => Game.Beatmap.SetDefault()); + + AddStep("Push editor loader", () => Game.ScreenStack.Push(new EditorLoader())); + AddUntilStep("Wait for loader current", () => Game.ScreenStack.CurrentScreen is EditorLoader); + AddStep("Close editor while loading", () => Game.ScreenStack.CurrentScreen.Exit()); + + AddUntilStep("Wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu); + + AddAssert("Check no new beatmaps were made", () => { - Game.Beatmap.SetDefault(); + var beatmapSetsAfter = Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); + return beatmapSetsAfter.SequenceEqual(beatmapSets); }); - - AddStep("Open editor loader", () => - { - Game.ScreenStack.Push(new EditorLoader()); - }); - - AddUntilStep("wait for editor", () => Game.ScreenStack.CurrentScreen is EditorLoader); - - AddStep("close editor while loading", () => - { - Game.ScreenStack.CurrentScreen.Exit(); - }); - - AddUntilStep("wait for editor", () => Game.ScreenStack.CurrentScreen is MainMenu); - - BeatmapSetInfo[]? currentSetInfos = null; - - AddStep("Get current beatmaps", () => - { - Game.Realm.Run(realm => - { - currentSetInfos = realm.All().Where(x => !x.DeletePending).ToArray(); - }); - }); - - AddAssert("dummy beatmap didn't appear", () => currentSetInfos.IsDeepEqual(beatmapSets) && currentSetInfos is not null); } } } From 32f8c674f4d751937db57082cc872bc38a1c7bed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 11:01:29 +0900 Subject: [PATCH 0605/1400] Extract beatmap retrieval method for more legibility --- .../Navigation/TestSceneBeatmapEditorNavigation.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index c76758e6c6..554da36cc4 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using DeepEqual.Syntax; using NUnit.Framework; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -18,10 +17,7 @@ namespace osu.Game.Tests.Visual.Navigation { BeatmapSetInfo[] beatmapSets = null!; - AddStep("Fetch initial beatmaps", () => - { - beatmapSets = Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); - }); + AddStep("Fetch initial beatmaps", () => beatmapSets = allBeatmapSets()); AddStep("Set current beatmap to default", () => Game.Beatmap.SetDefault()); @@ -30,12 +26,9 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("Close editor while loading", () => Game.ScreenStack.CurrentScreen.Exit()); AddUntilStep("Wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu); + AddAssert("Check no new beatmaps were made", () => allBeatmapSets().SequenceEqual(beatmapSets)); - AddAssert("Check no new beatmaps were made", () => - { - var beatmapSetsAfter = Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); - return beatmapSetsAfter.SequenceEqual(beatmapSets); - }); + BeatmapSetInfo[] allBeatmapSets() => Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); } } } From 26431006448c9d192ac5931fc1fc3cf10f76c2a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 11:05:10 +0900 Subject: [PATCH 0606/1400] Add xmldoc to new test mentioning failure rate and general purpose --- .../Visual/Navigation/TestSceneBeatmapEditorNavigation.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 554da36cc4..603573058e 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -12,6 +12,14 @@ namespace osu.Game.Tests.Visual.Navigation { public partial class TestSceneBeatmapEditorNavigation : OsuGameTestScene { + /// + /// When entering the editor, a new beatmap is created as part of the asynchronous load process. + /// This test ensures that in the case of an early exit from the editor (ie. while it's still loading) + /// doesn't leave a dangling beatmap behind. + /// + /// This may not fail 100% due to timing, but has a pretty high chance of hitting a failure so works well enough + /// as a test. + /// [Test] public void TestCancelNavigationToEditor() { From 3b0ba4b38bc886538d62e56fbbfdf7b081cf5d84 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sat, 29 Apr 2023 19:52:22 +0200 Subject: [PATCH 0607/1400] Improved logic for `ApplyStateChange` for skin editor --- .../SkinEditor/SkinEditorChangeHandler.cs | 65 ++++++++++++++++--- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index d1a1850796..151557c9e1 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.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 System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -56,20 +57,64 @@ namespace osu.Game.Overlays.SkinEditor if (deserializedContent == null) return; - SerialisedDrawableInfo[] skinnableInfo = deserializedContent.ToArray(); - Drawable[] targetComponents = firstTarget.Components.OfType().ToArray(); + SerialisedDrawableInfo[] skinnableInfos = deserializedContent.ToArray(); + ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); - if (!skinnableInfo.Select(s => s.Type).SequenceEqual(targetComponents.Select(d => d.GetType()))) + // Store indexes based on type for later lookup + + var skinnableInfoIndexes = new Dictionary>(); + var targetComponentsIndexes = new Dictionary>(); + + for (int i = 0; i < skinnableInfos.Length; i++) { - // Perform a naive full reload for now. - firstTarget.Reload(skinnableInfo); + Type lookup = skinnableInfos[i].Type; + + if (!skinnableInfoIndexes.TryGetValue(lookup, out List? infoIndexes)) + skinnableInfoIndexes.Add(lookup, infoIndexes = new List()); + + infoIndexes.Add(i); } - else - { - int i = 0; - foreach (var drawable in targetComponents) - drawable.ApplySerialisedInfo(skinnableInfo[i++]); + for (int i = 0; i < targetComponents.Length; i++) + { + Type lookup = targetComponents[i].GetType(); + + if (!targetComponentsIndexes.TryGetValue(lookup, out List? componentIndexes)) + targetComponentsIndexes.Add(lookup, componentIndexes = new List()); + + componentIndexes.Add(i); + } + + foreach ((Type lookup, List infoIndexes) in skinnableInfoIndexes) + { + if (!targetComponentsIndexes.TryGetValue(lookup, out List? componentIndexes)) + componentIndexes = new List(0); + + int j = 0; + + for (int i = 0; i < infoIndexes.Count; i++) + { + if (i >= componentIndexes.Count) + // Add new component + firstTarget.Add((ISerialisableDrawable)skinnableInfos[infoIndexes[i]].CreateInstance()); + else + // Modify existing component + ((Drawable)targetComponents[componentIndexes[j++]]).ApplySerialisedInfo(skinnableInfos[infoIndexes[i]]); + } + + // Remove extra components + for (; j < componentIndexes.Count; j++) + firstTarget.Remove(targetComponents[componentIndexes[j]], false); + } + + foreach ((Type lookup, List componentIndexes) in targetComponentsIndexes) + { + if (skinnableInfoIndexes.ContainsKey(lookup)) + continue; + + // Remove extra components that weren't removed above + for (int i = 0; i < componentIndexes.Count; i++) + firstTarget.Remove(targetComponents[componentIndexes[i]], false); } } } From 17e4b75dfd5f55756e7d67316566bbb1f195a9dc Mon Sep 17 00:00:00 2001 From: Terochi Date: Sat, 29 Apr 2023 20:54:19 +0200 Subject: [PATCH 0608/1400] Save first state when editing --- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index 2b23ce290f..f0ad92d4da 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -235,10 +235,7 @@ namespace osu.Game.Overlays.SkinEditor }, true); canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true); - SelectedComponents.BindCollectionChanged((_, _) => - { - canCopy.Value = canCut.Value = SelectedComponents.Any(); - }, true); + SelectedComponents.BindCollectionChanged((_, _) => canCopy.Value = canCut.Value = SelectedComponents.Any(), true); clipboard.Content.BindValueChanged(content => canPaste.Value = !string.IsNullOrEmpty(content.NewValue), true); @@ -345,6 +342,7 @@ namespace osu.Game.Overlays.SkinEditor changeHandler = new SkinEditorChangeHandler(skinComponentsContainer); changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); + changeHandler.SaveState(); content.Child = new SkinBlueprintContainer(skinComponentsContainer); @@ -479,12 +477,18 @@ namespace osu.Game.Overlays.SkinEditor protected void Cut() { + if (!canCut.Value) + return; + Copy(); DeleteItems(SelectedComponents.ToArray()); } protected void Copy() { + if (!canCopy.Value) + return; + clipboard.Content.Value = JsonConvert.SerializeObject(SelectedComponents.Cast().Select(s => s.CreateSerialisedInfo()).ToArray()); } @@ -500,6 +504,9 @@ namespace osu.Game.Overlays.SkinEditor protected void Paste() { + if (!canPaste.Value) + return; + changeHandler?.BeginChange(); var drawableInfo = JsonConvert.DeserializeObject(clipboard.Content.Value); From ffcc8e91b242a22a17701566ac284a62d8f057c1 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 29 Apr 2023 23:51:49 +0200 Subject: [PATCH 0609/1400] fix legacy parser incorrectly assigning sample info for sliders --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 68ca6bc506..ba5de6c14b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } if (split.Length > 10) - readCustomSampleBanks(split[10], bankInfo); + readCustomSampleBanks(split[10], bankInfo, true); // One node for each repeat + the start and end nodes int nodes = repeatCount + 2; @@ -182,7 +182,7 @@ namespace osu.Game.Rulesets.Objects.Legacy return result; } - private void readCustomSampleBanks(string str, SampleBankInfo bankInfo) + private void readCustomSampleBanks(string str, SampleBankInfo bankInfo, bool banksOnly = false) { if (string.IsNullOrEmpty(str)) return; @@ -202,6 +202,8 @@ namespace osu.Game.Rulesets.Objects.Legacy bankInfo.BankForNormal = stringBank; bankInfo.BankForAdditions = string.IsNullOrEmpty(stringAddBank) ? stringBank : stringAddBank; + if (banksOnly) return; + if (split.Length > 2) bankInfo.CustomSampleBank = Parsing.ParseInt(split[2]); From 92efd04f3138b62d49458fb296021e7101fb3105 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 29 Apr 2023 23:52:24 +0200 Subject: [PATCH 0610/1400] fix sample of drumroll ticks being bankless --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 5 ++++- .../Objects/TaikoStrongableHitObject.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 11 +++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 5613bb190a..c1a78f46b2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -3,9 +3,11 @@ #nullable disable +using System.Linq; using osu.Game.Rulesets.Objects.Types; using System.Threading; using osu.Framework.Bindables; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; @@ -90,7 +92,8 @@ namespace osu.Game.Rulesets.Taiko.Objects FirstTick = first, TickSpacing = tickSpacing, StartTime = t, - IsStrong = IsStrong + IsStrong = IsStrong, + Samples = Samples.Where(s => s.Name == HitSampleInfo.HIT_FINISH).ToList() }); first = false; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs index d4d59d5d44..0043f231d2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.Objects if (IsStrongBindable.Value != strongSamples.Any()) { if (IsStrongBindable.Value) - Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_FINISH)); + Samples.Add(GetSampleInfo(HitSampleInfo.HIT_FINISH)); else { foreach (var sample in strongSamples) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 095ec1ff1b..774ff9dc1d 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -204,6 +204,17 @@ namespace osu.Game.Rulesets.Objects return slidingSamples; } + + /// + /// Create a SampleInfo based on the sample settings of the hit normal sample in . + /// + /// The name of the sample. + /// A populated . + protected HitSampleInfo GetSampleInfo(string sampleName) + { + var hitnormalSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL); + return hitnormalSample == null ? new HitSampleInfo(sampleName) : hitnormalSample.With(newName: sampleName); + } } public static class HitObjectExtensions From a6e780a1b9c5740e74c17d9c9f098a9e30e4871f Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sat, 29 Apr 2023 23:52:30 +0200 Subject: [PATCH 0611/1400] Update CheckMutedObjectsTest.cs --- .../Editing/Checks/CheckMutedObjectsTest.cs | 104 +----------------- 1 file changed, 6 insertions(+), 98 deletions(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs b/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs index 1e1c214c30..5a3ef619d1 100644 --- a/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckMutedObjectsTest.cs @@ -37,45 +37,6 @@ namespace osu.Game.Tests.Editing.Checks cpi.Add(2000, new SampleControlPoint { SampleVolume = volume_muted }); } - [Test] - public void TestNormalControlPointVolume() - { - var hitCircle = new HitCircle - { - StartTime = 0, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - hitCircle.ApplyDefaults(cpi, new BeatmapDifficulty()); - - assertOk(new List { hitCircle }); - } - - [Test] - public void TestLowControlPointVolume() - { - var hitCircle = new HitCircle - { - StartTime = 1000, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - hitCircle.ApplyDefaults(cpi, new BeatmapDifficulty()); - - assertLowVolume(new List { hitCircle }); - } - - [Test] - public void TestMutedControlPointVolume() - { - var hitCircle = new HitCircle - { - StartTime = 2000, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - hitCircle.ApplyDefaults(cpi, new BeatmapDifficulty()); - - assertMuted(new List { hitCircle }); - } - [Test] public void TestNormalSampleVolume() { @@ -122,7 +83,7 @@ namespace osu.Game.Tests.Editing.Checks var sliderHead = new SliderHeadCircle { StartTime = 0, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } + Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: volume_regular) } }; sliderHead.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -135,7 +96,7 @@ namespace osu.Game.Tests.Editing.Checks var slider = new MockNestableHitObject(new List { sliderHead, sliderTick, }, startTime: 0, endTime: 500) { - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } + Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: volume_regular) } }; slider.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -155,13 +116,13 @@ namespace osu.Game.Tests.Editing.Checks var sliderTick = new SliderTick { StartTime = 250, - Samples = new List { new HitSampleInfo("slidertick") } + Samples = new List { new HitSampleInfo("slidertick", volume: volume_regular) } }; sliderTick.ApplyDefaults(cpi, new BeatmapDifficulty()); var slider = new MockNestableHitObject(new List { sliderHead, sliderTick, }, startTime: 0, endTime: 500) { - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } // Applies to the tail. + Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: volume_regular) } // Applies to the tail. }; slider.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -174,14 +135,14 @@ namespace osu.Game.Tests.Editing.Checks var sliderHead = new SliderHeadCircle { StartTime = 0, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } + Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: volume_regular) } }; sliderHead.ApplyDefaults(cpi, new BeatmapDifficulty()); var sliderTick = new SliderTick { StartTime = 250, - Samples = new List { new HitSampleInfo("slidertick") } + Samples = new List { new HitSampleInfo("slidertick", volume: volume_regular) } }; sliderTick.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -194,59 +155,6 @@ namespace osu.Game.Tests.Editing.Checks assertMutedPassive(new List { slider }); } - [Test] - public void TestMutedControlPointVolumeSliderHead() - { - var sliderHead = new SliderHeadCircle - { - StartTime = 2000, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - sliderHead.ApplyDefaults(cpi, new BeatmapDifficulty()); - - var sliderTick = new SliderTick - { - StartTime = 2250, - Samples = new List { new HitSampleInfo("slidertick") } - }; - sliderTick.ApplyDefaults(cpi, new BeatmapDifficulty()); - - var slider = new MockNestableHitObject(new List { sliderHead, sliderTick, }, startTime: 2000, endTime: 2500) - { - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: volume_regular) } - }; - slider.ApplyDefaults(cpi, new BeatmapDifficulty()); - - assertMuted(new List { slider }); - } - - [Test] - public void TestMutedControlPointVolumeSliderTail() - { - var sliderHead = new SliderHeadCircle - { - StartTime = 0, - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - sliderHead.ApplyDefaults(cpi, new BeatmapDifficulty()); - - var sliderTick = new SliderTick - { - StartTime = 250, - Samples = new List { new HitSampleInfo("slidertick") } - }; - sliderTick.ApplyDefaults(cpi, new BeatmapDifficulty()); - - // Ends after the 5% control point. - var slider = new MockNestableHitObject(new List { sliderHead, sliderTick, }, startTime: 0, endTime: 2500) - { - Samples = new List { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } - }; - slider.ApplyDefaults(cpi, new BeatmapDifficulty()); - - assertMutedPassive(new List { slider }); - } - private void assertOk(List hitObjects) { Assert.That(check.Run(getContext(hitObjects)), Is.Empty); From 83111223e0d9ef4ea85c16746a6d79c0e31b6bd2 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 01:08:52 +0200 Subject: [PATCH 0612/1400] fix null sample --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 91dd7754d0..96128c6981 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -76,7 +76,8 @@ namespace osu.Game.Rulesets.Edit { // Take the hitnormal sample of the last hit object var lastHitNormal = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); - HitObject.Samples.Add(lastHitNormal); + if (lastHitNormal != null) + HitObject.Samples[0] = lastHitNormal; placementHandler.BeginPlacement(HitObject); if (commitStart) From 9a9e02b110431b32bcf9281db2349ef1418c8abe Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 02:00:35 +0200 Subject: [PATCH 0613/1400] Added tests --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 89 ++++++++++++++----- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 119b753d70..71eabd776a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -2,12 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.IO; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; using osu.Framework.Testing; using osu.Game.Overlays; using osu.Game.Overlays.Settings; @@ -97,15 +100,10 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.PressButton(MouseButton.Left); }); - AddStep("Drag to bottom right", () => - { - InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); - }); + AddStep("Drag to bottom right", + () => { InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); }); - AddStep("Release button", () => - { - InputManager.ReleaseButton(MouseButton.Left); - }); + AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); AddAssert("First two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box1, box2 })); @@ -115,15 +113,9 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.PressButton(MouseButton.Left); }); - AddStep("Drag to top left", () => - { - InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); - }); + AddStep("Drag to top left", () => { InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); }); - AddStep("Release button", () => - { - InputManager.ReleaseButton(MouseButton.Left); - }); + AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); @@ -147,10 +139,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Three black boxes added", () => targetContainer.Components.OfType().Count(), () => Is.EqualTo(3)); - AddStep("Store black box blueprints", () => - { - blueprints = skinEditor.ChildrenOfType().Where(b => b.Item is BigBlackBox).ToArray(); - }); + AddStep("Store black box blueprints", () => { blueprints = skinEditor.ChildrenOfType().Where(b => b.Item is BigBlackBox).ToArray(); }); AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); @@ -182,6 +171,48 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("all boxes still selected", () => skinEditor.SelectedComponents, () => Has.Count.EqualTo(2)); } + [Test] + public void TestUndo() + { + SkinComponentsContainer firstTarget = null!; + TestSkinEditorChangeHandler changeHandler = null!; + byte[] defaultState = null!; + IEnumerable testComponents = null!; + + AddStep("Load necessary things", () => + { + firstTarget = Player.ChildrenOfType().First(); + changeHandler = new TestSkinEditorChangeHandler(firstTarget); + changeHandler.SaveState(); + defaultState = changeHandler.GetCurrentState(); + testComponents = new[] { targetContainer.Components.First(), targetContainer.Components[targetContainer.Components.Count / 2], targetContainer.Components.Last() }; + }); + + AddStep("Press undo", () => InputManager.Keys(PlatformAction.Undo)); + AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + + AddStep("Add big black boxes", () => + { + InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + InputManager.Click(MouseButton.Left); + InputManager.Click(MouseButton.Left); + }); + AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); + AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + + AddStep("Select components", () => skinEditor.SelectedComponents.AddRange(testComponents)); + AddStep("Bring to front", () => skinEditor.BringSelectionToFront()); + + AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); + AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + + AddStep("Remove components", () => testComponents.ForEach(c => firstTarget.Remove(c, false))); + + AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); + AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + } + [TestCase(false)] [TestCase(true)] public void TestBringToFront(bool alterSelectionOrder) @@ -269,5 +300,23 @@ namespace osu.Game.Tests.Visual.Gameplay } protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + private partial class TestSkinEditorChangeHandler : SkinEditorChangeHandler + { + public TestSkinEditorChangeHandler(Drawable targetScreen) + : base(targetScreen) + { + } + + public byte[] GetCurrentState() + { + using var stream = new MemoryStream(); + + WriteCurrentStateToStream(stream); + byte[] newState = stream.ToArray(); + + return newState; + } + } } } From 8ec2154965cd79939daa44adb7d0c678606bfae8 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 02:01:18 +0200 Subject: [PATCH 0614/1400] Fixed `ApplyStateChange` to happen in correct order --- .../SkinEditor/SkinEditorChangeHandler.cs | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 151557c9e1..f38f6b0911 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -62,19 +62,8 @@ namespace osu.Game.Overlays.SkinEditor // Store indexes based on type for later lookup - var skinnableInfoIndexes = new Dictionary>(); var targetComponentsIndexes = new Dictionary>(); - for (int i = 0; i < skinnableInfos.Length; i++) - { - Type lookup = skinnableInfos[i].Type; - - if (!skinnableInfoIndexes.TryGetValue(lookup, out List? infoIndexes)) - skinnableInfoIndexes.Add(lookup, infoIndexes = new List()); - - infoIndexes.Add(i); - } - for (int i = 0; i < targetComponents.Length; i++) { Type lookup = targetComponents[i].GetType(); @@ -85,35 +74,34 @@ namespace osu.Game.Overlays.SkinEditor componentIndexes.Add(i); } - foreach ((Type lookup, List infoIndexes) in skinnableInfoIndexes) + var indexCounting = new Dictionary(); + + var empty = new List(0); + + for (int i = 0; i < skinnableInfos.Length; i++) { + Type lookup = skinnableInfos[i].Type; + if (!targetComponentsIndexes.TryGetValue(lookup, out List? componentIndexes)) - componentIndexes = new List(0); + componentIndexes = empty; - int j = 0; + if (!indexCounting.ContainsKey(lookup)) + indexCounting.Add(lookup, 0); - for (int i = 0; i < infoIndexes.Count; i++) - { - if (i >= componentIndexes.Count) - // Add new component - firstTarget.Add((ISerialisableDrawable)skinnableInfos[infoIndexes[i]].CreateInstance()); - else - // Modify existing component - ((Drawable)targetComponents[componentIndexes[j++]]).ApplySerialisedInfo(skinnableInfos[infoIndexes[i]]); - } - - // Remove extra components - for (; j < componentIndexes.Count; j++) - firstTarget.Remove(targetComponents[componentIndexes[j]], false); + if (i >= componentIndexes.Count) + // Add new component + firstTarget.Add((ISerialisableDrawable)skinnableInfos[i].CreateInstance()); + else + // Modify existing component + ((Drawable)targetComponents[componentIndexes[indexCounting[lookup]++]]).ApplySerialisedInfo(skinnableInfos[i]); } foreach ((Type lookup, List componentIndexes) in targetComponentsIndexes) { - if (skinnableInfoIndexes.ContainsKey(lookup)) - continue; + indexCounting.TryGetValue(lookup, out int i); // Remove extra components that weren't removed above - for (int i = 0; i < componentIndexes.Count; i++) + for (; i < componentIndexes.Count; i++) firstTarget.Remove(targetComponents[componentIndexes[i]], false); } } From 585318400cacf70533aefef88d2880f30d4f909b Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 02:32:20 +0200 Subject: [PATCH 0615/1400] Refactor tests --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 71eabd776a..45cc329f53 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -183,15 +183,22 @@ namespace osu.Game.Tests.Visual.Gameplay { firstTarget = Player.ChildrenOfType().First(); changeHandler = new TestSkinEditorChangeHandler(firstTarget); + changeHandler.SaveState(); defaultState = changeHandler.GetCurrentState(); - testComponents = new[] { targetContainer.Components.First(), targetContainer.Components[targetContainer.Components.Count / 2], targetContainer.Components.Last() }; + + testComponents = new[] + { + targetContainer.Components.First(), + targetContainer.Components[targetContainer.Components.Count / 2], + targetContainer.Components.Last() + }; }); AddStep("Press undo", () => InputManager.Keys(PlatformAction.Undo)); AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); - AddStep("Add big black boxes", () => + AddStep("Add components", () => { InputManager.MoveMouseTo(skinEditor.ChildrenOfType().First()); InputManager.Click(MouseButton.Left); @@ -203,12 +210,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Select components", () => skinEditor.SelectedComponents.AddRange(testComponents)); AddStep("Bring to front", () => skinEditor.BringSelectionToFront()); - AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); AddStep("Remove components", () => testComponents.ForEach(c => firstTarget.Remove(c, false))); - AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); } From b39a9d816e1881bd40e471aa738fe8d455828871 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 16:05:45 +0900 Subject: [PATCH 0616/1400] Add basic structural requirements for cursor ripples --- .../Configuration/OsuRulesetConfigManager.cs | 2 ++ .../Legacy/OsuLegacySkinTransformer.cs | 5 +++++ .../UI/Cursor/CursorRippleVisualiser.cs | 21 +++++++++++++++++++ .../UI/Cursor/OsuCursorContainer.cs | 1 + .../UI/OsuSettingsSubsection.cs | 5 +++++ .../Localisation/RulesetSettingsStrings.cs | 5 +++++ 6 files changed, 39 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs index b8ad61e6dd..2056a50eda 100644 --- a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Configuration SetDefault(OsuRulesetSetting.SnakingInSliders, true); SetDefault(OsuRulesetSetting.SnakingOutSliders, true); SetDefault(OsuRulesetSetting.ShowCursorTrail, true); + SetDefault(OsuRulesetSetting.ShowCursorRipples, false); SetDefault(OsuRulesetSetting.PlayfieldBorderStyle, PlayfieldBorderStyle.None); } } @@ -31,6 +32,7 @@ namespace osu.Game.Rulesets.Osu.Configuration SnakingInSliders, SnakingOutSliders, ShowCursorTrail, + ShowCursorRipples, PlayfieldBorderStyle, } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 620540b8ef..279835747f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -100,6 +100,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return null; + case OsuSkinComponents.CursorRipple: + // TODO: resize texture to 0.5?? but that might break skins.. + if (GetTexture("cursor-ripple") != null) + return this.GetAnimation("cursor-ripple", false, false); + case OsuSkinComponents.CursorParticles: if (GetTexture("star2") != null) return new LegacyCursorParticles(); diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs new file mode 100644 index 0000000000..ef0cae7de8 --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Osu.Configuration; + +namespace osu.Game.Rulesets.Osu.UI.Cursor +{ + public partial class CursorRippleVisualiser : CompositeDrawable + { + private readonly Bindable showRipples = new Bindable(true); + + [BackgroundDependencyLoader(true)] + private void load(OsuRulesetConfigManager rulesetConfig) + { + rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorTrail, showRipples); + } + } +} diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 5d7648b073..2b541bd345 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -48,6 +48,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Children = new[] { cursorTrail = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail(), confineMode: ConfineMode.NoScaling), + new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipples), confineMode: ConfineMode.NoScaling), new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorParticles), confineMode: ConfineMode.NoScaling), } }; diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 64c4e7eef6..0e410dbf57 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -43,6 +43,11 @@ namespace osu.Game.Rulesets.Osu.UI LabelText = RulesetSettingsStrings.CursorTrail, Current = config.GetBindable(OsuRulesetSetting.ShowCursorTrail) }, + new SettingsCheckbox + { + LabelText = RulesetSettingsStrings.CursorRipples, + Current = config.GetBindable(OsuRulesetSetting.ShowCursorRipples) + }, new SettingsEnumDropdown { LabelText = RulesetSettingsStrings.PlayfieldBorderStyle, diff --git a/osu.Game/Localisation/RulesetSettingsStrings.cs b/osu.Game/Localisation/RulesetSettingsStrings.cs index 1b0df6ecf6..52e6a5eaac 100644 --- a/osu.Game/Localisation/RulesetSettingsStrings.cs +++ b/osu.Game/Localisation/RulesetSettingsStrings.cs @@ -29,6 +29,11 @@ namespace osu.Game.Localisation /// public static LocalisableString CursorTrail => new TranslatableString(getKey(@"cursor_trail"), @"Cursor trail"); + /// + /// "Cursor ripples" + /// + public static LocalisableString CursorRipples => new TranslatableString(getKey(@"cursor_ripples"), @"Cursor ripples"); + /// /// "Playfield border style" /// From a4ae9e409bf1cb5e9c2f614e2967dc3bf82210b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 16:06:08 +0900 Subject: [PATCH 0617/1400] Implement ripples (legacy and default) --- .../TestSceneGameplayCursor.cs | 13 +++++ osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 1 + .../Legacy/OsuLegacySkinTransformer.cs | 2 + .../UI/Cursor/CursorRippleVisualiser.cs | 53 +++++++++++++++++-- .../UI/Cursor/OsuCursorContainer.cs | 2 +- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs index 907422858e..c84a6ab70f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneGameplayCursor.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,6 +19,7 @@ using osu.Framework.Testing.Input; using osu.Framework.Utils; using osu.Game.Audio; using osu.Game.Configuration; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Skinning; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Screens.Play; @@ -40,6 +42,8 @@ namespace osu.Game.Rulesets.Osu.Tests private Drawable background; + private readonly Bindable ripples = new Bindable(); + public TestSceneGameplayCursor() { var ruleset = new OsuRuleset(); @@ -57,6 +61,8 @@ namespace osu.Game.Rulesets.Osu.Tests }); }); + AddToggleStep("ripples", v => ripples.Value = v); + AddSliderStep("circle size", 0f, 10f, 0f, val => { config.SetValue(OsuSetting.AutoCursorSize, true); @@ -67,6 +73,13 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("test cursor container", () => loadContent(false)); } + [BackgroundDependencyLoader] + private void load() + { + var rulesetConfig = (OsuRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull(); + rulesetConfig.BindWith(OsuRulesetSetting.ShowCursorRipples, ripples); + } + [TestCase(1, 1)] [TestCase(5, 1)] [TestCase(10, 1)] diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 8fdf3821fa..52fdfea95f 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Osu Cursor, CursorTrail, CursorParticles, + CursorRipple, SliderScorePoint, ReverseArrow, HitCircleText, diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 279835747f..bf817eda29 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -105,6 +105,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy if (GetTexture("cursor-ripple") != null) return this.GetAnimation("cursor-ripple", false, false); + return null; + case OsuSkinComponents.CursorParticles: if (GetTexture("star2") != null) return new LegacyCursorParticles(); diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index ef0cae7de8..401525efcd 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -3,19 +3,66 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Configuration; +using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Skinning; +using osuTK; namespace osu.Game.Rulesets.Osu.UI.Cursor { - public partial class CursorRippleVisualiser : CompositeDrawable + public partial class CursorRippleVisualiser : CompositeDrawable, IKeyBindingHandler { private readonly Bindable showRipples = new Bindable(true); [BackgroundDependencyLoader(true)] - private void load(OsuRulesetConfigManager rulesetConfig) + private void load(OsuRulesetConfigManager? rulesetConfig) { - rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorTrail, showRipples); + rulesetConfig?.BindWith(OsuRulesetSetting.ShowCursorRipples, showRipples); + } + + public bool OnPressed(KeyBindingPressEvent e) + { + if (showRipples.Value) + { + var ripple = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipple), _ => new DefaultCursorRipple()) + { + Blending = BlendingParameters.Additive, + Position = e.MousePosition + }; + + AddInternal(ripple); + + ripple.ScaleTo(0.05f) + .ScaleTo(0.5f, 700, Easing.Out) + .FadeTo(0.2f) + .FadeOut(700) + .Expire(); + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + + public partial class DefaultCursorRipple : CompositeDrawable + { + [BackgroundDependencyLoader] + private void load() + { + InternalChildren = new Drawable[] + { + new RingPiece(3) + { + Size = new Vector2(512), + } + }; + } } } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 2b541bd345..35fb8e67d8 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Children = new[] { cursorTrail = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail(), confineMode: ConfineMode.NoScaling), - new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipples), confineMode: ConfineMode.NoScaling), + new CursorRippleVisualiser(), new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorParticles), confineMode: ConfineMode.NoScaling), } }; From c994adfc22a3c7a25985988bd2b9f48ac47c3b58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 29 Apr 2023 22:00:17 +0900 Subject: [PATCH 0618/1400] Add pooling support for ripples --- .../UI/Cursor/CursorRippleVisualiser.cs | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index 401525efcd..e13e0d5dfb 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Pooling; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Configuration; @@ -18,6 +19,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { private readonly Bindable showRipples = new Bindable(true); + private readonly DrawablePool ripplePool = new DrawablePool(20); + [BackgroundDependencyLoader(true)] private void load(OsuRulesetConfigManager? rulesetConfig) { @@ -27,21 +30,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public bool OnPressed(KeyBindingPressEvent e) { if (showRipples.Value) - { - var ripple = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipple), _ => new DefaultCursorRipple()) - { - Blending = BlendingParameters.Additive, - Position = e.MousePosition - }; - - AddInternal(ripple); - - ripple.ScaleTo(0.05f) - .ScaleTo(0.5f, 700, Easing.Out) - .FadeTo(0.2f) - .FadeOut(700) - .Expire(); - } + AddInternal(ripplePool.Get()); return false; } @@ -50,6 +39,37 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { } + private partial class CursorRipple : PoolableDrawable + { + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Both; + Origin = Anchor.Centre; + + InternalChildren = new Drawable[] + { + new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipple), _ => new DefaultCursorRipple()) + { + Blending = BlendingParameters.Additive, + } + }; + } + + protected override void PrepareForUse() + { + base.PrepareForUse(); + + ClearTransforms(true); + + this.ScaleTo(0.05f) + .ScaleTo(0.5f, 700, Easing.Out) + .FadeTo(0.2f) + .FadeOut(700) + .Expire(); + } + } + public partial class DefaultCursorRipple : CompositeDrawable { [BackgroundDependencyLoader] From 6a62949fcd36e4ee62fdfb8de528901784733cf6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 30 Apr 2023 10:38:21 +0900 Subject: [PATCH 0619/1400] Fix positioning and rewinding support for ripples --- .../UI/Cursor/CursorRippleVisualiser.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index e13e0d5dfb..27e9d1d347 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -21,6 +21,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly DrawablePool ripplePool = new DrawablePool(20); + public CursorRippleVisualiser() + { + RelativeSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader(true)] private void load(OsuRulesetConfigManager? rulesetConfig) { @@ -30,7 +35,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public bool OnPressed(KeyBindingPressEvent e) { if (showRipples.Value) - AddInternal(ripplePool.Get()); + { + AddInternal(ripplePool.Get(r => + { + r.Position = e.MousePosition; + })); + } return false; } @@ -66,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor .ScaleTo(0.5f, 700, Easing.Out) .FadeTo(0.2f) .FadeOut(700) - .Expire(); + .Expire(true); } } @@ -75,6 +85,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load() { + AutoSizeAxes = Axes.Both; + InternalChildren = new Drawable[] { new RingPiece(3) From 72b472a75604a97d1f15ee211550bf28e2b4204c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 30 Apr 2023 11:19:03 +0900 Subject: [PATCH 0620/1400] Change default scaling and add note about legacy `cursor-ripple` scale --- .../Legacy/OsuLegacySkinTransformer.cs | 19 +++++++++++++++++-- .../UI/Cursor/CursorRippleVisualiser.cs | 8 ++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index bf817eda29..f049aa088f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -101,9 +101,24 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return null; case OsuSkinComponents.CursorRipple: - // TODO: resize texture to 0.5?? but that might break skins.. if (GetTexture("cursor-ripple") != null) - return this.GetAnimation("cursor-ripple", false, false); + { + var ripple = this.GetAnimation("cursor-ripple", false, false); + + // In stable this element was scaled down to 50% and opacity 20%, but this makes the elements WAY too big and inflexible. + // If anyone complains about these not being applied, this can be uncommented. + // + // But if no one complains I'd rather fix this in lazer. Wiki documentation doesn't mention size, + // so we might be okay. + // + // if (ripple != null) + // { + // ripple.Scale = new Vector2(0.5f); + // ripple.Alpha = 0.2f; + // } + + return ripple; + } return null; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index 27e9d1d347..465b708b5a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -73,9 +73,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor ClearTransforms(true); this.ScaleTo(0.05f) - .ScaleTo(0.5f, 700, Easing.Out) - .FadeTo(0.2f) - .FadeOut(700) + .ScaleTo(1, 700, Easing.Out) + .FadeOutFromOne(700) .Expire(true); } } @@ -91,7 +90,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { new RingPiece(3) { - Size = new Vector2(512), + Size = new Vector2(256), + Alpha = 0.2f, } }; } From 949dc1c0f96e31d0a20323d83f3fa8a98ab95592 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 12:05:55 +0200 Subject: [PATCH 0621/1400] Improved logic --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 25 +++++--- .../SkinEditor/SkinEditorChangeHandler.cs | 57 +++++++++---------- 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 45cc329f53..4a0be3bb68 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -172,7 +172,7 @@ namespace osu.Game.Tests.Visual.Gameplay } [Test] - public void TestUndo() + public void TestUndoEditHistory() { SkinComponentsContainer firstTarget = null!; TestSkinEditorChangeHandler changeHandler = null!; @@ -205,17 +205,28 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.Click(MouseButton.Left); InputManager.Click(MouseButton.Left); }); - AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); - AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + revertAndCheckUnchanged(); + + AddStep("Move components", () => + { + changeHandler.BeginChange(); + testComponents.ForEach(c => ((Drawable)c).Position += Vector2.One); + changeHandler.EndChange(); + }); + revertAndCheckUnchanged(); AddStep("Select components", () => skinEditor.SelectedComponents.AddRange(testComponents)); AddStep("Bring to front", () => skinEditor.BringSelectionToFront()); - AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); - AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + revertAndCheckUnchanged(); AddStep("Remove components", () => testComponents.ForEach(c => firstTarget.Remove(c, false))); - AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); - AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + revertAndCheckUnchanged(); + + void revertAndCheckUnchanged() + { + AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); + AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + } } [TestCase(false)] diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index f38f6b0911..6285080d36 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -60,49 +60,48 @@ namespace osu.Game.Overlays.SkinEditor SerialisedDrawableInfo[] skinnableInfos = deserializedContent.ToArray(); ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); - // Store indexes based on type for later lookup + // Store components based on type for later lookup + var typedComponents = new Dictionary>(); - var targetComponentsIndexes = new Dictionary>(); - - for (int i = 0; i < targetComponents.Length; i++) + foreach (var component in targetComponents) { - Type lookup = targetComponents[i].GetType(); + Type lookup = component.GetType(); - if (!targetComponentsIndexes.TryGetValue(lookup, out List? componentIndexes)) - targetComponentsIndexes.Add(lookup, componentIndexes = new List()); + if (!typedComponents.TryGetValue(lookup, out List? typeComponents)) + typedComponents.Add(lookup, typeComponents = new List()); - componentIndexes.Add(i); + typeComponents.Add(component); } - var indexCounting = new Dictionary(); + // Remove all components + for (int i = targetComponents.Length - 1; i >= 0; i--) + firstTarget.Remove(targetComponents[i], false); - var empty = new List(0); + // Keeps count of how many components for each type were already revived + Dictionary typedComponentCounter = typedComponents.Keys.ToDictionary(t => t, _ => 0); - for (int i = 0; i < skinnableInfos.Length; i++) + foreach (var skinnableInfo in skinnableInfos) { - Type lookup = skinnableInfos[i].Type; + Type lookup = skinnableInfo.Type; - if (!targetComponentsIndexes.TryGetValue(lookup, out List? componentIndexes)) - componentIndexes = empty; + if (!typedComponents.TryGetValue(lookup, out List? typeComponents)) + { + firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance()); + continue; + } - if (!indexCounting.ContainsKey(lookup)) - indexCounting.Add(lookup, 0); + int typeComponentsUsed = typedComponentCounter[lookup]++; - if (i >= componentIndexes.Count) - // Add new component - firstTarget.Add((ISerialisableDrawable)skinnableInfos[i].CreateInstance()); + ISerialisableDrawable component; + + if (typeComponentsUsed < typeComponents.Count) + // Re-use unused component + ((Drawable)(component = typeComponents[typeComponentsUsed])).ApplySerialisedInfo(skinnableInfo); else - // Modify existing component - ((Drawable)targetComponents[componentIndexes[indexCounting[lookup]++]]).ApplySerialisedInfo(skinnableInfos[i]); - } + // Create new one + component = (ISerialisableDrawable)skinnableInfo.CreateInstance(); - foreach ((Type lookup, List componentIndexes) in targetComponentsIndexes) - { - indexCounting.TryGetValue(lookup, out int i); - - // Remove extra components that weren't removed above - for (; i < componentIndexes.Count; i++) - firstTarget.Remove(targetComponents[componentIndexes[i]], false); + firstTarget.Add(component); } } } From 1eb2e35dffb3215b3c58987fa6b244710babc49a Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 16:03:58 +0200 Subject: [PATCH 0622/1400] fix ticks not being generated by default --- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index dd75a86f96..98e536de38 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Osu.Objects set => SliderVelocityBindable.Value = value; } - public bool GenerateTicks { get; set; } + public bool GenerateTicks { get; set; } = true; [JsonIgnore] public SliderHeadCircle HeadCircle { get; protected set; } From e7a478ce9c7e8dc20be47173233f0700fd6d88e9 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 16:04:03 +0200 Subject: [PATCH 0623/1400] Update convert-samples-expected-conversion.json --- .../Testing/Beatmaps/convert-samples-expected-conversion.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json index 6f1d45ad8c..4d298bb671 100644 --- a/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json +++ b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/convert-samples-expected-conversion.json @@ -10,7 +10,7 @@ ["Gameplay/soft-hitnormal"], ["Gameplay/drum-hitnormal"] ], - "Samples": ["Gameplay/-hitnormal"] + "Samples": ["Gameplay/normal-hitnormal"] }, { "StartTime": 1875.0, "EndTime": 2750.0, @@ -19,7 +19,7 @@ ["Gameplay/soft-hitnormal"], ["Gameplay/drum-hitnormal"] ], - "Samples": ["Gameplay/-hitnormal"] + "Samples": ["Gameplay/normal-hitnormal"] }] }, { "StartTime": 3750.0, From 8f02bd80f967db674c7d1655c3f5f72645b77c76 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 16:10:59 +0200 Subject: [PATCH 0624/1400] Addressed changes --- .../Visual/Gameplay/TestSceneSkinEditor.cs | 29 +++++++++---- osu.Game/Overlays/SkinEditor/SkinEditor.cs | 15 ++----- .../SkinEditor/SkinEditorChangeHandler.cs | 41 +++++++++++-------- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index 4a0be3bb68..f7eb42872d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -100,10 +100,15 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.PressButton(MouseButton.Left); }); - AddStep("Drag to bottom right", - () => { InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); }); + AddStep("Drag to bottom right", () => + { + InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.TopRight + new Vector2(-box3.ScreenSpaceDrawQuad.Width / 8, box3.ScreenSpaceDrawQuad.Height / 4)); + }); - AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); + AddStep("Release button", () => + { + InputManager.ReleaseButton(MouseButton.Left); + }); AddAssert("First two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box1, box2 })); @@ -113,9 +118,15 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.PressButton(MouseButton.Left); }); - AddStep("Drag to top left", () => { InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); }); + AddStep("Drag to top left", () => + { + InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre - new Vector2(box2.ScreenSpaceDrawQuad.Width / 4)); + }); - AddStep("Release button", () => { InputManager.ReleaseButton(MouseButton.Left); }); + AddStep("Release button", () => + { + InputManager.ReleaseButton(MouseButton.Left); + }); AddAssert("Last two boxes selected", () => skinEditor.SelectedComponents, () => Is.EqualTo(new[] { box2, box3 })); @@ -139,7 +150,10 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("Three black boxes added", () => targetContainer.Components.OfType().Count(), () => Is.EqualTo(3)); - AddStep("Store black box blueprints", () => { blueprints = skinEditor.ChildrenOfType().Where(b => b.Item is BigBlackBox).ToArray(); }); + AddStep("Store black box blueprints", () => + { + blueprints = skinEditor.ChildrenOfType().Where(b => b.Item is BigBlackBox).ToArray(); + }); AddAssert("Selection is black box 1", () => skinEditor.SelectedComponents.Single(), () => Is.EqualTo(blueprints[0].Item)); @@ -184,7 +198,6 @@ namespace osu.Game.Tests.Visual.Gameplay firstTarget = Player.ChildrenOfType().First(); changeHandler = new TestSkinEditorChangeHandler(firstTarget); - changeHandler.SaveState(); defaultState = changeHandler.GetCurrentState(); testComponents = new[] @@ -225,7 +238,7 @@ namespace osu.Game.Tests.Visual.Gameplay void revertAndCheckUnchanged() { AddStep("Revert changes", () => changeHandler.RestoreState(int.MinValue)); - AddAssert("Nothing changed", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); + AddAssert("Current state is same as default", () => defaultState.SequenceEqual(changeHandler.GetCurrentState())); } } diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index f0ad92d4da..2b23ce290f 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -235,7 +235,10 @@ namespace osu.Game.Overlays.SkinEditor }, true); canPaste.Current.BindValueChanged(paste => pasteMenuItem.Action.Disabled = !paste.NewValue, true); - SelectedComponents.BindCollectionChanged((_, _) => canCopy.Value = canCut.Value = SelectedComponents.Any(), true); + SelectedComponents.BindCollectionChanged((_, _) => + { + canCopy.Value = canCut.Value = SelectedComponents.Any(); + }, true); clipboard.Content.BindValueChanged(content => canPaste.Value = !string.IsNullOrEmpty(content.NewValue), true); @@ -342,7 +345,6 @@ namespace osu.Game.Overlays.SkinEditor changeHandler = new SkinEditorChangeHandler(skinComponentsContainer); changeHandler.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); - changeHandler.SaveState(); content.Child = new SkinBlueprintContainer(skinComponentsContainer); @@ -477,18 +479,12 @@ namespace osu.Game.Overlays.SkinEditor protected void Cut() { - if (!canCut.Value) - return; - Copy(); DeleteItems(SelectedComponents.ToArray()); } protected void Copy() { - if (!canCopy.Value) - return; - clipboard.Content.Value = JsonConvert.SerializeObject(SelectedComponents.Cast().Select(s => s.CreateSerialisedInfo()).ToArray()); } @@ -504,9 +500,6 @@ namespace osu.Game.Overlays.SkinEditor protected void Paste() { - if (!canPaste.Value) - return; - changeHandler?.BeginChange(); var drawableInfo = JsonConvert.DeserializeObject(clipboard.Content.Value); diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 6285080d36..8c7f7bbab7 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.SkinEditor return; components = new BindableList { BindTarget = firstTarget.Components }; - components.BindCollectionChanged((_, _) => SaveState()); + components.BindCollectionChanged((_, _) => SaveState(), true); } protected override void WriteCurrentStateToStream(MemoryStream stream) @@ -61,47 +61,52 @@ namespace osu.Game.Overlays.SkinEditor ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); // Store components based on type for later lookup - var typedComponents = new Dictionary>(); + var typedComponents = new Dictionary>(); - foreach (var component in targetComponents) + for (int i = targetComponents.Length - 1; i >= 0; i--) { + Drawable component = (Drawable)targetComponents[i]; Type lookup = component.GetType(); - if (!typedComponents.TryGetValue(lookup, out List? typeComponents)) - typedComponents.Add(lookup, typeComponents = new List()); + if (!typedComponents.TryGetValue(lookup, out Stack? typeComponents)) + typedComponents.Add(lookup, typeComponents = new Stack()); - typeComponents.Add(component); + typeComponents.Push(component); } // Remove all components for (int i = targetComponents.Length - 1; i >= 0; i--) firstTarget.Remove(targetComponents[i], false); - // Keeps count of how many components for each type were already revived - Dictionary typedComponentCounter = typedComponents.Keys.ToDictionary(t => t, _ => 0); - foreach (var skinnableInfo in skinnableInfos) { Type lookup = skinnableInfo.Type; - if (!typedComponents.TryGetValue(lookup, out List? typeComponents)) + if (!typedComponents.TryGetValue(lookup, out Stack? typeComponents)) { firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance()); continue; } - int typeComponentsUsed = typedComponentCounter[lookup]++; - - ISerialisableDrawable component; - - if (typeComponentsUsed < typeComponents.Count) + if (typeComponents.TryPop(out Drawable? component)) + { // Re-use unused component - ((Drawable)(component = typeComponents[typeComponentsUsed])).ApplySerialisedInfo(skinnableInfo); + component.ApplySerialisedInfo(skinnableInfo); + } else + { // Create new one - component = (ISerialisableDrawable)skinnableInfo.CreateInstance(); + component = skinnableInfo.CreateInstance(); + } - firstTarget.Add(component); + firstTarget.Add((ISerialisableDrawable)component); + } + + foreach ((Type _, Stack typeComponents) in typedComponents) + { + // Dispose extra components + foreach (var component in typeComponents) + component.Dispose(); } } } From fb4b681cc527c1b9430d2537e474d77f9035286c Mon Sep 17 00:00:00 2001 From: Terochi Date: Sun, 30 Apr 2023 16:36:01 +0200 Subject: [PATCH 0625/1400] Use `Queue` instead of `Stack` --- .../SkinEditor/SkinEditorChangeHandler.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 8c7f7bbab7..18ffdb0edc 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -61,17 +61,16 @@ namespace osu.Game.Overlays.SkinEditor ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); // Store components based on type for later lookup - var typedComponents = new Dictionary>(); + var typedComponents = new Dictionary>(); - for (int i = targetComponents.Length - 1; i >= 0; i--) + foreach (ISerialisableDrawable component in targetComponents) { - Drawable component = (Drawable)targetComponents[i]; Type lookup = component.GetType(); - if (!typedComponents.TryGetValue(lookup, out Stack? typeComponents)) - typedComponents.Add(lookup, typeComponents = new Stack()); + if (!typedComponents.TryGetValue(lookup, out Queue? typeComponents)) + typedComponents.Add(lookup, typeComponents = new Queue()); - typeComponents.Push(component); + typeComponents.Enqueue((Drawable)component); } // Remove all components @@ -82,13 +81,13 @@ namespace osu.Game.Overlays.SkinEditor { Type lookup = skinnableInfo.Type; - if (!typedComponents.TryGetValue(lookup, out Stack? typeComponents)) + if (!typedComponents.TryGetValue(lookup, out Queue? typeComponents)) { firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance()); continue; } - if (typeComponents.TryPop(out Drawable? component)) + if (typeComponents.TryDequeue(out Drawable? component)) { // Re-use unused component component.ApplySerialisedInfo(skinnableInfo); @@ -102,7 +101,7 @@ namespace osu.Game.Overlays.SkinEditor firstTarget.Add((ISerialisableDrawable)component); } - foreach ((Type _, Stack typeComponents) in typedComponents) + foreach ((Type _, Queue typeComponents) in typedComponents) { // Dispose extra components foreach (var component in typeComponents) From 79f3cfec91e58bc67cb3a1df1d099fc08e991938 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 16:43:26 +0200 Subject: [PATCH 0626/1400] fix 0 velocity juicestream --- .../Edit/Blueprints/Components/EditablePath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs index 7a577f8a83..75ee0546dd 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components // // The value is clamped here by the bindable min and max values. // In case the required velocity is too large, the path is not preserved. - svBindable.Value = Math.Ceiling(requiredVelocity / svToVelocityFactor); + svBindable.Value = requiredVelocity == 0 ? 1 : Math.Ceiling(requiredVelocity / svToVelocityFactor); path.ConvertToSliderPath(hitObject.Path, hitObject.LegacyConvertedY, hitObject.Velocity); From d35355970f2aa40dbddb54dee6eacac225ad5f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 30 Apr 2023 17:23:45 +0200 Subject: [PATCH 0627/1400] Add test case covering failure scenario --- .../TestSceneModSelectOverlay.cs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5ccaebd721..f99fe1d8d4 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -14,6 +14,7 @@ using osu.Framework.Localisation; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; @@ -67,6 +68,19 @@ namespace osu.Game.Tests.Visual.UserInterface } } }); + r.Add(new ModPreset + { + Name = "Half Time 0.5x", + Description = "Very slow", + Ruleset = r.Find(OsuRuleset.SHORT_NAME), + Mods = new[] + { + new OsuModHalfTime + { + SpeedChange = { Value = 0.5 } + } + } + }); }); }); } @@ -566,6 +580,28 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("5 columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 5); } + [Test] + public void TestModMultiplierUpdates() + { + createScreen(); + + AddStep("select mod preset with half time", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single(preset => preset.Preset.Value.Name == "Half Time 0.5x")); + InputManager.Click(MouseButton.Left); + }); + AddAssert("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.5)); + + // this is highly unorthodox in a test, but because the `ModSettingChangeTracker` machinery heavily leans on events and object disposal and re-creation, + // it is instrumental in the reproduction of the failure scenario that this test is supposed to cover. + AddStep("force collection", GC.Collect); + + AddStep("open customisation area", () => modSelectOverlay.CustomisationButton!.TriggerClick()); + AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType().Single() + .ChildrenOfType>().Single().TriggerClick()); + AddUntilStep("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.7)); + } + private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => modSelectOverlay.ChildrenOfType().Any() && modSelectOverlay.ChildrenOfType().All(column => column.IsLoaded && column.ItemsLoaded)); From 2e3daf0a541e14fb518292fabcc2ae8dde319e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 30 Apr 2023 17:24:07 +0200 Subject: [PATCH 0628/1400] Fix leak of `ModSettingChangeTracker` instances The `SelectedMods.BindValueChanged()` callback in `ModSelectOverlay` can in some instances run recursively. This is most heavily leaned on in scenarios where `SelectedMods` is updated by an external component. In such cases, the mod select overlay needs to replace the mod instances received externally with mod instances which it owns, so that the changes made on the overlay can propagate outwards. This in particular means that prior to this commit, it was possible to encounter the following scenario: modSettingChangeTracker?.Dispose(); updateFromExternalSelection(); // mutates SelectedMods to perform the replacement // therefore causing a recursive call modSettingChangeTracker?.Dispose(); // inner call continues modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); // outer call continues modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); This leaks one `modSettingChangeTracker` instance from the inner call, which is never disposed. To avoid this, move the disposal to the same side of the recursion that the creation happens on, changing the call pattern to: updateFromExternalSelection(); // mutates SelectedMods to perform the replacement // therefore causing a recursive call modSettingChangeTracker?.Dispose(); // inner call continues modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); modSettingChangeTracker?.Dispose(); // outer call continues modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); which, while slightly wasteful, does not cause any leaks. The solution is definitely suboptimal, but addressing this properly would entail a major rewrite of the mod instance management in the mods overlay, which is probably not the wisest move to make right now. --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d611fd3c0b..46d3620c9c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -244,12 +244,12 @@ namespace osu.Game.Overlays.Mods SelectedMods.BindValueChanged(val => { - modSettingChangeTracker?.Dispose(); - updateMultiplier(); updateFromExternalSelection(); updateCustomisation(); + modSettingChangeTracker?.Dispose(); + if (AllowCustomisation) { modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); From 139a1d7e6d6ec8f5d5c13de881f4ddfdd2542bc4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 17:46:47 +0200 Subject: [PATCH 0629/1400] fix legacy encoder writing sample info while not writing node samples --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index a681429d02..c5a8cc89be 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -476,16 +476,16 @@ namespace osu.Game.Beatmaps.Formats if (curveData != null) { - for (int i = 0; i < curveData.NodeSamples.Count; i++) + for (int i = 0; i < curveData.SpanCount() + 1; i++) { - writer.Write(FormattableString.Invariant($"{(int)toLegacyHitSoundType(curveData.NodeSamples[i])}")); - writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + writer.Write(FormattableString.Invariant($"{(i < curveData.NodeSamples.Count ? (int)toLegacyHitSoundType(curveData.NodeSamples[i]) : 0)}")); + writer.Write(i != curveData.SpanCount() ? "|" : ","); } - for (int i = 0; i < curveData.NodeSamples.Count; i++) + for (int i = 0; i < curveData.SpanCount() + 1; i++) { - writer.Write(getSampleBank(curveData.NodeSamples[i], true)); - writer.Write(i != curveData.NodeSamples.Count - 1 ? "|" : ","); + writer.Write(i < curveData.NodeSamples.Count ? getSampleBank(curveData.NodeSamples[i], true) : "0:0"); + writer.Write(i != curveData.SpanCount() ? "|" : ","); } } } From 4a0ff046ae302ceb2b2eb379055ec119eb240b4a Mon Sep 17 00:00:00 2001 From: OliBomby Date: Sun, 30 Apr 2023 19:20:42 +0200 Subject: [PATCH 0630/1400] pass new hitobject properties through beatmap converters --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 4 +++- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 6 +++++- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 7774a7da09..2c8ef9eae0 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -26,6 +26,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps var xPositionData = obj as IHasXPosition; var yPositionData = obj as IHasYPosition; var comboData = obj as IHasCombo; + var sliderVelocityData = obj as IHasSliderVelocity; switch (obj) { @@ -41,7 +42,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps NewCombo = comboData?.NewCombo ?? false, ComboOffset = comboData?.ComboOffset ?? 0, LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0, - LegacyConvertedY = yPositionData?.Y ?? CatchHitObject.DEFAULT_LEGACY_CONVERT_Y + LegacyConvertedY = yPositionData?.Y ?? CatchHitObject.DEFAULT_LEGACY_CONVERT_Y, + SliderVelocity = sliderVelocityData?.SliderVelocity ?? 1 }.Yield(); case IHasDuration endTime: diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index e9518895be..d03ee81f0d 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -30,6 +30,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { var positionData = original as IHasPosition; var comboData = original as IHasCombo; + var sliderVelocityData = original as IHasSliderVelocity; + var generateTicksData = original as IHasGenerateTicks; switch (original) { @@ -47,7 +49,9 @@ namespace osu.Game.Rulesets.Osu.Beatmaps LegacyLastTickOffset = (original as IHasLegacyLastTickOffset)?.LegacyLastTickOffset, // prior to v8, speed multipliers don't adjust for how many ticks are generated over the same distance. // this results in more (or less) ticks being generated in Date: Sun, 30 Apr 2023 19:32:24 +0200 Subject: [PATCH 0631/1400] add min and max value to SliderVelocity --- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 7 ++++++- osu.Game.Rulesets.Osu/Objects/Slider.cs | 7 ++++++- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index f8af161ad5..169e99c90c 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -28,7 +28,12 @@ namespace osu.Game.Rulesets.Catch.Objects public int RepeatCount { get; set; } - public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1) + { + Precision = 0.01, + MinValue = 0.1, + MaxValue = 10 + }; public double SliderVelocity { diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 98e536de38..4189f8ba1e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -134,7 +134,12 @@ namespace osu.Game.Rulesets.Osu.Objects /// public bool OnlyJudgeNestedObjects = true; - public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1) + { + Precision = 0.01, + MinValue = 0.1, + MaxValue = 10 + }; public double SliderVelocity { diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index c1a78f46b2..b4a12fd314 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -38,7 +38,12 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double Velocity { get; private set; } - public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1); + public BindableNumber SliderVelocityBindable { get; } = new BindableDouble(1) + { + Precision = 0.01, + MinValue = 0.1, + MaxValue = 10 + }; public double SliderVelocity { From 2a947571546bd883716e7a182a52100a68210548 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 00:49:01 +0200 Subject: [PATCH 0632/1400] Make sure the first object you place has bank and volume --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 96128c6981..bdcb334738 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Edit HitObject = hitObject; // adding the default hit sample should be the case regardless of the ruleset. - HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL)); + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK, volume: 100)); RelativeSizeAxes = Axes.Both; From b8ae508639421a89dbfe0fadb1b433bdaa46d05f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 May 2023 13:09:00 +0900 Subject: [PATCH 0633/1400] Fix incorrect starting scale for ripples --- osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index 465b708b5a..663c1f54fc 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor ClearTransforms(true); - this.ScaleTo(0.05f) + this.ScaleTo(0.1f) .ScaleTo(1, 700, Easing.Out) .FadeOutFromOne(700) .Expire(true); From 5cbfefbcb4d6177a4012527d28d53d56c13ffab0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 May 2023 13:18:04 +0900 Subject: [PATCH 0634/1400] Adjust metrics of default ripple to match stable default better --- osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index 663c1f54fc..cee5574f06 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Pooling; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.Configuration; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Skinning; using osuTK; @@ -90,8 +91,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { new RingPiece(3) { - Size = new Vector2(256), - Alpha = 0.2f, + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2), + Alpha = 0.1f, } }; } From 0a70734331f2ba319c74c9b909ddcca3f338a6a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 May 2023 14:40:48 +0900 Subject: [PATCH 0635/1400] Adjust ripple size with cursor scale (including CS) --- .../UI/Cursor/CursorRippleVisualiser.cs | 18 +++++++++++------- .../UI/Cursor/OsuCursorContainer.cs | 5 ++++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs index cee5574f06..076d97d06a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorRippleVisualiser.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor RelativeSizeAxes = Axes.Both; } + public Vector2 CursorScale { get; set; } = Vector2.One; + [BackgroundDependencyLoader(true)] private void load(OsuRulesetConfigManager? rulesetConfig) { @@ -40,6 +42,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor AddInternal(ripplePool.Get(r => { r.Position = e.MousePosition; + r.Scale = CursorScale; })); } @@ -52,18 +55,17 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private partial class CursorRipple : PoolableDrawable { + private Drawable ripple = null!; + [BackgroundDependencyLoader] private void load() { AutoSizeAxes = Axes.Both; Origin = Anchor.Centre; - InternalChildren = new Drawable[] + InternalChild = ripple = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipple), _ => new DefaultCursorRipple()) { - new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorRipple), _ => new DefaultCursorRipple()) - { - Blending = BlendingParameters.Additive, - } + Blending = BlendingParameters.Additive, }; } @@ -73,8 +75,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor ClearTransforms(true); - this.ScaleTo(0.1f) - .ScaleTo(1, 700, Easing.Out) + ripple.ScaleTo(0.1f) + .ScaleTo(1, 700, Easing.Out); + + this .FadeOutFromOne(700) .Expire(true); } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 35fb8e67d8..bf1ff872dd 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private Bindable userCursorScale; private Bindable autoCursorScale; + private readonly CursorRippleVisualiser rippleVisualiser; + public OsuCursorContainer() { InternalChild = fadeContainer = new Container @@ -48,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Children = new[] { cursorTrail = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail(), confineMode: ConfineMode.NoScaling), - new CursorRippleVisualiser(), + rippleVisualiser = new CursorRippleVisualiser(), new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorParticles), confineMode: ConfineMode.NoScaling), } }; @@ -83,6 +85,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor var newScale = new Vector2(e.NewValue); ActiveCursor.Scale = newScale; + rippleVisualiser.CursorScale = newScale; cursorTrail.Scale = newScale; }, true); From ff29189e8951945c6ef701159cc7636a75032d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 May 2023 09:33:37 +0200 Subject: [PATCH 0636/1400] Add custom `cursor-ripple` to cover skinnability in test --- .../Resources/special-skin/cursor-ripple@2x.png | Bin 0 -> 2149 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/Resources/special-skin/cursor-ripple@2x.png diff --git a/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/cursor-ripple@2x.png b/osu.Game.Rulesets.Osu.Tests/Resources/special-skin/cursor-ripple@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..258162c4864ddc469ba21697770b2fc8e1297eb5 GIT binary patch literal 2149 zcmcgsX;4#V6us|}kS8dFF-#Ic5|_5rT2^f>iv$Bgv@GHZ1A?;2AVv@s6p|2B6e7xW zlxhVxtS~NA5Em3f6%wnCsC65ug_3cob&Xbu8uEHSrtPn`e>!7ka^Ac5o_o&u^4?@q zY;?p3hfxjyFhUU-76(A#Ed`7{UJ~=_Gq6~fC6~u4$>GtPQ{e0-z%ys3EC>aJhf-of7Z^qsf-otCubWW*_atCL+XG%{l}KK3qE zJJPQx;zpf&wKAq{&gx;c4|)bNUo~(mD5|PpyZGCvv!Ow4S#G-qHl-e(c&MYlBlW|i zt(K}s227|wKV7@3M&Kw8hQ>S7shd&{f=X2*z(Bu6#$MS$(MqiyF}RJ(ZDDev_IHcKYigqyWfn0mafQXJTG&9a-P zZ+ju;oVC05gOMGuHLv2Fd!j!x5Dnm|}@n!fi!HEkh|KDMDWe-yn9#<6jxP$&`zJdSWLeZrcAtD)9n?HxowT38fCiXBKhX zNTaMwKn(T~D?S%ZOFaLT+P>07WU6jubmo~!9E0V67oBR26PEa@8YfHiobTSJam)=<3+kH)j3YO6AWl_5pq4je%{>Id;MBdWWTQYP3+T7>3@7Dgwi+~={G(>p5BOWJ`rCSF zl>EZLb|b5G(9F7Ed)Zp6ny|Y^vuE%x`{8Fsb{QGBnf0HLakllD6B&zHd_iz*U>6Y& znOo~tC6A+%fRn=z4j)1%f_#m}YzH*oM+GvV4bH&G+AS1N zj3@-8K$&>Jai21TK?KvR_@KzzR0V#bM(d$o4wcb}jV@rKJ(;Bb} O@S_Ni4m&z6Mf(Thel05i literal 0 HcmV?d00001 From cef9f73d346cdafb9e4d5c7aa3f4a5a25f82ef1a Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 12:31:27 +0200 Subject: [PATCH 0637/1400] dont assign custom sample bank and volume to hitobjects in non-mania gamemodes this makes it easier to edit hitsounds in the stable editor after export because the sample control point effects wont get overwritten by the properties of the hitobject --- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index c5a8cc89be..28f3a8d951 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -520,6 +520,14 @@ namespace osu.Game.Beatmaps.Formats string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; int volume = samples.FirstOrDefault()?.Volume ?? 100; + // We want to ignore custom sample banks and volume when not encoding to the mania game mode, + // because they cause unexpected results in the editor and are already satisfied by the control points. + if (onlineRulesetID != 3) + { + customSampleBank = "0"; + volume = 0; + } + sb.Append(':'); sb.Append(FormattableString.Invariant($"{customSampleBank}:")); sb.Append(FormattableString.Invariant($"{volume}:")); From 4d52ce769bcea52ee6e10cbc3826a4d570f48707 Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 1 May 2023 12:53:58 +0200 Subject: [PATCH 0638/1400] Revert `SaveState()` calling on initialization --- osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs | 1 + osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs index f7eb42872d..7b37b6624d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs @@ -198,6 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay firstTarget = Player.ChildrenOfType().First(); changeHandler = new TestSkinEditorChangeHandler(firstTarget); + changeHandler.SaveState(); defaultState = changeHandler.GetCurrentState(); testComponents = new[] diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 18ffdb0edc..3dddf639cc 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.SkinEditor return; components = new BindableList { BindTarget = firstTarget.Components }; - components.BindCollectionChanged((_, _) => SaveState(), true); + components.BindCollectionChanged((_, _) => SaveState()); } protected override void WriteCurrentStateToStream(MemoryStream stream) From 27cfadca16476bc9cbe069294bbc3b141c9cdcc7 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 14:14:57 +0200 Subject: [PATCH 0639/1400] add sample info to Banana and SpinnerBonusTick --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 8 +++----- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs | 6 ------ osu.Game/Rulesets/Objects/HitObject.cs | 2 +- 5 files changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index af03c9acab..e137204c32 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -22,11 +22,9 @@ namespace osu.Game.Rulesets.Catch.Objects public override Judgement CreateJudgement() => new CatchBananaJudgement(); - private static readonly List samples = new List { new BananaHitSampleInfo() }; - - public Banana() + public Banana(int volume = 100) { - Samples = samples; + Samples = new List { new BananaHitSampleInfo(volume) }; } // override any external colour changes with banananana @@ -53,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Objects public override IEnumerable LookupNames => lookup_names; - public BananaHitSampleInfo(int volume = 0) + public BananaHitSampleInfo(int volume = 100) : base(string.Empty, volume: volume) { } diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index b45f95a8e6..08febeabbf 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Catch.Objects { cancellationToken.ThrowIfCancellationRequested(); - AddNested(new Banana + AddNested(new Banana(GetSampleInfo().Volume) { StartTime = time, BananaIndex = i, diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 55924c19c9..df5898fd67 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Objects AddNested(i < SpinsRequired ? new SpinnerTick { StartTime = startTime, SpinnerDuration = Duration } - : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration }); + : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration, Samples = new[] { GetSampleInfo("spinnerbonus") } }); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 81cdf5755b..00ceccaf7b 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -3,7 +3,6 @@ #nullable disable -using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -11,11 +10,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class SpinnerBonusTick : SpinnerTick { - public SpinnerBonusTick() - { - Samples.Add(new HitSampleInfo("spinnerbonus")); - } - public override Judgement CreateJudgement() => new OsuSpinnerBonusTickJudgement(); public class OsuSpinnerBonusTickJudgement : OsuSpinnerTickJudgement diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 774ff9dc1d..a4cb976d50 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Objects /// /// The name of the sample. /// A populated . - protected HitSampleInfo GetSampleInfo(string sampleName) + protected HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) { var hitnormalSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL); return hitnormalSample == null ? new HitSampleInfo(sampleName) : hitnormalSample.With(newName: sampleName); From 8302bb1f37b5c5c18d85134fc0a5834b7c4caaa9 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 14:56:29 +0200 Subject: [PATCH 0640/1400] dont encode custom sample bank for objects without legacy samples --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 28f3a8d951..343dd7b082 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -173,9 +172,6 @@ namespace osu.Game.Beatmaps.Formats private void handleControlPoints(TextWriter writer) { - if (beatmap.ControlPointInfo.Groups.Count == 0) - return; - var legacyControlPoints = new LegacyControlPointInfo(); foreach (var point in beatmap.ControlPointInfo.AllControlPoints) legacyControlPoints.Add(point.Time, point.DeepClone()); @@ -199,6 +195,8 @@ namespace osu.Game.Beatmaps.Formats legacyControlPoints.Add(point.Time, new DifficultyControlPoint { SliderVelocity = point.ScrollSpeed }); } + int lastCustomSampleIndex = 0; + foreach (var group in legacyControlPoints.Groups) { var groupTimingPoint = group.ControlPoints.OfType().FirstOrDefault(); @@ -227,6 +225,12 @@ namespace osu.Game.Beatmaps.Formats // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty)); + // Inherit the previous sample bank if the current sample bank is not set + int customSampleBank = toLegacyCustomSampleBank(tempHitSample); + if (customSampleBank < 0) + customSampleBank = lastCustomSampleIndex; + lastCustomSampleIndex = customSampleBank; + // Convert effect flags to the legacy format LegacyEffectFlags effectFlags = LegacyEffectFlags.None; if (effectPoint.KiaiMode) @@ -236,7 +240,7 @@ namespace osu.Game.Beatmaps.Formats writer.Write(FormattableString.Invariant($"{timingPoint.TimeSignature.Numerator},")); writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},")); - writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},")); + writer.Write(FormattableString.Invariant($"{customSampleBank},")); writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); writer.Write(FormattableString.Invariant($"{(isTimingPoint ? '1' : '0')},")); writer.Write(FormattableString.Invariant($"{(int)effectFlags}")); @@ -276,7 +280,8 @@ namespace osu.Game.Beatmaps.Formats int volume = hitObject.Samples.Max(o => o.Volume); int customIndex = hitObject.Samples.Any(o => o is ConvertHitObjectParser.LegacyHitSampleInfo) ? hitObject.Samples.OfType().Max(o => o.CustomSampleBank) - : 0; + : -1; + yield return new LegacyBeatmapDecoder.LegacySampleControlPoint { Time = hitObject.GetEndTime(), SampleVolume = volume, CustomSampleBank = customIndex }; } @@ -516,7 +521,7 @@ namespace osu.Game.Beatmaps.Formats if (!banksOnly) { - string customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name))); + int customSampleBank = toLegacyCustomSampleBank(samples.FirstOrDefault(s => !string.IsNullOrEmpty(s.Name))); string sampleFilename = samples.FirstOrDefault(s => string.IsNullOrEmpty(s.Name))?.LookupNames.First() ?? string.Empty; int volume = samples.FirstOrDefault()?.Volume ?? 100; @@ -524,7 +529,7 @@ namespace osu.Game.Beatmaps.Formats // because they cause unexpected results in the editor and are already satisfied by the control points. if (onlineRulesetID != 3) { - customSampleBank = "0"; + customSampleBank = 0; volume = 0; } @@ -580,12 +585,12 @@ namespace osu.Game.Beatmaps.Formats } } - private string toLegacyCustomSampleBank(HitSampleInfo hitSampleInfo) + private int toLegacyCustomSampleBank(HitSampleInfo hitSampleInfo) { if (hitSampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy) - return legacy.CustomSampleBank.ToString(CultureInfo.InvariantCulture); + return legacy.CustomSampleBank; - return "0"; + return 0; } } } From 1dc34ee25de83fd4c2bc73151bfd3fde607519d0 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 15:48:54 +0200 Subject: [PATCH 0641/1400] fix infinite repeat count when adjusting length of 0 length slider --- .../Compose/Components/Timeline/TimelineHitObjectBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 4e5087c004..50f941a1e5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -414,7 +414,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline double lengthOfOneRepeat = repeatHitObject.Duration / (repeatHitObject.RepeatCount + 1); int proposedCount = Math.Max(0, (int)Math.Round(proposedDuration / lengthOfOneRepeat) - 1); - if (proposedCount == repeatHitObject.RepeatCount) + if (proposedCount == repeatHitObject.RepeatCount || lengthOfOneRepeat == 0) return; repeatHitObject.RepeatCount = proposedCount; From dbb2a8980b001c3ca97f31d3b7b9431ea1d30f7c Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 15:56:23 +0200 Subject: [PATCH 0642/1400] add test --- .../TestSceneTimelineHitObjectBlueprint.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs index 709d796e97..932e45b1a6 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs @@ -77,5 +77,38 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("object has non-zero duration", () => EditorBeatmap.HitObjects.OfType().Single().Duration > 0); } + + [Test] + public void TestDisallowRepeatsOnZeroDurationObjects() + { + DragArea dragArea; + + AddStep("add zero length slider", () => + { + EditorBeatmap.Clear(); + EditorBeatmap.Add(new Slider + { + Position = new Vector2(256, 256), + StartTime = 2700 + }); + }); + + AddStep("hold down drag bar", () => + { + // distinguishes between the actual drag bar and its "underlay shadow". + dragArea = this.ChildrenOfType().Single(bar => bar.HandlePositionalInput); + InputManager.MoveMouseTo(dragArea); + InputManager.PressButton(MouseButton.Left); + }); + + AddStep("try to extend drag bar", () => + { + var blueprint = this.ChildrenOfType().Single(); + InputManager.MoveMouseTo(blueprint.SelectionQuad.TopLeft + new Vector2(100, 0)); + InputManager.ReleaseButton(MouseButton.Left); + }); + + AddAssert("object has zero repeats", () => EditorBeatmap.HitObjects.OfType().Single().RepeatCount == 0); + } } } From 8c21fddb5e1d98a0158e664b44b0c7331c2338f7 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 16:53:38 +0200 Subject: [PATCH 0643/1400] remove all redundancies from encoded control points --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 72 ++++++++++++++----- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 343dd7b082..6b228a56a1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -170,6 +171,24 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Break},{b.StartTime},{b.EndTime}")); } + private struct LegacyControlPointProperties + { + internal double SliderVelocity { get; set; } + internal int TimingSignature { get; init; } + internal int SampleBank { get; init; } + internal int CustomSampleBank { get; init; } + internal int SampleVolume { get; init; } + internal LegacyEffectFlags EffectFlags { get; init; } + + internal bool IsRedundant(LegacyControlPointProperties other) => + SliderVelocity == other.SliderVelocity && + TimingSignature == other.TimingSignature && + SampleBank == other.SampleBank && + CustomSampleBank == other.CustomSampleBank && + SampleVolume == other.SampleVolume && + EffectFlags == other.EffectFlags; + } + private void handleControlPoints(TextWriter writer) { var legacyControlPoints = new LegacyControlPointInfo(); @@ -195,41 +214,44 @@ namespace osu.Game.Beatmaps.Formats legacyControlPoints.Add(point.Time, new DifficultyControlPoint { SliderVelocity = point.ScrollSpeed }); } - int lastCustomSampleIndex = 0; + LegacyControlPointProperties lastControlPointProperties = new LegacyControlPointProperties(); foreach (var group in legacyControlPoints.Groups) { var groupTimingPoint = group.ControlPoints.OfType().FirstOrDefault(); + var controlPointProperties = getLegacyControlPointProperties(group, groupTimingPoint != null); // If the group contains a timing control point, it needs to be output separately. if (groupTimingPoint != null) { writer.Write(FormattableString.Invariant($"{groupTimingPoint.Time},")); writer.Write(FormattableString.Invariant($"{groupTimingPoint.BeatLength},")); - outputControlPointAt(groupTimingPoint.Time, true); + outputControlPointAt(controlPointProperties, true); + lastControlPointProperties = controlPointProperties; + lastControlPointProperties.SliderVelocity = 1; } + if (controlPointProperties.IsRedundant(lastControlPointProperties)) + continue; + // Output any remaining effects as secondary non-timing control point. - var difficultyPoint = legacyControlPoints.DifficultyPointAt(group.Time); writer.Write(FormattableString.Invariant($"{group.Time},")); - writer.Write(FormattableString.Invariant($"{-100 / difficultyPoint.SliderVelocity},")); - outputControlPointAt(group.Time, false); + writer.Write(FormattableString.Invariant($"{-100 / controlPointProperties.SliderVelocity},")); + outputControlPointAt(controlPointProperties, false); + lastControlPointProperties = controlPointProperties; } - void outputControlPointAt(double time, bool isTimingPoint) + LegacyControlPointProperties getLegacyControlPointProperties(ControlPointGroup group, bool updateSampleBank) { + double time = group.Time; + var timingPoint = legacyControlPoints.TimingPointAt(time); + var difficultyPoint = legacyControlPoints.DifficultyPointAt(time); var samplePoint = legacyControlPoints.SamplePointAt(time); var effectPoint = legacyControlPoints.EffectPointAt(time); - var timingPoint = legacyControlPoints.TimingPointAt(time); // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty)); - - // Inherit the previous sample bank if the current sample bank is not set int customSampleBank = toLegacyCustomSampleBank(tempHitSample); - if (customSampleBank < 0) - customSampleBank = lastCustomSampleIndex; - lastCustomSampleIndex = customSampleBank; // Convert effect flags to the legacy format LegacyEffectFlags effectFlags = LegacyEffectFlags.None; @@ -238,12 +260,26 @@ namespace osu.Game.Beatmaps.Formats if (timingPoint.OmitFirstBarLine) effectFlags |= LegacyEffectFlags.OmitFirstBarLine; - writer.Write(FormattableString.Invariant($"{timingPoint.TimeSignature.Numerator},")); - writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},")); - writer.Write(FormattableString.Invariant($"{customSampleBank},")); - writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); - writer.Write(FormattableString.Invariant($"{(isTimingPoint ? '1' : '0')},")); - writer.Write(FormattableString.Invariant($"{(int)effectFlags}")); + return new LegacyControlPointProperties + { + SliderVelocity = difficultyPoint.SliderVelocity, + TimingSignature = timingPoint.TimeSignature.Numerator, + SampleBank = updateSampleBank ? (int)toLegacySampleBank(tempHitSample.Bank) : lastControlPointProperties.SampleBank, + // Inherit the previous custom sample bank if the current custom sample bank is not set + CustomSampleBank = customSampleBank >= 0 ? customSampleBank : lastControlPointProperties.CustomSampleBank, + SampleVolume = tempHitSample.Volume, + EffectFlags = effectFlags + }; + } + + void outputControlPointAt(LegacyControlPointProperties controlPoint, bool isTimingPoint) + { + writer.Write(FormattableString.Invariant($"{controlPoint.TimingSignature.ToString(CultureInfo.InvariantCulture)},")); + writer.Write(FormattableString.Invariant($"{controlPoint.SampleBank.ToString(CultureInfo.InvariantCulture)},")); + writer.Write(FormattableString.Invariant($"{controlPoint.CustomSampleBank.ToString(CultureInfo.InvariantCulture)},")); + writer.Write(FormattableString.Invariant($"{controlPoint.SampleVolume.ToString(CultureInfo.InvariantCulture)},")); + writer.Write(FormattableString.Invariant($"{(isTimingPoint ? "1" : "0")},")); + writer.Write(FormattableString.Invariant($"{((int)controlPoint.EffectFlags).ToString(CultureInfo.InvariantCulture)}")); writer.WriteLine(); } From 8ab3a87b13b7a7d0efce52d8db67b2e8af9f6a81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 May 2023 17:13:09 +0200 Subject: [PATCH 0644/1400] Add failing test case covering online ID reset on save This test scene passes at e58e1151f3c610d8019e1f1e408a1cb55d204c24 and fails at current master, due to an inadvertent regression caused by e72f103c1759e61c3afa7080f962c639265996c3. As it turns out, the online lookup flow that was causing UI thread freezes when saving beatmaps in the editor, was also responsible for resetting the online ID of locally-modified beatmaps if online lookup failed. --- ...TestSceneLocallyModifyingOnlineBeatmaps.cs | 56 +++++++++++++++++++ .../Tests/Visual/EditorSavingTestScene.cs | 27 ++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs diff --git a/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs b/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs new file mode 100644 index 0000000000..be9bbcfdd8 --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.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.Linq; +using System.Net; +using NUnit.Framework; +using osu.Framework.Extensions; +using osu.Game.Database; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Tests.Resources; + +namespace osu.Game.Tests.Visual.Editing +{ + public partial class TestSceneLocallyModifyingOnlineBeatmaps : EditorSavingTestScene + { + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + + public override void SetUpSteps() + { + CreateInitialBeatmap = () => + { + var importedSet = Game.BeatmapManager.Import(new ImportTask(TestResources.GetTestBeatmapForImport())).GetResultSafely(); + return Game.BeatmapManager.GetWorkingBeatmap(importedSet!.Value.Beatmaps.First()); + }; + + base.SetUpSteps(); + } + + [Test] + public void TestLocallyModifyingOnlineBeatmap() + { + AddAssert("editor beatmap has online ID", () => EditorBeatmap.BeatmapInfo.OnlineID, () => Is.GreaterThan(0)); + + AddStep("delete first hitobject", () => EditorBeatmap.RemoveAt(0)); + + AddStep("mock online lookup failure", () => + { + dummyAPI.HandleRequest = req => + { + if (req is GetBeatmapRequest) + { + req.TriggerFailure(new APIException("Beatmap not found", new WebException("NotFound"))); + return true; + } + + return false; + }; + }); + SaveEditor(); + + ReloadEditorToSameBeatmap(); + AddAssert("editor beatmap online ID reset", () => EditorBeatmap.BeatmapInfo.OnlineID, () => Is.EqualTo(-1)); + } + } +} diff --git a/osu.Game/Tests/Visual/EditorSavingTestScene.cs b/osu.Game/Tests/Visual/EditorSavingTestScene.cs index cd9e9e1d52..78188d7cf7 100644 --- a/osu.Game/Tests/Visual/EditorSavingTestScene.cs +++ b/osu.Game/Tests/Visual/EditorSavingTestScene.cs @@ -3,9 +3,12 @@ #nullable disable +using System; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Input; using osu.Framework.Testing; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Setup; @@ -24,18 +27,27 @@ namespace osu.Game.Tests.Visual protected EditorBeatmap EditorBeatmap => (EditorBeatmap)Editor.Dependencies.Get(typeof(EditorBeatmap)); + [CanBeNull] + protected Func CreateInitialBeatmap { get; set; } + [SetUpSteps] public override void SetUpSteps() { base.SetUpSteps(); - AddStep("set default beatmap", () => Game.Beatmap.SetDefault()); + if (CreateInitialBeatmap == null) + AddStep("set default beatmap", () => Game.Beatmap.SetDefault()); + else + { + AddStep("set test beatmap", () => Game.Beatmap.Value = CreateInitialBeatmap?.Invoke()); + } PushAndConfirm(() => new EditorLoader()); AddUntilStep("wait for editor load", () => Editor?.IsLoaded == true); - AddUntilStep("wait for metadata screen load", () => Editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); + if (CreateInitialBeatmap == null) + AddUntilStep("wait for metadata screen load", () => Editor.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); // We intentionally switch away from the metadata screen, else there is a feedback loop with the textbox handling which causes metadata changes below to get overwritten. @@ -50,6 +62,14 @@ namespace osu.Game.Tests.Visual protected void ReloadEditorToSameBeatmap() { + Guid beatmapSetGuid = Guid.Empty; + Guid beatmapGuid = Guid.Empty; + + AddStep("Store beatmap GUIDs", () => + { + beatmapSetGuid = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID; + beatmapGuid = EditorBeatmap.BeatmapInfo.ID; + }); AddStep("Exit", () => InputManager.Key(Key.Escape)); AddUntilStep("Wait for main menu", () => Game.ScreenStack.CurrentScreen is MainMenu); @@ -59,7 +79,8 @@ namespace osu.Game.Tests.Visual PushAndConfirm(() => songSelect = new PlaySongSelect()); AddUntilStep("wait for carousel load", () => songSelect.BeatmapSetsLoaded); - AddUntilStep("Wait for beatmap selected", () => !Game.Beatmap.IsDefault); + AddStep("Present same beatmap", () => Game.PresentBeatmap(Game.BeatmapManager.QueryBeatmapSet(set => set.ID == beatmapSetGuid)!.Value, beatmap => beatmap.ID == beatmapGuid)); + AddUntilStep("Wait for beatmap selected", () => Game.Beatmap.Value.BeatmapInfo.ID == beatmapGuid); AddStep("Open options", () => InputManager.Key(Key.F3)); AddStep("Enter editor", () => InputManager.Key(Key.Number5)); From f470b2c9cc379b24be498b4865f0f82f6fa41a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 May 2023 17:24:58 +0200 Subject: [PATCH 0645/1400] Always reset online info when saving local beatmap --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 6af6a25579..3f2ab9b391 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -440,6 +440,7 @@ namespace osu.Game.Beatmaps beatmapInfo.LastLocalUpdate = DateTimeOffset.Now; beatmapInfo.Status = BeatmapOnlineStatus.LocallyModified; + beatmapInfo.ResetOnlineInfo(); AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); From 1fb4c814f4446eefa768e9f2f0f73af0334c64f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 May 2023 17:31:55 +0200 Subject: [PATCH 0646/1400] Remove no longer needed API call mocking The online ID will be reset unconditionally after any local change is made to any beatmap. That behaviour no longer depends on online lookups succeeding or failing. This may change at a later date when beatmap submission is integrated into lazer - the idea is that online IDs would get re-populated on local beatmaps once they are submitted to web. --- ...TestSceneLocallyModifyingOnlineBeatmaps.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs b/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs index be9bbcfdd8..7f9a69833c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneLocallyModifyingOnlineBeatmaps.cs @@ -2,20 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using System.Net; using NUnit.Framework; using osu.Framework.Extensions; using osu.Game.Database; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Editing { public partial class TestSceneLocallyModifyingOnlineBeatmaps : EditorSavingTestScene { - private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; - public override void SetUpSteps() { CreateInitialBeatmap = () => @@ -33,20 +28,6 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("editor beatmap has online ID", () => EditorBeatmap.BeatmapInfo.OnlineID, () => Is.GreaterThan(0)); AddStep("delete first hitobject", () => EditorBeatmap.RemoveAt(0)); - - AddStep("mock online lookup failure", () => - { - dummyAPI.HandleRequest = req => - { - if (req is GetBeatmapRequest) - { - req.TriggerFailure(new APIException("Beatmap not found", new WebException("NotFound"))); - return true; - } - - return false; - }; - }); SaveEditor(); ReloadEditorToSameBeatmap(); From cf5211aec922852673c77dcedae081c89ca005e1 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Mon, 1 May 2023 19:22:52 +0200 Subject: [PATCH 0647/1400] Enable current distance snap when exactly on a hit object --- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index aa47b4f424..09c6af3820 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Edit private (HitObject before, HitObject after)? getObjectsOnEitherSideOfCurrentTime() { - HitObject lastBefore = Playfield.HitObjectContainer.AliveObjects.LastOrDefault(h => h.HitObject.StartTime <= EditorClock.CurrentTime)?.HitObject; + HitObject lastBefore = Playfield.HitObjectContainer.AliveObjects.LastOrDefault(h => h.HitObject.StartTime < EditorClock.CurrentTime)?.HitObject; if (lastBefore == null) return null; From 436ebdcfcb1d556c6bad05dea472aa9f4f41959a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 May 2023 19:06:25 +0200 Subject: [PATCH 0648/1400] Fix beatmap leaderboard test failure Because the online info reset (which includes online ID reset) was happening after encoding, `TestSceneBeatmapLeaderboard.TestLocalScoresDisplayOnBeatmapEdit()` started failing, as the hash no longer matched expectations after the first save of the map. --- osu.Game/Beatmaps/BeatmapManager.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 3f2ab9b391..ae62564b0d 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -415,6 +415,13 @@ namespace osu.Game.Beatmaps // All changes to metadata are made in the provided beatmapInfo, so this should be copied to the `IBeatmap` before encoding. beatmapContent.BeatmapInfo = beatmapInfo; + // Since now this is a locally-modified beatmap, we also set all relevant flags to indicate this. + // Importantly, the `ResetOnlineInfo()` call must happen before encoding, as online ID is encoded into the `.osu` file, + // which influences the beatmap checksums. + beatmapInfo.LastLocalUpdate = DateTimeOffset.Now; + beatmapInfo.Status = BeatmapOnlineStatus.LocallyModified; + beatmapInfo.ResetOnlineInfo(); + using (var stream = new MemoryStream()) { using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true)) @@ -438,10 +445,6 @@ namespace osu.Game.Beatmaps beatmapInfo.MD5Hash = stream.ComputeMD5Hash(); beatmapInfo.Hash = stream.ComputeSHA2Hash(); - beatmapInfo.LastLocalUpdate = DateTimeOffset.Now; - beatmapInfo.Status = BeatmapOnlineStatus.LocallyModified; - beatmapInfo.ResetOnlineInfo(); - AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo)); updateHashAndMarkDirty(setInfo); From 87db89114368d55a4029ff45109a0a9b9002c268 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 13:12:08 +0900 Subject: [PATCH 0649/1400] Adjust test to reliabily fail --- .../Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs index 932e45b1a6..08e036248b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs @@ -105,9 +105,10 @@ namespace osu.Game.Tests.Visual.Editing { var blueprint = this.ChildrenOfType().Single(); InputManager.MoveMouseTo(blueprint.SelectionQuad.TopLeft + new Vector2(100, 0)); - InputManager.ReleaseButton(MouseButton.Left); }); + AddStep("release button", () => InputManager.PressButton(MouseButton.Left)); + AddAssert("object has zero repeats", () => EditorBeatmap.HitObjects.OfType().Single().RepeatCount == 0); } } From 63890ef6feb9b8fffd28152545aaf88d0aefe9ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 13:24:19 +0900 Subject: [PATCH 0650/1400] Fix audio offset tooltip potentially showing "-0 ms" Closes https://github.com/ppy/osu/issues/23339. --- osu.Game/Graphics/UserInterface/TimeSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index e4058827f3..e6e7ae9305 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -12,6 +12,6 @@ namespace osu.Game.Graphics.UserInterface /// public partial class TimeSlider : RoundedSliderBar { - public override LocalisableString TooltipText => $"{Current.Value:N0} ms"; + public override LocalisableString TooltipText => $"{base.TooltipText} ms"; } } From e808e7316b320c3b9f4105ed2f79081bf8203283 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 13:29:30 +0900 Subject: [PATCH 0651/1400] Mark delegate value unused and add comment to avoid future regression --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 46d3620c9c..38ae8c68cb 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -242,7 +242,7 @@ namespace osu.Game.Overlays.Mods if (AllowCustomisation) ((IBindable>)modSettingsArea.SelectedMods).BindTo(SelectedMods); - SelectedMods.BindValueChanged(val => + SelectedMods.BindValueChanged(_ => { updateMultiplier(); updateFromExternalSelection(); @@ -252,6 +252,10 @@ namespace osu.Game.Overlays.Mods if (AllowCustomisation) { + // Importantly, use SelectedMods.Value here (and not the ValueChanged NewValue) as the latter can + // potentially be stale, due to complexities in the way change trackers work. + // + // See https://github.com/ppy/osu/pull/23284#issuecomment-1529056988 modSettingChangeTracker = new ModSettingChangeTracker(SelectedMods.Value); modSettingChangeTracker.SettingChanged += _ => updateMultiplier(); } From 37a5dde8592c48edebdc3ffaa36da96da75d226c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 13:47:49 +0900 Subject: [PATCH 0652/1400] Fix `BeatmapAttributeText` not supporting unicode artist/title --- osu.Game/Skinning/Components/BeatmapAttributeText.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/Components/BeatmapAttributeText.cs b/osu.Game/Skinning/Components/BeatmapAttributeText.cs index 2c16a67cac..6523039a3f 100644 --- a/osu.Game/Skinning/Components/BeatmapAttributeText.cs +++ b/osu.Game/Skinning/Components/BeatmapAttributeText.cs @@ -84,8 +84,8 @@ namespace osu.Game.Skinning.Components private void updateBeatmapContent(WorkingBeatmap workingBeatmap) { - valueDictionary[BeatmapAttribute.Title] = workingBeatmap.BeatmapInfo.Metadata.Title; - valueDictionary[BeatmapAttribute.Artist] = workingBeatmap.BeatmapInfo.Metadata.Artist; + valueDictionary[BeatmapAttribute.Title] = new RomanisableString(workingBeatmap.BeatmapInfo.Metadata.TitleUnicode, workingBeatmap.BeatmapInfo.Metadata.Title); + valueDictionary[BeatmapAttribute.Artist] = new RomanisableString(workingBeatmap.BeatmapInfo.Metadata.ArtistUnicode, workingBeatmap.BeatmapInfo.Metadata.Artist); valueDictionary[BeatmapAttribute.DifficultyName] = workingBeatmap.BeatmapInfo.DifficultyName; valueDictionary[BeatmapAttribute.Creator] = workingBeatmap.BeatmapInfo.Metadata.Author.Username; valueDictionary[BeatmapAttribute.Length] = TimeSpan.FromMilliseconds(workingBeatmap.BeatmapInfo.Length).ToFormattedDuration(); From ad40099e3280d0929ce13b2adca488354bef9f81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 14:00:52 +0900 Subject: [PATCH 0653/1400] Ensure negative sign is only applied when the post-rounded result is negative --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 0c36d73085..0e26029ffa 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -97,7 +97,9 @@ namespace osu.Game.Graphics.UserInterface // Find the number of significant digits (we could have less than 5 after normalize()) int significantDigits = FormatUtils.FindPrecision(decimalPrecision); - return floatValue.ToString($"N{significantDigits}"); + string negativeSign = Math.Round(floatValue, significantDigits) < 0 ? "-" : string.Empty; + + return $"{negativeSign}{Math.Abs(floatValue).ToString($"N{significantDigits}")}"; } /// From 736be6a73ba2c9ff5332b39f828f0310a8d76851 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 14:11:16 +0900 Subject: [PATCH 0654/1400] Refactor slightly for readability --- osu.Game/Overlays/Music/PlaylistItem.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 4a39cc06c8..90fdfd0491 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Music var artist = new RomanisableString(metadata.ArtistUnicode, metadata.Artist); titlePart = text.AddText(title, sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)); - titlePart.DrawablePartsRecreated += _ => updateSelectionState(SelectedSet.Value, instant: true); + titlePart.DrawablePartsRecreated += _ => updateSelectionState(SelectedSet.Value, applyImmediately: true); text.AddText(@" "); // to separate the title from the artist. text.AddText(artist, sprite => @@ -66,24 +66,25 @@ namespace osu.Game.Overlays.Music sprite.Padding = new MarginPadding { Top = 1 }; }); - SelectedSet.BindValueChanged(set => updateSelectionState(set.NewValue, instant: false)); - updateSelectionState(SelectedSet.Value, instant: true); + SelectedSet.BindValueChanged(set => updateSelectionState(set.NewValue)); + updateSelectionState(SelectedSet.Value, applyImmediately: true); }); } private bool selected; - private void updateSelectionState(Live selectedSet, bool instant) + private void updateSelectionState(Live selectedSet, bool applyImmediately = false) { - bool newSelected = selectedSet?.Equals(Model) == true; + bool wasSelected = selected; + selected = selectedSet?.Equals(Model) == true; - if (newSelected == selected && !instant) // instant updates should forcibly set correct state regardless of previous state. + // Immediate updates should forcibly set correct state regardless of previous state. + // This ensures that the initial state is correctly applied. + if (wasSelected == selected && !applyImmediately) return; - selected = newSelected; - foreach (Drawable s in titlePart.Drawables) - s.FadeColour(selected ? colours.Yellow : Color4.White, instant ? 0 : FADE_DURATION); + s.FadeColour(selected ? colours.Yellow : Color4.White, applyImmediately ? 0 : FADE_DURATION); } protected override Drawable CreateContent() => new DelayedLoadWrapper(text = new OsuTextFlowContainer From 7a840e1d8227a3e2dd5073afd27305c47dc7f494 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 14:29:26 +0900 Subject: [PATCH 0655/1400] Remove unnecessary `TransferValue` spec --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 0515e8dc97..ad47039579 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -171,7 +171,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Current = scalingBackgroundDim, KeyboardStep = 0.01f, DisplayAsPercentage = true, - TransferValueOnCommit = false }, } }, From ab4f66fad331aa7d048f8f1365ec12f25071098b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 14:31:39 +0900 Subject: [PATCH 0656/1400] Minor readability refactors --- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 +- .../Settings/Sections/Graphics/LayoutSettings.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index bd52c8bb32..84eb382d34 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -155,7 +155,7 @@ namespace osu.Game.Graphics.Containers private bool requiresBackgroundVisible => (scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1) - && scalingMenuBackgroundDim.Value != 1f; + && scalingMenuBackgroundDim.Value < 1; private void updateSize() { diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index ad47039579..2e26d15105 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -230,11 +230,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (s == dimSlider) { s.CanBeShown.Value = scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays; - return; } - - s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; - s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; + else + { + s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything; + s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off; + } }); } } From 57f48e070359f65100e33838091ee72f28d6cc68 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 14:33:57 +0900 Subject: [PATCH 0657/1400] Start colour black to ensure initial appear transition doesn't look silly --- osu.Game/Graphics/Containers/ScalingContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index 84eb382d34..c47aba2f0c 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Configuration; using osu.Game.Screens; using osu.Game.Screens.Backgrounds; using osuTK; +using osuTK.Graphics; namespace osu.Game.Graphics.Containers { @@ -169,6 +170,7 @@ namespace osu.Game.Graphics.Containers AddInternal(backgroundStack = new BackgroundScreenStack { Alpha = 0, + Colour = Color4.Black, Depth = float.MaxValue }); From 8a536c1cdb75496ad56b056baa83fc2d14376deb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 15:09:24 +0900 Subject: [PATCH 0658/1400] Fix non-block namespace usage --- .../Timeline/HitObjectPointPiece.cs | 83 ++++++++++--------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs index f7854705a4..4b357d3a62 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/HitObjectPointPiece.cs @@ -11,51 +11,52 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; -namespace osu.Game.Screens.Edit.Compose.Components.Timeline; - -public partial class HitObjectPointPiece : CircularContainer +namespace osu.Game.Screens.Edit.Compose.Components.Timeline { - protected OsuSpriteText Label { get; private set; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public partial class HitObjectPointPiece : CircularContainer { - AutoSizeAxes = Axes.Both; + protected OsuSpriteText Label { get; private set; } - Color4 colour = GetRepresentingColour(colours); - - InternalChildren = new Drawable[] + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - new Container - { - AutoSizeAxes = Axes.X, - Height = 16, - Masking = true, - CornerRadius = 8, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Children = new Drawable[] - { - new Box - { - Colour = colour, - RelativeSizeAxes = Axes.Both, - }, - Label = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Padding = new MarginPadding(5), - Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold), - Colour = colours.B5, - } - } - }, - }; - } + AutoSizeAxes = Axes.Both; - protected virtual Color4 GetRepresentingColour(OsuColour colours) - { - return colours.Yellow; + Color4 colour = GetRepresentingColour(colours); + + InternalChildren = new Drawable[] + { + new Container + { + AutoSizeAxes = Axes.X, + Height = 16, + Masking = true, + CornerRadius = 8, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Children = new Drawable[] + { + new Box + { + Colour = colour, + RelativeSizeAxes = Axes.Both, + }, + Label = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Padding = new MarginPadding(5), + Font = OsuFont.Default.With(size: 12, weight: FontWeight.SemiBold), + Colour = colours.B5, + } + } + }, + }; + } + + protected virtual Color4 GetRepresentingColour(OsuColour colours) + { + return colours.Yellow; + } } } From 67f83f246b1c65c62416a24375ef580139d046dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 15:36:01 +0900 Subject: [PATCH 0659/1400] Add more padding around playfield in editor to avoid overlap with tool areas Closes #23130. --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 9 +++++++-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 12 ++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 7a70257f3a..ff1e208186 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -13,8 +13,8 @@ using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Utils; using osu.Framework.Input.Events; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; @@ -62,7 +62,12 @@ namespace osu.Game.Rulesets.Osu.Edit private void load() { // Give a bit of breathing room around the playfield content. - PlayfieldContentContainer.Padding = new MarginPadding(10); + PlayfieldContentContainer.Padding = new MarginPadding + { + Vertical = 10, + Left = TOOLBOX_CONTRACTED_SIZE_LEFT + 10, + Right = TOOLBOX_CONTRACTED_SIZE_RIGHT + 10, + }; LayerBelowRuleset.AddRange(new Drawable[] { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 653861c11c..e2dbd2acdc 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -116,6 +116,11 @@ namespace osu.Game.Rulesets.Edit PlayfieldContentContainer = new Container { Name = "Content", + Padding = new MarginPadding + { + Left = TOOLBOX_CONTRACTED_SIZE_LEFT, + Right = TOOLBOX_CONTRACTED_SIZE_RIGHT, + }, RelativeSizeAxes = Axes.Both, Children = new Drawable[] { @@ -138,7 +143,7 @@ namespace osu.Game.Rulesets.Edit Colour = colourProvider.Background5, RelativeSizeAxes = Axes.Both, }, - LeftToolbox = new ExpandingToolboxContainer(60, 200) + LeftToolbox = new ExpandingToolboxContainer(TOOLBOX_CONTRACTED_SIZE_LEFT, 200) { Children = new Drawable[] { @@ -173,7 +178,7 @@ namespace osu.Game.Rulesets.Edit Colour = colourProvider.Background5, RelativeSizeAxes = Axes.Both, }, - RightToolbox = new ExpandingToolboxContainer(130, 250) + RightToolbox = new ExpandingToolboxContainer(TOOLBOX_CONTRACTED_SIZE_RIGHT, 250) { Child = new EditorToolboxGroup("inspector") { @@ -450,6 +455,9 @@ namespace osu.Game.Rulesets.Edit [Cached] public abstract partial class HitObjectComposer : CompositeDrawable, IPositionSnapProvider { + public const float TOOLBOX_CONTRACTED_SIZE_LEFT = 60; + public const float TOOLBOX_CONTRACTED_SIZE_RIGHT = 130; + public readonly Ruleset Ruleset; protected HitObjectComposer(Ruleset ruleset) From c2ad8c23201814a3ce3103584e2bacc51c30b020 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 2 May 2023 08:41:30 +0200 Subject: [PATCH 0660/1400] Fix comment 1 osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs Co-authored-by: Dean Herbert --- osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs index 5de7d348c5..c587654cda 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Types public interface IHasGenerateTicks { /// - /// Whether or not slider ticks should be generated at this control point. + /// Whether or not slider ticks should be generated by this object. /// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991). /// public bool GenerateTicks { get; set; } From 2e018c8b0696b2394465ef31d1f49aad7c514627 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 2 May 2023 08:41:47 +0200 Subject: [PATCH 0661/1400] Fix comment 2 osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs Co-authored-by: Dean Herbert --- osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs index c587654cda..3ac8b8a086 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasGenerateTicks.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Objects.Types { /// - /// A type of which may or may not generate ticks. + /// A type of which explicitly specifies whether it should generate ticks. /// public interface IHasGenerateTicks { From bd72c67d68aa3bc4bc18f70cd0fd6a4c8c9eb9d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 15:47:35 +0900 Subject: [PATCH 0662/1400] Increase the rate of slider ball fade on argon skins to match other implementations --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs index d6ce793c7e..461b4a3b45 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonSliderBall.cs @@ -98,7 +98,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime)) { - this.FadeOut(duration, Easing.OutQuint); + // intentionally pile on an extra FadeOut to make it happen much faster + this.FadeOut(duration / 4, Easing.OutQuint); icon.ScaleTo(defaultIconScale * icon_scale, duration, Easing.OutQuint); } } From e3c51b96526223674cada703130544646b768f97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 16:26:56 +0900 Subject: [PATCH 0663/1400] Add ability to toggle snaking in slider test scene --- .../TestSceneSlider.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index 1e9f931b74..4ad78a3190 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -15,6 +15,10 @@ using osuTK.Graphics; using osu.Game.Rulesets.Mods; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Testing; using osu.Game.Beatmaps.Legacy; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -22,6 +26,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Configuration; namespace osu.Game.Rulesets.Osu.Tests { @@ -30,6 +35,27 @@ namespace osu.Game.Rulesets.Osu.Tests { private int depthIndex; + private readonly BindableBool snakingIn = new BindableBool(); + private readonly BindableBool snakingOut = new BindableBool(); + + [SetUpSteps] + public void SetUpSteps() + { + AddToggleStep("toggle snaking", v => + { + snakingIn.Value = v; + snakingOut.Value = v; + }); + } + + [BackgroundDependencyLoader] + private void load() + { + var config = (OsuRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull(); + config.BindWith(OsuRulesetSetting.SnakingInSliders, snakingIn); + config.BindWith(OsuRulesetSetting.SnakingOutSliders, snakingOut); + } + [Test] public void TestVariousSliders() { From 1a04be15c74b009bb9e329bf0d35b0031abe5328 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 16:27:17 +0900 Subject: [PATCH 0664/1400] Fix fade in delay for first slider end circle being incorrect when snaking disabled --- .../Objects/Drawables/DrawableSliderRepeat.cs | 11 +++++++---- .../Objects/Drawables/DrawableSliderTail.cs | 8 +++++++- osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs | 5 +---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 3446d41fb4..d474db0526 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -87,12 +87,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateInitialTransforms() { + // When snaking in is enabled, the first end circle needs to be delayed until the snaking completes. + bool delayFadeIn = DrawableSlider.SliderBody!.SnakingIn.Value && HitObject.RepeatIndex == 0; + animDuration = Math.Min(300, HitObject.SpanDuration); - this.Animate( - d => d.FadeIn(animDuration), - d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 2, Easing.OutElasticHalf) - ); + this + .FadeOut() + .Delay(delayFadeIn ? Slider!.TimePreempt / 3f : 0) + .FadeIn(HitObject.RepeatIndex == 0 ? HitObject.TimeFadeIn : animDuration); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 2c1b68e05a..da4feae242 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -91,7 +91,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateInitialTransforms(); - CirclePiece.FadeInFromZero(HitObject.TimeFadeIn); + // When snaking in is enabled, the first end circle needs to be delayed until the snaking completes. + bool delayFadeIn = DrawableSlider.SliderBody!.SnakingIn.Value && HitObject.RepeatIndex == 0; + + CirclePiece + .FadeOut() + .Delay(delayFadeIn ? Slider!.TimePreempt / 3f : 0) + .FadeIn(HitObject.TimeFadeIn); } protected override void UpdateHitStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index 35bec92354..b5374333c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs @@ -39,11 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects } else { - // taken from osu-stable - const float first_end_circle_preempt_adjust = 2 / 3f; - // The first end circle should fade in with the slider. - TimePreempt = (StartTime - slider.StartTime) + slider.TimePreempt * first_end_circle_preempt_adjust; + TimePreempt = (StartTime - slider.StartTime) + slider.TimePreempt; } } From a619812cab7f881c2968db977e2bb5322299b03e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 16:36:43 +0900 Subject: [PATCH 0665/1400] Fix nullability and remove extra preempt from `SliderEndCircle` calculation --- .../Objects/Drawables/DrawableSliderRepeat.cs | 4 ++-- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs | 4 ++-- osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index d474db0526..fc4863f164 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -88,13 +88,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateInitialTransforms() { // When snaking in is enabled, the first end circle needs to be delayed until the snaking completes. - bool delayFadeIn = DrawableSlider.SliderBody!.SnakingIn.Value && HitObject.RepeatIndex == 0; + bool delayFadeIn = DrawableSlider.SliderBody?.SnakingIn.Value == true && HitObject.RepeatIndex == 0; animDuration = Math.Min(300, HitObject.SpanDuration); this .FadeOut() - .Delay(delayFadeIn ? Slider!.TimePreempt / 3f : 0) + .Delay(delayFadeIn ? (Slider?.TimePreempt ?? 0) / 3 : 0) .FadeIn(HitObject.RepeatIndex == 0 ? HitObject.TimeFadeIn : animDuration); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index da4feae242..d9501f7d58 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -92,11 +92,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdateInitialTransforms(); // When snaking in is enabled, the first end circle needs to be delayed until the snaking completes. - bool delayFadeIn = DrawableSlider.SliderBody!.SnakingIn.Value && HitObject.RepeatIndex == 0; + bool delayFadeIn = DrawableSlider.SliderBody?.SnakingIn.Value == true && HitObject.RepeatIndex == 0; CirclePiece .FadeOut() - .Delay(delayFadeIn ? Slider!.TimePreempt / 3f : 0) + .Delay(delayFadeIn ? (Slider?.TimePreempt ?? 0) / 3 : 0) .FadeIn(HitObject.TimeFadeIn); } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index b5374333c9..f52c3ab382 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects else { // The first end circle should fade in with the slider. - TimePreempt = (StartTime - slider.StartTime) + slider.TimePreempt; + TimePreempt += StartTime - slider.StartTime; } } From 414b80d44e78ee5495aa18ae3afd7661b9fe32a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 17:00:54 +0900 Subject: [PATCH 0666/1400] Change flashlight depth in a more standard way --- osu.Game/Rulesets/Mods/ModFlashlight.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 9527e8ab5d..215fc877dc 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -82,12 +82,12 @@ namespace osu.Game.Rulesets.Mods flashlight.RelativeSizeAxes = Axes.Both; flashlight.Colour = Color4.Black; + // Flashlight mods should always draw above any other mod adding overlays. + flashlight.Depth = float.MinValue; flashlight.Combo.BindTo(Combo); drawableRuleset.Overlays.Add(flashlight); - // Stop flashlight from being drawn underneath other mods that generate HitObjects. - drawableRuleset.Overlays.ChangeChildDepth(flashlight, float.MinValue); } protected abstract Flashlight CreateFlashlight(); From fb0e90913db89e8ffc80fc17056d8ed1f4cbfecc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 17:07:12 +0900 Subject: [PATCH 0667/1400] Ensure lifetime start is also updated when reverting judgements --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 0fc27c8f1d..bfc6c24fa5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Mods BubbleDrawable? lastBubble = bubbleContainer.OfType().LastOrDefault(); lastBubble?.ClearTransforms(); - lastBubble?.Expire(); + lastBubble?.Expire(true); }; } From 7830711c8e97b83852f705dbad25d50cc71a1604 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 17:07:22 +0900 Subject: [PATCH 0668/1400] Tidy up various code quality issues in `OsuModBubbles` --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index bfc6c24fa5..9ae38de7c9 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -165,15 +165,15 @@ namespace osu.Game.Rulesets.Osu.Mods ColourInfo colourDarker = DrawableOsuHitObject.AccentColour.Value.Darken(0.1f); // The absolute length of the bubble's animation, can be used in fractions for animations of partial length - double getAnimationDuration = 1700 + Math.Pow(FadeTime, 1.07f); + double duration = 1700 + Math.Pow(FadeTime, 1.07f); // Main bubble scaling based on combo this.FadeTo(1) - .ScaleTo(MaxSize, getAnimationDuration * 0.8f) + .ScaleTo(MaxSize, duration * 0.8f) .Then() // Pop at the end of the bubbles life time - .ScaleTo(MaxSize * 1.5f, getAnimationDuration * 0.2f, Easing.OutQuint) - .FadeOut(getAnimationDuration * 0.2f, Easing.OutCirc).Expire(); + .ScaleTo(MaxSize * 1.5f, duration * 0.2f, Easing.OutQuint) + .FadeOut(duration * 0.2f, Easing.OutCirc).Expire(); if (!DrawableOsuHitObject.IsHit) return; @@ -182,28 +182,28 @@ namespace osu.Game.Rulesets.Osu.Mods colourBox.FadeColour(colourDarker); - content.TransformTo(nameof(BorderColour), colourDarker, getAnimationDuration * 0.3f, Easing.OutQuint); + content.TransformTo(nameof(BorderColour), colourDarker, duration * 0.3f, Easing.OutQuint); // Ripple effect utilises the border to reduce drawable count - content.TransformTo(nameof(BorderThickness), 2f, getAnimationDuration * 0.3f, Easing.OutQuint) + content.TransformTo(nameof(BorderThickness), 2f, duration * 0.3f, Easing.OutQuint) // Avoids transparency overlap issues during the bubble "pop" .Then().Schedule(() => content.BorderThickness = 0); } - private Vector2 getPosition(DrawableOsuHitObject drawableOsuHitObject) + private Vector2 getPosition(DrawableOsuHitObject drawableObject) { - switch (drawableOsuHitObject) + switch (drawableObject) { // SliderHeads are derived from HitCircles, // so we must handle them before to avoid them using the wrong positioning logic case DrawableSliderHead: - return drawableOsuHitObject.HitObject.Position; + return drawableObject.HitObject.Position; // Using hitobject position will cause issues with HitCircle placement due to stack leniency. case DrawableHitCircle: - return drawableOsuHitObject.Position; + return drawableObject.Position; default: - return drawableOsuHitObject.HitObject.Position; + return drawableObject.HitObject.Position; } } } From e44672bdd5f4f11ae0d309c20df29271d4203f05 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 2 May 2023 17:08:49 +0900 Subject: [PATCH 0669/1400] Avoid using `Schedule` in transforms (doesn't handle rewind well) --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 9ae38de7c9..12e2090f89 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -185,8 +185,9 @@ namespace osu.Game.Rulesets.Osu.Mods content.TransformTo(nameof(BorderColour), colourDarker, duration * 0.3f, Easing.OutQuint); // Ripple effect utilises the border to reduce drawable count content.TransformTo(nameof(BorderThickness), 2f, duration * 0.3f, Easing.OutQuint) + .Then() // Avoids transparency overlap issues during the bubble "pop" - .Then().Schedule(() => content.BorderThickness = 0); + .TransformTo(nameof(BorderThickness), 0f); } private Vector2 getPosition(DrawableOsuHitObject drawableObject) From 8160d562640f4c3f40d8d4b01a68306f8177e31c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 2 May 2023 11:51:05 +0300 Subject: [PATCH 0670/1400] Update test shaders --- .../Resources/Shaders/sh_TestFragment.fs | 15 ++++--- .../Resources/Shaders/sh_TestVertex.vs | 42 ++++++++----------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Resources/Shaders/sh_TestFragment.fs b/osu.Game.Tests/Resources/Shaders/sh_TestFragment.fs index c70ad751be..99b85d0502 100644 --- a/osu.Game.Tests/Resources/Shaders/sh_TestFragment.fs +++ b/osu.Game.Tests/Resources/Shaders/sh_TestFragment.fs @@ -1,11 +1,14 @@ -#include "sh_Utils.h" +#define HIGH_PRECISION_VERTEX -varying mediump vec2 v_TexCoord; -varying mediump vec4 v_TexRect; +#include "sh_Utils.h" +#include "sh_Masking.h" + +layout(location = 2) in highp vec2 v_TexCoord; + +layout(location = 0) out vec4 o_Colour; void main(void) { - float hueValue = v_TexCoord.x / (v_TexRect[2] - v_TexRect[0]); - gl_FragColor = hsv2rgb(vec4(hueValue, 1, 1, 1)); + highp float hueValue = v_TexCoord.x / (v_TexRect[2] - v_TexRect[0]); + o_Colour = getRoundedColor(hsv2rgb(vec4(hueValue, 1, 1, 1)), v_TexCoord); } - diff --git a/osu.Game.Tests/Resources/Shaders/sh_TestVertex.vs b/osu.Game.Tests/Resources/Shaders/sh_TestVertex.vs index 4485356fa4..505554bb33 100644 --- a/osu.Game.Tests/Resources/Shaders/sh_TestVertex.vs +++ b/osu.Game.Tests/Resources/Shaders/sh_TestVertex.vs @@ -1,31 +1,25 @@ -#include "sh_Utils.h" +layout(location = 0) in highp vec2 m_Position; +layout(location = 1) in lowp vec4 m_Colour; +layout(location = 2) in highp vec2 m_TexCoord; +layout(location = 3) in highp vec4 m_TexRect; +layout(location = 4) in mediump vec2 m_BlendRange; -attribute highp vec2 m_Position; -attribute lowp vec4 m_Colour; -attribute mediump vec2 m_TexCoord; -attribute mediump vec4 m_TexRect; -attribute mediump vec2 m_BlendRange; - -varying highp vec2 v_MaskingPosition; -varying lowp vec4 v_Colour; -varying mediump vec2 v_TexCoord; -varying mediump vec4 v_TexRect; -varying mediump vec2 v_BlendRange; - -uniform highp mat4 g_ProjMatrix; -uniform highp mat3 g_ToMaskingSpace; +layout(location = 0) out highp vec2 v_MaskingPosition; +layout(location = 1) out lowp vec4 v_Colour; +layout(location = 2) out highp vec2 v_TexCoord; +layout(location = 3) out highp vec4 v_TexRect; +layout(location = 4) out mediump vec2 v_BlendRange; void main(void) { - // Transform from screen space to masking space. - highp vec3 maskingPos = g_ToMaskingSpace * vec3(m_Position, 1.0); - v_MaskingPosition = maskingPos.xy / maskingPos.z; + // Transform from screen space to masking space. + highp vec3 maskingPos = g_ToMaskingSpace * vec3(m_Position, 1.0); + v_MaskingPosition = maskingPos.xy / maskingPos.z; - v_Colour = m_Colour; - v_TexCoord = m_TexCoord; - v_TexRect = m_TexRect; - v_BlendRange = m_BlendRange; + v_Colour = m_Colour; + v_TexCoord = m_TexCoord; + v_TexRect = m_TexRect; + v_BlendRange = m_BlendRange; - gl_Position = gProjMatrix * vec4(m_Position, 1.0, 1.0); + gl_Position = g_ProjMatrix * vec4(m_Position, 1.0, 1.0); } - From ba5088f71a57bf7d26eac4f6d319b9c0eb08d438 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 2 May 2023 11:55:05 +0300 Subject: [PATCH 0671/1400] Add missing ruleset shader tests --- osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs index 585a3f95e7..f0a9ce7beb 100644 --- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs +++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs @@ -53,6 +53,8 @@ namespace osu.Game.Tests.Testing { Dependencies.Get().GetRawData(@"sh_TestVertex.vs"); Dependencies.Get().GetRawData(@"sh_TestFragment.fs"); + Dependencies.Get().Load(@"TestVertex", @"TestFragment"); + Dependencies.Get().Load(VertexShaderDescriptor.TEXTURE_2, @"TestFragment"); }); } From d2d81bb82c6fe9fcca7e7c8f4ac3879994aa8aa4 Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 2 May 2023 12:29:11 +0200 Subject: [PATCH 0672/1400] remove redundant zero check in sv calculation --- .../Edit/Blueprints/Components/EditablePath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs index 75ee0546dd..7a577f8a83 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/Components/EditablePath.cs @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints.Components // // The value is clamped here by the bindable min and max values. // In case the required velocity is too large, the path is not preserved. - svBindable.Value = requiredVelocity == 0 ? 1 : Math.Ceiling(requiredVelocity / svToVelocityFactor); + svBindable.Value = Math.Ceiling(requiredVelocity / svToVelocityFactor); path.ConvertToSliderPath(hitObject.Path, hitObject.LegacyConvertedY, hitObject.Velocity); From 90d98cd3294ec30533017d83382d60525305f98c Mon Sep 17 00:00:00 2001 From: OliBomby Date: Tue, 2 May 2023 12:41:39 +0200 Subject: [PATCH 0673/1400] remove constructor argument from Banana --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 8 +++++--- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index e137204c32..e4aa778902 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -22,9 +22,11 @@ namespace osu.Game.Rulesets.Catch.Objects public override Judgement CreateJudgement() => new CatchBananaJudgement(); - public Banana(int volume = 100) + private static readonly List samples = new List { new BananaHitSampleInfo() }; + + public Banana() { - Samples = new List { new BananaHitSampleInfo(volume) }; + Samples = samples; } // override any external colour changes with banananana @@ -45,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Objects } } - private class BananaHitSampleInfo : HitSampleInfo, IEquatable + public class BananaHitSampleInfo : HitSampleInfo, IEquatable { private static readonly string[] lookup_names = { "Gameplay/metronomelow", "Gameplay/catch-banana" }; diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 08febeabbf..5bd4ac86f5 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,7 +1,9 @@ // 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 System.Threading; +using osu.Game.Audio; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; @@ -35,10 +37,11 @@ namespace osu.Game.Rulesets.Catch.Objects { cancellationToken.ThrowIfCancellationRequested(); - AddNested(new Banana(GetSampleInfo().Volume) + AddNested(new Banana { StartTime = time, BananaIndex = i, + Samples = new List { new Banana.BananaHitSampleInfo(GetSampleInfo().Volume) } }); time += spacing; From a6ca0497399d5e83faca452782c49fa74c2c406a Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 2 May 2023 14:15:33 +0300 Subject: [PATCH 0674/1400] Manually implement @bdach prototype --- .../UserInterface/TestSceneModColumn.cs | 2 +- .../Mods/Input/ClassicModHotkeyHandler.cs | 2 +- .../Mods/Input/SequentialModHotkeyHandler.cs | 2 +- osu.Game/Overlays/Mods/ModColumn.cs | 12 +++--- osu.Game/Overlays/Mods/ModPanel.cs | 30 +++++++++++--- osu.Game/Overlays/Mods/ModPresetPanel.cs | 11 ++++++ osu.Game/Overlays/Mods/ModSelectColumn.cs | 9 ++++- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 39 ++++++++++++------- osu.Game/Overlays/Mods/ModSelectPanel.cs | 26 ++++++++++++- osu.Game/Overlays/Mods/ModState.cs | 11 +++++- osu.Game/Overlays/Mods/SelectAllModsButton.cs | 2 +- 11 files changed, 112 insertions(+), 34 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index a11000214c..3f5676ee24 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -291,7 +291,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) - modState.Filtered.Value = filter?.Invoke(modState.Mod) == false; + modState.MatchingFilter.Value = filter?.Invoke(modState.Mod) == false; } private partial class TestModColumn : ModColumn diff --git a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs index 4f3c18fc43..566e741880 100644 --- a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Mods.Input if (!mod_type_lookup.TryGetValue(e.Key, out var typesToMatch)) return false; - var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && !modState.Filtered.Value).ToArray(); + var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && modState.MatchingFilter.Value).ToArray(); if (matchingMods.Length == 0) return false; diff --git a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs index dedb556304..b4ec8ad4c8 100644 --- a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Mods.Input if (index < 0) return false; - var modState = availableMods.Where(modState => !modState.Filtered.Value).ElementAtOrDefault(index); + var modState = availableMods.Where(modState => modState.MatchingFilter.Value).ElementAtOrDefault(index); if (modState == null) return false; diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 5d9f616e5f..df2a7780d3 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Mods foreach (var mod in availableMods) { mod.Active.BindValueChanged(_ => updateState()); - mod.Filtered.BindValueChanged(_ => updateState()); + mod.MatchingFilter.BindValueChanged(_ => updateState()); } updateState(); @@ -145,12 +145,12 @@ namespace osu.Game.Overlays.Mods private void updateState() { - Alpha = availableMods.All(mod => mod.Filtered.Value) ? 0 : 1; + Alpha = availableMods.All(mod => !mod.MatchingFilter.Value) ? 0 : 1; if (toggleAllCheckbox != null && !SelectionAnimationRunning) { - toggleAllCheckbox.Alpha = availableMods.Any(panel => !panel.Filtered.Value) ? 1 : 0; - toggleAllCheckbox.Current.Value = availableMods.Where(panel => !panel.Filtered.Value).All(panel => panel.Active.Value); + toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.MatchingFilter.Value) ? 1 : 0; + toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.MatchingFilter.Value).All(panel => panel.Active.Value); } } @@ -195,7 +195,7 @@ namespace osu.Game.Overlays.Mods { pendingSelectionOperations.Clear(); - foreach (var button in availableMods.Where(b => !b.Active.Value && !b.Filtered.Value)) + foreach (var button in availableMods.Where(b => !b.Active.Value && b.MatchingFilter.Value)) pendingSelectionOperations.Enqueue(() => button.Active.Value = true); } @@ -206,7 +206,7 @@ namespace osu.Game.Overlays.Mods { pendingSelectionOperations.Clear(); - foreach (var button in availableMods.Where(b => b.Active.Value && !b.Filtered.Value)) + foreach (var button in availableMods.Where(b => b.Active.Value && b.MatchingFilter.Value)) pendingSelectionOperations.Enqueue(() => button.Active.Value = false); } diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index b5fee9d116..a5ff52dfd2 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -1,9 +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 System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -11,11 +14,10 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPanel : ModSelectPanel + public partial class ModPanel : ModSelectPanel, IConditionalFilterable { public Mod Mod => modState.Mod; public override BindableBool Active => modState.Active; - public BindableBool Filtered => modState.Filtered; protected override float IdleSwitchWidth => 54; protected override float ExpandedSwitchWidth => 70; @@ -54,7 +56,7 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - Filtered.BindValueChanged(_ => updateFilterState(), true); + canBeShown.BindTo(modState.ValidForSelection); } protected override void Select() @@ -71,11 +73,29 @@ namespace osu.Game.Overlays.Mods #region Filtering support - private void updateFilterState() + public override IEnumerable FilterTerms => new[] { - this.FadeTo(Filtered.Value ? 0 : 1); + Mod.Name, + Mod.Acronym, + Mod.Description + }; + + public override bool MatchingFilter + { + get => modState.MatchingFilter.Value; + set + { + if (modState.MatchingFilter.Value == value) + return; + + modState.MatchingFilter.Value = value; + this.FadeTo(value ? 1 : 0); + } } + private readonly BindableBool canBeShown = new BindableBool(true); + IBindable IConditionalFilterable.CanBeShown => canBeShown; + #endregion } } diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 6e12e34124..5b6146e106 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Graphics; @@ -80,6 +81,16 @@ namespace osu.Game.Overlays.Mods Active.Value = new HashSet(Preset.Value.Mods).SetEquals(selectedMods.Value); } + #region Filtering support + + public override IEnumerable FilterTerms => new LocalisableString[] + { + Preset.Value.Name, + Preset.Value.Description + }; + + #endregion + #region IHasCustomTooltip public ModPreset TooltipContent => Preset.Value; diff --git a/osu.Game/Overlays/Mods/ModSelectColumn.cs b/osu.Game/Overlays/Mods/ModSelectColumn.cs index e6d7bcd97d..8bf3fd404f 100644 --- a/osu.Game/Overlays/Mods/ModSelectColumn.cs +++ b/osu.Game/Overlays/Mods/ModSelectColumn.cs @@ -43,10 +43,15 @@ namespace osu.Game.Overlays.Mods /// public readonly Bindable Active = new BindableBool(true); + public string SearchTerm + { + set => ItemsFlow.SearchTerm = value; + } + protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => base.ReceivePositionalInputAtSubTree(screenSpacePos) && Active.Value; protected readonly Container ControlContainer; - protected readonly FillFlowContainer ItemsFlow; + protected readonly SearchContainer ItemsFlow; private readonly TextFlowContainer headerText; private readonly Box headerBackground; @@ -150,7 +155,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.Both, ClampExtension = 100, ScrollbarOverlapsContent = false, - Child = ItemsFlow = new FillFlowContainer + Child = ItemsFlow = new SearchContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 31f2c87100..12e894cfba 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -108,6 +108,8 @@ namespace osu.Game.Overlays.Mods private ColumnFlowContainer columnFlow = null!; private FillFlowContainer footerButtonFlow = null!; + private Container aboveColumnsContent = null!; + private ShearedSearchTextBox searchTextBox = null!; private DifficultyMultiplierDisplay? multiplierDisplay; private ModSearch? modSearch; @@ -148,6 +150,17 @@ namespace osu.Game.Overlays.Mods MainAreaContent.AddRange(new Drawable[] { + aboveColumnsContent = new Container + { + RelativeSizeAxes = Axes.X, + Height = ModsEffectDisplay.HEIGHT, + Padding = new MarginPadding { Horizontal = 100 }, + Child = searchTextBox = new ShearedSearchTextBox + { + HoldFocus = false, + Width = 300 + } + }, new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, @@ -188,18 +201,10 @@ namespace osu.Game.Overlays.Mods if (ShowTotalMultiplier) { - MainAreaContent.Add(new Container + aboveColumnsContent.Add(multiplierDisplay = new DifficultyMultiplierDisplay { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - AutoSizeAxes = Axes.X, - Height = ModsEffectDisplay.HEIGHT, - Margin = new MarginPadding { Horizontal = 100 }, - Child = multiplierDisplay = new DifficultyMultiplierDisplay - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre }); } @@ -271,6 +276,12 @@ namespace osu.Game.Overlays.Mods customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); + searchTextBox.Current.BindValueChanged(query => + { + foreach (var column in columnFlow.Columns) + column.SearchTerm = query.NewValue; + }, true); + // Start scrolled slightly to the right to give the user a sense that // there is more horizontal content available. ScheduleAfterChildren(() => @@ -352,7 +363,7 @@ namespace osu.Game.Overlays.Mods private void filterMods() { foreach (var modState in allAvailableMods) - modState.Filtered.Value = !modState.Mod.HasImplementation || !IsValidMod.Invoke(modState.Mod); + modState.ValidForSelection.Value = modState.Mod.HasImplementation && IsValidMod.Invoke(modState.Mod); } private void updateMultiplier() @@ -487,7 +498,7 @@ namespace osu.Game.Overlays.Mods { var column = columnFlow[i].Column; - bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => modState.Filtered.Value); + bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => !modState.MatchingFilter.Value); double delay = allFiltered ? 0 : nonFilteredColumnCount * 30; double duration = allFiltered ? 0 : fade_in_duration; @@ -549,7 +560,7 @@ namespace osu.Game.Overlays.Mods if (column is ModColumn modColumn) { - allFiltered = modColumn.AvailableMods.All(modState => modState.Filtered.Value); + allFiltered = modColumn.AvailableMods.All(modState => !modState.MatchingFilter.Value); modColumn.FlushPendingSelections(); } diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 81285833bd..90663d083c 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.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 System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -24,7 +25,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Mods { - public abstract partial class ModSelectPanel : OsuClickableContainer, IHasAccentColour + public abstract partial class ModSelectPanel : OsuClickableContainer, IHasAccentColour, IFilterable { public abstract BindableBool Active { get; } @@ -263,5 +264,28 @@ namespace osu.Game.Overlays.Mods TextBackground.FadeColour(foregroundColour, transitionDuration, Easing.OutQuint); TextFlow.FadeColour(textColour, transitionDuration, Easing.OutQuint); } + + #region IFilterable + + public abstract IEnumerable FilterTerms { get; } + + private bool matchingFilter; + + public virtual bool MatchingFilter + { + get => matchingFilter; + set + { + if (matchingFilter == value) + return; + + matchingFilter = value; + this.FadeTo(value ? 1 : 0); + } + } + + public bool FilteringActive { set { } } + + #endregion } } diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index 3ee890e876..35b264fe71 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.cs @@ -32,9 +32,16 @@ namespace osu.Game.Overlays.Mods public bool PendingConfiguration { get; set; } /// - /// Whether the mod is currently filtered out due to not matching imposed criteria. + /// Whether the mod is currently valid for selection. + /// This can be in scenarios such as the free mod select overlay, where not all mods are selectable + /// regardless of search criteria imposed by the user selecting. /// - public BindableBool Filtered { get; } = new BindableBool(); + public BindableBool ValidForSelection { get; } = new BindableBool(true); + + /// + /// Whether the mod is matching the current filter, i.e. it is available for user selection. + /// + public BindableBool MatchingFilter { get; } = new BindableBool(true); public ModState(Mod mod) { diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index f4b8025227..212563de7d 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Mods { Enabled.Value = availableMods.Value .SelectMany(pair => pair.Value) - .Any(modState => !modState.Active.Value && !modState.Filtered.Value); + .Any(modState => !modState.Active.Value && !modState.MatchingFilter.Value); } public bool OnPressed(KeyBindingPressEvent e) From 95badb9455218c2c2d1d755eb9bf1668c7624984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 2 May 2023 18:35:06 +0200 Subject: [PATCH 0675/1400] Adjust composer tests to new screen layout `TestSceneHitObjectComposer.TestPlacementFailsWhenClickingButton()` was attempting to cover the case of the user clicking a toolbox button which was in front of the playfield, and ensure that the click did not result in a placement. However, since the paddings in 67f83f246b1c65c62416a24375ef580139d046dc were added, it is impossible for a toolbox button to be in front of the playfield in the collapsed state, which the test was relying on. The test scenario is still however relevant in the case of the toolbox being expanded, as in that state the toolbux buttons may very well end up being in front of the playfield, and they still should not result in a hitobject being placed. To ensure that this is the case, add a few extra test steps ensuring that the toolbox is expanded first before trying to retrieve an overlapping button. --- .../Visual/Editing/TestSceneHitObjectComposer.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs index 7ab0188114..9bdb9a513c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectComposer.cs @@ -108,12 +108,16 @@ namespace osu.Game.Tests.Visual.Editing AddStep("Change to hitcircle", () => hitObjectComposer.ChildrenOfType().First(d => d.Button.Label == "HitCircle").TriggerClick()); + ExpandingToolboxContainer toolboxContainer = null!; + + AddStep("move mouse to toolbox", () => InputManager.MoveMouseTo(toolboxContainer = hitObjectComposer.ChildrenOfType().First())); + AddUntilStep("toolbox is expanded", () => toolboxContainer.Expanded.Value); + AddUntilStep("wait for toolbox to expand", () => toolboxContainer.LatestTransformEndTime, () => Is.EqualTo(Time.Current)); + AddStep("move mouse to overlapping toggle button", () => { var playfield = hitObjectComposer.Playfield.ScreenSpaceDrawQuad; - var button = hitObjectComposer - .ChildrenOfType().First() - .ChildrenOfType().First(b => playfield.Contains(b.ScreenSpaceDrawQuad.Centre)); + var button = toolboxContainer.ChildrenOfType().First(b => playfield.Contains(b.ScreenSpaceDrawQuad.Centre)); InputManager.MoveMouseTo(button); }); From 9c4312b407bb208917a8abf42283018bdf47bd56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 12:37:07 +0900 Subject: [PATCH 0676/1400] Add support for flipping colour of reverse arrow on legacy default skin when combo colour is too bright --- .../Skinning/Legacy/LegacyReverseArrow.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs index fbe094ef81..e6166e9441 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs @@ -3,11 +3,13 @@ using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { @@ -18,6 +20,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy private Drawable proxy = null!; + private Bindable accentColour = null!; + + private bool textureIsDefaultSkin; + + private Drawable arrow = null!; + [BackgroundDependencyLoader] private void load(ISkinSource skinSource) { @@ -26,7 +34,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy string lookupName = new OsuSkinComponentLookup(OsuSkinComponents.ReverseArrow).LookupName; var skin = skinSource.FindProvider(s => s.GetTexture(lookupName) != null); - InternalChild = skin?.GetAnimation(lookupName, true, true) ?? Empty(); + + InternalChild = arrow = (skin?.GetAnimation(lookupName, true, true) ?? Empty()); + textureIsDefaultSkin = skin is ISkinTransformer transformer && transformer.Skin is DefaultLegacySkin; } protected override void LoadComplete() @@ -39,6 +49,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { drawableHitObject.HitObjectApplied += onHitObjectApplied; onHitObjectApplied(drawableHitObject); + + accentColour = drawableHitObject.AccentColour.GetBoundCopy(); + accentColour.BindValueChanged(c => + { + arrow.Colour = textureIsDefaultSkin && c.NewValue.R + c.NewValue.G + c.NewValue.B > (600 / 255f) ? Color4.Black : Color4.White; + }, true); } } From 16c624fb61a7dd02460e799dd48570162f3eb2a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 13:02:05 +0900 Subject: [PATCH 0677/1400] Ensure `static` banana samples are not mutated --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index e4aa778902..4c66c054e1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -22,11 +22,11 @@ namespace osu.Game.Rulesets.Catch.Objects public override Judgement CreateJudgement() => new CatchBananaJudgement(); - private static readonly List samples = new List { new BananaHitSampleInfo() }; + private static readonly IList default_banana_samples = new List { new BananaHitSampleInfo() }.AsReadOnly(); public Banana() { - Samples = samples; + Samples = default_banana_samples; } // override any external colour changes with banananana From 588a4e6196cc038928fa0d68481b72cae0cba4e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 13:19:13 +0900 Subject: [PATCH 0678/1400] Move pragma disable to top of `LegacyBeatmapDecoder` Makes more sense as it's used multiple times in the class. --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index d20f7e198b..9dcd97459f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -3,6 +3,8 @@ #nullable disable +#pragma warning disable 618 + using System; using System.Collections.Generic; using System.IO; @@ -102,9 +104,8 @@ namespace osu.Game.Beatmaps.Formats var legacyInfo = beatmap.ControlPointInfo as LegacyControlPointInfo; DifficultyControlPoint difficultyControlPoint = legacyInfo != null ? legacyInfo.DifficultyPointAt(hitObject.StartTime) : DifficultyControlPoint.DEFAULT; -#pragma warning disable 618 + if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint) -#pragma warning restore 618 { hitObject.LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier; if (hitObject is IHasGenerateTicks hasGenerateTicks) @@ -494,9 +495,7 @@ namespace osu.Game.Beatmaps.Formats int onlineRulesetID = beatmap.BeatmapInfo.Ruleset.OnlineID; -#pragma warning disable 618 addControlPoint(time, new LegacyDifficultyControlPoint(onlineRulesetID, beatLength) -#pragma warning restore 618 { SliderVelocity = speedMultiplier, }, timingChange); From cca15f930c5ab8a4ef7a3558613bf4bf12f84d33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 13:26:50 +0900 Subject: [PATCH 0679/1400] Refactor `applyLegacyInfoAndDefaults` for legibility --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 9dcd97459f..90be90fcaf 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -101,9 +101,14 @@ namespace osu.Game.Beatmaps.Formats private void applyLegacyInfoAndDefaults(HitObject hitObject) { - var legacyInfo = beatmap.ControlPointInfo as LegacyControlPointInfo; + DifficultyControlPoint difficultyControlPoint = DifficultyControlPoint.DEFAULT; + SampleControlPoint sampleControlPoint = SampleControlPoint.DEFAULT; - DifficultyControlPoint difficultyControlPoint = legacyInfo != null ? legacyInfo.DifficultyPointAt(hitObject.StartTime) : DifficultyControlPoint.DEFAULT; + if (beatmap.ControlPointInfo is LegacyControlPointInfo legacyInfo) + { + difficultyControlPoint = legacyInfo.DifficultyPointAt(hitObject.StartTime); + sampleControlPoint = legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency); + } if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint) { @@ -117,18 +122,17 @@ namespace osu.Game.Beatmaps.Formats hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); - SampleControlPoint sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency) : SampleControlPoint.DEFAULT; - hitObject.Samples = hitObject.Samples.Select(o => sampleControlPoint.ApplyTo(o)).ToList(); - if (hitObject is not IHasRepeats hasRepeats) return; - - for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) + if (hitObject is IHasRepeats hasRepeats) { - double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency; - sampleControlPoint = legacyInfo != null ? legacyInfo.SamplePointAt(time) : SampleControlPoint.DEFAULT; + for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) + { + double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency; + sampleControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(time) ?? SampleControlPoint.DEFAULT; - hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(o => sampleControlPoint.ApplyTo(o)).ToList(); + hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(o => sampleControlPoint.ApplyTo(o)).ToList(); + } } } From 48fd99818ea448a6f21fa2ecb9e67bd8ef260e0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 13:30:45 +0900 Subject: [PATCH 0680/1400] Split out default and sample application --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 90be90fcaf..5e98025c9a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -95,20 +95,14 @@ namespace osu.Game.Beatmaps.Formats foreach (var hitObject in this.beatmap.HitObjects) { - applyLegacyInfoAndDefaults(hitObject); + applyDefaults(hitObject); + applySamples(hitObject); } } - private void applyLegacyInfoAndDefaults(HitObject hitObject) + private void applyDefaults(HitObject hitObject) { - DifficultyControlPoint difficultyControlPoint = DifficultyControlPoint.DEFAULT; - SampleControlPoint sampleControlPoint = SampleControlPoint.DEFAULT; - - if (beatmap.ControlPointInfo is LegacyControlPointInfo legacyInfo) - { - difficultyControlPoint = legacyInfo.DifficultyPointAt(hitObject.StartTime); - sampleControlPoint = legacyInfo.SamplePointAt(hitObject.GetEndTime() + control_point_leniency); - } + DifficultyControlPoint difficultyControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.DifficultyPointAt(hitObject.StartTime) ?? DifficultyControlPoint.DEFAULT; if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint) { @@ -121,6 +115,11 @@ namespace osu.Game.Beatmaps.Formats hasSliderVelocity.SliderVelocity = difficultyControlPoint.SliderVelocity; hitObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty); + } + + private void applySamples(HitObject hitObject) + { + SampleControlPoint sampleControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(hitObject.GetEndTime() + control_point_leniency) ?? SampleControlPoint.DEFAULT; hitObject.Samples = hitObject.Samples.Select(o => sampleControlPoint.ApplyTo(o)).ToList(); @@ -129,9 +128,9 @@ namespace osu.Game.Beatmaps.Formats for (int i = 0; i < hasRepeats.NodeSamples.Count; i++) { double time = hitObject.StartTime + i * hasRepeats.Duration / hasRepeats.SpanCount() + control_point_leniency; - sampleControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(time) ?? SampleControlPoint.DEFAULT; + var nodeSamplePoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(time) ?? SampleControlPoint.DEFAULT; - hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(o => sampleControlPoint.ApplyTo(o)).ToList(); + hasRepeats.NodeSamples[i] = hasRepeats.NodeSamples[i].Select(o => nodeSamplePoint.ApplyTo(o)).ToList(); } } } From f930c4bd0aaa4137ce2c2fbcbe5870a7d919fefb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 13:33:31 +0900 Subject: [PATCH 0681/1400] Move `struct` to bottom of file --- .../Beatmaps/Formats/LegacyBeatmapEncoder.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 6b228a56a1..7fbcca9adb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -92,7 +92,8 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"AudioLeadIn: {beatmap.BeatmapInfo.AudioLeadIn}")); writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); writer.WriteLine(FormattableString.Invariant($"Countdown: {(int)beatmap.BeatmapInfo.Countdown}")); - writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(((beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePoints?.FirstOrDefault() ?? SampleControlPoint.DEFAULT).SampleBank)}")); + writer.WriteLine(FormattableString.Invariant( + $"SampleSet: {toLegacySampleBank(((beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePoints?.FirstOrDefault() ?? SampleControlPoint.DEFAULT).SampleBank)}")); writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); writer.WriteLine(FormattableString.Invariant($"Mode: {onlineRulesetID}")); writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}")); @@ -171,24 +172,6 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"{(int)LegacyEventType.Break},{b.StartTime},{b.EndTime}")); } - private struct LegacyControlPointProperties - { - internal double SliderVelocity { get; set; } - internal int TimingSignature { get; init; } - internal int SampleBank { get; init; } - internal int CustomSampleBank { get; init; } - internal int SampleVolume { get; init; } - internal LegacyEffectFlags EffectFlags { get; init; } - - internal bool IsRedundant(LegacyControlPointProperties other) => - SliderVelocity == other.SliderVelocity && - TimingSignature == other.TimingSignature && - SampleBank == other.SampleBank && - CustomSampleBank == other.CustomSampleBank && - SampleVolume == other.SampleVolume && - EffectFlags == other.EffectFlags; - } - private void handleControlPoints(TextWriter writer) { var legacyControlPoints = new LegacyControlPointInfo(); @@ -243,11 +226,10 @@ namespace osu.Game.Beatmaps.Formats LegacyControlPointProperties getLegacyControlPointProperties(ControlPointGroup group, bool updateSampleBank) { - double time = group.Time; - var timingPoint = legacyControlPoints.TimingPointAt(time); - var difficultyPoint = legacyControlPoints.DifficultyPointAt(time); - var samplePoint = legacyControlPoints.SamplePointAt(time); - var effectPoint = legacyControlPoints.EffectPointAt(time); + var timingPoint = legacyControlPoints.TimingPointAt(group.Time); + var difficultyPoint = legacyControlPoints.DifficultyPointAt(group.Time); + var samplePoint = legacyControlPoints.SamplePointAt(group.Time); + var effectPoint = legacyControlPoints.EffectPointAt(group.Time); // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty)); @@ -628,5 +610,23 @@ namespace osu.Game.Beatmaps.Formats return 0; } + + private struct LegacyControlPointProperties + { + internal double SliderVelocity { get; set; } + internal int TimingSignature { get; init; } + internal int SampleBank { get; init; } + internal int CustomSampleBank { get; init; } + internal int SampleVolume { get; init; } + internal LegacyEffectFlags EffectFlags { get; init; } + + internal bool IsRedundant(LegacyControlPointProperties other) => + SliderVelocity == other.SliderVelocity && + TimingSignature == other.TimingSignature && + SampleBank == other.SampleBank && + CustomSampleBank == other.CustomSampleBank && + SampleVolume == other.SampleVolume && + EffectFlags == other.EffectFlags; + } } } From 384693a431757767d27594ef8906cd3d1ace0861 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 14:30:57 +0900 Subject: [PATCH 0682/1400] Fix test failure in `MultiplayerMatchSongSelect` due to multiple overlays present https://github.com/ppy/osu/actions/runs/4868337922/jobs/8681736995?pr=23308. --- .../Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index c0b6a0beab..9b130071cc 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -98,6 +98,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep($"select {requiredMod.ReadableName()} as required", () => songSelect.Mods.Value = new[] { (Mod)Activator.CreateInstance(requiredMod) }); AddAssert("freemods empty", () => songSelect.FreeMods.Value.Count == 0); + + // A previous test's mod overlay could still be fading out. + AddUntilStep("wait for only one freemod overlay", () => this.ChildrenOfType().Count() == 1); + assertHasFreeModButton(allowedMod, false); assertHasFreeModButton(requiredMod, false); } From a3efae36907fc596061ffadf7e552d6c078c360a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 14:33:30 +0900 Subject: [PATCH 0683/1400] Fix potentially incorrect thread access in `OsuTabControlCheckbox` https://github.com/ppy/osu/actions/runs/4868337922/jobs/8681736829. --- .../UserInterface/OsuTabControlCheckbox.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index fa58ae27f2..71bc18737f 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -49,11 +49,10 @@ namespace osu.Game.Graphics.UserInterface private const float transition_length = 500; private Sample sampleChecked; private Sample sampleUnchecked; + private readonly SpriteIcon icon; public OsuTabControlCheckbox() { - SpriteIcon icon; - AutoSizeAxes = Axes.Both; Children = new Drawable[] @@ -85,14 +84,6 @@ namespace osu.Game.Graphics.UserInterface Anchor = Anchor.BottomLeft, } }; - - Current.ValueChanged += selected => - { - icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; - text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium); - - updateFade(); - }; } [BackgroundDependencyLoader] @@ -103,6 +94,14 @@ namespace osu.Game.Graphics.UserInterface sampleChecked = audio.Samples.Get(@"UI/check-on"); sampleUnchecked = audio.Samples.Get(@"UI/check-off"); + + Current.ValueChanged += selected => + { + icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; + text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium); + + updateFade(); + }; } protected override bool OnHover(HoverEvent e) From bede1292de37f4be3270c2e86c215783e3ef52d8 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 2 May 2023 22:24:07 -0700 Subject: [PATCH 0684/1400] Fix overlay scroll back button not absorbing hover from behind --- osu.Game/Overlays/OverlayScrollContainer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 9752e04f44..ba7486a57f 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -185,6 +185,8 @@ namespace osu.Game.Overlays content.ScaleTo(1, 1000, Easing.OutElastic); base.OnMouseUp(e); } + + protected override bool OnHover(HoverEvent e) => true; } } } From 1c74f6e8ea60fe91335c95883bc8d434e51b07ac Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 2 May 2023 22:54:42 -0700 Subject: [PATCH 0685/1400] Fix regressed button hover fade in --- osu.Game/Overlays/OverlayScrollContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index ba7486a57f..2a615f0e12 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -186,7 +186,11 @@ namespace osu.Game.Overlays base.OnMouseUp(e); } - protected override bool OnHover(HoverEvent e) => true; + protected override bool OnHover(HoverEvent e) + { + base.OnHover(e); + return true; + } } } } From 453143813fafc7a62736ab473a883a194d7e643d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 14:57:31 +0900 Subject: [PATCH 0686/1400] Extend input handling of osu! logo to full border area This is the easiest way to make this happen. It does mean the pink area is being drawn behind the white border, but I haven't found a scenario where this is noticeable. Closes #4217. --- osu.Game/Screens/Menu/OsuLogo.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 9430a1cda8..33dc23d88d 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -35,6 +35,12 @@ namespace osu.Game.Screens.Menu private const double transition_length = 300; + /// + /// The osu! logo sprite has a shadow included in its texture. + /// This adjustment vector is used to match the precise edge of the border of the logo. + /// + private static readonly Vector2 scale_adjust = new Vector2(0.96f); + private readonly Sprite logo; private readonly CircularContainer logoContainer; private readonly Container logoBounceContainer; @@ -150,7 +156,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Anchor = Anchor.Centre, Alpha = visualizer_default_alpha, - Size = new Vector2(0.96f) + Size = scale_adjust }, new Container { @@ -162,7 +168,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.88f), + Scale = scale_adjust, Masking = true, Children = new Drawable[] { From 6a59ded1bad631e2b3ce508b4050b0a937126037 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 15:18:37 +0900 Subject: [PATCH 0687/1400] Move logic to `Update` instead --- .../Objects/Drawables/DrawableHoldNote.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index b2c84b140b..20daab2447 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -219,6 +219,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Time.Current < releaseTime) releaseTime = null; + if (Time.Current < HoldStartTime) + endHold(); + // Pad the full size container so its contents (i.e. the masking container) reach under the tail. // This is required for the tail to not be masked away, since it lies outside the bounds of the hold note. sizingContainer.Padding = new MarginPadding @@ -322,15 +325,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (e.Action != Action.Value) return; - // do not run any of this logic when rewinding, as it inverts order of presses/releases. - if (Time.Elapsed < 0) - { - // Except for the IsHitting state, as this handles animations that need to be reapplied - // after rewind. - isHitting.Value = false; - return; - } - // Make sure a hold was started if (HoldStartTime == null) return; From 5f781bd6de1ef4c2e067eec5e985722500b7b192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 May 2023 09:26:54 +0200 Subject: [PATCH 0688/1400] Move callback to `LoadComplete()` Is the more correct place for `BindValueChanged()` callbacks. --- osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 71bc18737f..8eb6b792c6 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -94,14 +94,19 @@ namespace osu.Game.Graphics.UserInterface sampleChecked = audio.Samples.Get(@"UI/check-on"); sampleUnchecked = audio.Samples.Get(@"UI/check-off"); + } - Current.ValueChanged += selected => + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium); updateFade(); - }; + }); } protected override bool OnHover(HoverEvent e) From de1b28bcb284e9e07b4b36eb9a3513a5f7228732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 May 2023 09:27:23 +0200 Subject: [PATCH 0689/1400] Fix incorrect initial state of checkbox This only ever barely used to work without the `(..., true)` in `master` because of haphazard operation ordering. --- osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 8eb6b792c6..c9e1f74917 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -106,7 +106,7 @@ namespace osu.Game.Graphics.UserInterface text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium); updateFade(); - }); + }, true); } protected override bool OnHover(HoverEvent e) From 5757eb75299234da77876e70de818ae53d4e8728 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:20:12 +0900 Subject: [PATCH 0690/1400] Update a few more instances of `0.96f` scale constants --- osu.Game/Screens/Menu/IntroWelcome.cs | 2 +- osu.Game/Screens/Menu/OsuLogo.cs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Menu/IntroWelcome.cs b/osu.Game/Screens/Menu/IntroWelcome.cs index da44161507..2a6ebecb92 100644 --- a/osu.Game/Screens/Menu/IntroWelcome.cs +++ b/osu.Game/Screens/Menu/IntroWelcome.cs @@ -131,7 +131,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.Centre, Origin = Anchor.Centre, Colour = Color4.DarkBlue, - Size = new Vector2(0.96f) + Size = OsuLogo.SCALE_ADJUST, }, new Circle { diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 33dc23d88d..277b8bf888 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Menu /// The osu! logo sprite has a shadow included in its texture. /// This adjustment vector is used to match the precise edge of the border of the logo. /// - private static readonly Vector2 scale_adjust = new Vector2(0.96f); + public static readonly Vector2 SCALE_ADJUST = new Vector2(0.96f); private readonly Sprite logo; private readonly CircularContainer logoContainer; @@ -156,7 +156,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Anchor = Anchor.Centre, Alpha = visualizer_default_alpha, - Size = scale_adjust + Size = SCALE_ADJUST }, new Container { @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Scale = scale_adjust, + Scale = SCALE_ADJUST, Masking = true, Children = new Drawable[] { @@ -412,7 +412,7 @@ namespace osu.Game.Screens.Menu public void Impact() { impactContainer.FadeOutFromOne(250, Easing.In); - impactContainer.ScaleTo(0.96f); + impactContainer.ScaleTo(SCALE_ADJUST); impactContainer.ScaleTo(1.12f, 250); } From cd31cff8cdd4c26c64183f640178b604e638682e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:41:29 +0900 Subject: [PATCH 0691/1400] Fix event subscriptions not being cleaned up in `DrawableCarouselBeatmap` The handling of cleanup is performed only the `Item_Set` method. This was already correctly called for `DrawableCarouselBeatmapSet`, but not for the class in question here. This would cause runaway memory usage at song select when opening many beatmaps to show their difficulties. For simplicity, we don't yet pool these (and generate the drawables each time a set is opened) which isn't great but likely will be improved upon when we update the visual / filtering of the carousel. But this simplicity caused the memory usage to blow out until exiting back to the main menu when cleanup would finally occur. --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index f08d14720b..55d442215b 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -250,6 +250,9 @@ namespace osu.Game.Screens.Select.Carousel { base.Dispose(isDisposing); starDifficultyCancellationSource?.Cancel(); + + // This is important to clean up event subscriptions. + Item = null; } } } From 444f66b0eefdce3c4defaf46fffa927a886f6f51 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:45:09 +0900 Subject: [PATCH 0692/1400] Move to base class for added safety --- .../Screens/Select/Carousel/DrawableCarouselBeatmap.cs | 3 --- .../Screens/Select/Carousel/DrawableCarouselItem.cs | 10 +++++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 55d442215b..f08d14720b 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -250,9 +250,6 @@ namespace osu.Game.Screens.Select.Carousel { base.Dispose(isDisposing); starDifficultyCancellationSource?.Cancel(); - - // This is important to clean up event subscriptions. - Item = null; } } } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index f065926eb7..0c3de5848b 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select.Carousel item = value; - if (IsLoaded) + if (IsLoaded && !IsDisposed) UpdateItem(); } } @@ -165,5 +165,13 @@ namespace osu.Game.Screens.Select.Carousel Item.State.Value = CarouselItemState.Selected; return true; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + // This is important to clean up event subscriptions. + Item = null; + } } } From b28d7b1a928cbda8ee6da8a682683ea9dbd7376f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:51:02 +0900 Subject: [PATCH 0693/1400] Fix non-block namespace --- .../Online/API/Requests/ChatReportRequest.cs | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/osu.Game/Online/API/Requests/ChatReportRequest.cs b/osu.Game/Online/API/Requests/ChatReportRequest.cs index 01cb455183..85e5559e01 100644 --- a/osu.Game/Online/API/Requests/ChatReportRequest.cs +++ b/osu.Game/Online/API/Requests/ChatReportRequest.cs @@ -5,33 +5,34 @@ using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Overlays.Chat; -namespace osu.Game.Online.API.Requests; - -public class ChatReportRequest : APIRequest +namespace osu.Game.Online.API.Requests { - public readonly long? MessageId; - public readonly ChatReportReason Reason; - public readonly string Comment; - - public ChatReportRequest(long? id, ChatReportReason reason, string comment) + public class ChatReportRequest : APIRequest { - MessageId = id; - Reason = reason; - Comment = comment; + public readonly long? MessageId; + public readonly ChatReportReason Reason; + public readonly string Comment; + + public ChatReportRequest(long? id, ChatReportReason reason, string comment) + { + MessageId = id; + Reason = reason; + Comment = comment; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Post; + + req.AddParameter(@"reportable_type", @"message"); + req.AddParameter(@"reportable_id", $"{MessageId}"); + req.AddParameter(@"reason", Reason.ToString()); + req.AddParameter(@"comments", Comment); + + return req; + } + + protected override string Target => @"reports"; } - - protected override WebRequest CreateWebRequest() - { - var req = base.CreateWebRequest(); - req.Method = HttpMethod.Post; - - req.AddParameter(@"reportable_type", @"message"); - req.AddParameter(@"reportable_id", $"{MessageId}"); - req.AddParameter(@"reason", Reason.ToString()); - req.AddParameter(@"comments", Comment); - - return req; - } - - protected override string Target => @"reports"; } From b932e4d98690f9935aa1d50df4dd8757f9380928 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:53:22 +0900 Subject: [PATCH 0694/1400] Rename `DrawableUsername` to `DrawableChatUsername` and only pass message ID --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 2 +- osu.Game/Overlays/Chat/ChatLine.cs | 4 ++-- .../{DrawableUsername.cs => DrawableChatUsername.cs} | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) rename osu.Game/Overlays/Chat/{DrawableUsername.cs => DrawableChatUsername.cs} (96%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index faf48ef854..e9e2cc63c2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -616,7 +616,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); + AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); AddStep("Set report reason to other", () => { diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 0e69501ae9..dca34128d1 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -55,7 +55,7 @@ namespace osu.Game.Overlays.Chat private readonly OsuSpriteText drawableTimestamp; - private readonly DrawableUsername drawableUsername; + private readonly DrawableChatUsername drawableUsername; private readonly LinkFlowContainer drawableContentFlow; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername = new DrawableUsername(message) + drawableUsername = new DrawableChatUsername(message.Sender, message.Id) { Width = UsernameWidth, FontSize = FontSize, diff --git a/osu.Game/Overlays/Chat/DrawableUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs similarity index 96% rename from osu.Game/Overlays/Chat/DrawableUsername.cs rename to osu.Game/Overlays/Chat/DrawableChatUsername.cs index 25967003e9..4ba5c9769a 100644 --- a/osu.Game/Overlays/Chat/DrawableUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -31,7 +31,7 @@ using ChatStrings = osu.Game.Localisation.ChatStrings; namespace osu.Game.Overlays.Chat { - public partial class DrawableUsername : OsuClickableContainer, IHasContextMenu, IHasPopover + public partial class DrawableChatUsername : OsuClickableContainer, IHasContextMenu, IHasPopover { public Color4 AccentColour { get; } @@ -73,15 +73,15 @@ namespace osu.Game.Overlays.Chat private Bindable? currentChannel { get; set; } private readonly APIUser user; - private readonly Message message; + private readonly long? messageId; private readonly OsuSpriteText drawableText; private readonly Drawable colouredDrawable; - public DrawableUsername(Message message) + public DrawableChatUsername(APIUser user, long? messageId) { - this.message = message; - user = message.Sender; + this.user = user; + this.messageId = messageId; Action = openUserProfile; @@ -182,7 +182,7 @@ namespace osu.Game.Overlays.Chat private void report(ChatReportReason reason, string comments) { - var request = new ChatReportRequest(message.Id, reason, comments); + var request = new ChatReportRequest(messageId, reason, comments); request.Failure += _ => Schedule(() => { From be15d07b1734b853d1424c996b3e0de10a94c213 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 May 2023 18:59:39 +0900 Subject: [PATCH 0695/1400] Tidy up various implementation details --- osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs | 7 ++++--- osu.Game/Overlays/Chat/DrawableChatUsername.cs | 10 +++++----- osu.Game/Overlays/Comments/CommentReportButton.cs | 10 +++++----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs index 46006402ad..a5c60bb9e6 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs @@ -24,11 +24,12 @@ namespace osu.Game.Graphics.UserInterfaceV2 private OsuEnumDropdown reasonDropdown = null!; private OsuTextBox commentsTextBox = null!; private RoundedButton submitButton = null!; - public LocalisableString Header; + + private readonly LocalisableString header; protected ReportPopover(LocalisableString headerString) { - Header = headerString; + header = headerString; } [BackgroundDependencyLoader] @@ -53,7 +54,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Text = Header, + Text = header, Font = OsuFont.Torus.With(size: 25), Margin = new MarginPadding { Bottom = 10 } }, diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 4ba5c9769a..b3bbc74be7 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -180,6 +180,11 @@ namespace osu.Game.Overlays.Chat } } + public Popover GetPopover() => new ReportChatPopover(user) + { + Action = report + }; + private void report(ChatReportReason reason, string comments) { var request = new ChatReportRequest(messageId, reason, comments); @@ -260,10 +265,5 @@ namespace osu.Game.Overlays.Chat Color4Extensions.FromHex("812a96"), Color4Extensions.FromHex("992861"), }; - - public Popover GetPopover() => new ReportChatPopover(user) - { - Action = report - }; } } diff --git a/osu.Game/Overlays/Comments/CommentReportButton.cs b/osu.Game/Overlays/Comments/CommentReportButton.cs index ba5319094b..e4d4d671da 100644 --- a/osu.Game/Overlays/Comments/CommentReportButton.cs +++ b/osu.Game/Overlays/Comments/CommentReportButton.cs @@ -57,6 +57,11 @@ namespace osu.Game.Overlays.Comments link.AddLink(ReportStrings.CommentButton.ToLower(), this.ShowPopover); } + public Popover GetPopover() => new ReportCommentPopover(comment) + { + Action = report + }; + private void report(CommentReportReason reason, string comments) { var request = new CommentReportRequest(comment.Id, reason, comments); @@ -83,10 +88,5 @@ namespace osu.Game.Overlays.Comments api.Queue(request); } - - public Popover GetPopover() => new ReportCommentPopover(comment) - { - Action = report - }; } } From f0d35eb12be0262e892b4fc614128860007107c7 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 3 May 2023 13:12:11 +0300 Subject: [PATCH 0696/1400] Update testing --- .../TestSceneMultiplayerMatchSongSelect.cs | 2 +- .../TestSceneMultiplayerMatchSubScreen.cs | 2 +- .../Visual/UserInterface/TestSceneModColumn.cs | 12 ++++++------ .../UserInterface/TestSceneModSelectOverlay.cs | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index c0b6a0beab..dd1400b36e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.Multiplayer () => this.ChildrenOfType() .Single() .ChildrenOfType() - .Where(panel => !panel.Filtered.Value) + .Where(panel => panel.MatchingFilter) .All(b => b.Mod.GetType() != type)); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 8816787ceb..8fd16fb723 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -203,7 +203,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("mod select contains only double time mod", () => this.ChildrenOfType().Single().UserModsSelectOverlay .ChildrenOfType() - .SingleOrDefault(panel => !panel.Filtered.Value)?.Mod is OsuModDoubleTime); + .SingleOrDefault(panel => panel.MatchingFilter)?.Mod is OsuModDoubleTime); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 3f5676ee24..ec6084aa8e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -106,26 +106,26 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => !panel.Filtered.Value) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.MatchingFilter) == 2); clickToggle(); AddUntilStep("wait for animation", () => !column.SelectionAnimationRunning); - AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => !panel.Filtered.Value)); + AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => panel.MatchingFilter)); AddStep("unset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => !panel.Filtered.Value)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.MatchingFilter)); AddAssert("checkbox not selected", () => !column.ChildrenOfType().Single().Current.Value); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => !panel.Filtered.Value) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.MatchingFilter) == 2); AddAssert("checkbox selected", () => column.ChildrenOfType().Single().Current.Value); AddStep("filter out everything", () => setFilter(_ => false)); - AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => panel.Filtered.Value)); + AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => !panel.MatchingFilter)); AddUntilStep("checkbox hidden", () => !column.ChildrenOfType().Single().IsPresent); AddStep("inset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => !panel.Filtered.Value)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.MatchingFilter)); AddUntilStep("checkbox visible", () => column.ChildrenOfType().Single().IsPresent); void clickToggle() => AddStep("click toggle", () => diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5ccaebd721..9c6ec653e9 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -431,15 +431,15 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); changeRuleset(0); - AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => !panel.Filtered.Value)); + AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.MatchingFilter)); AddStep("make double time invalid", () => modSelectOverlay.IsValidMod = m => !(m is OsuModDoubleTime)); - AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => panel.Filtered.Value)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value)); + AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => !panel.MatchingFilter)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => panel.MatchingFilter)); AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = _ => true); - AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => !panel.Filtered.Value)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => !panel.Filtered.Value)); + AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.MatchingFilter)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => panel.MatchingFilter)); } [Test] @@ -465,7 +465,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set ruleset", () => Ruleset.Value = testRuleset.RulesetInfo); waitForColumnLoad(); - AddAssert("unimplemented mod panel is filtered", () => getPanelForMod(typeof(TestUnimplementedMod)).Filtered.Value); + AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).MatchingFilter); } [Test] From 152d2678d52c74d562c1c959da5502c960664ed1 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 3 May 2023 14:00:46 +0300 Subject: [PATCH 0697/1400] Fix `ModSelectColumn` completely disappear from `ModSelectOverlay` --- osu.Game/Overlays/Mods/ModSearch.cs | 10 -------- osu.Game/Overlays/Mods/ModSearchContainer.cs | 25 ++++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectColumn.cs | 6 ++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 4 files changed, 30 insertions(+), 15 deletions(-) delete mode 100644 osu.Game/Overlays/Mods/ModSearch.cs create mode 100644 osu.Game/Overlays/Mods/ModSearchContainer.cs diff --git a/osu.Game/Overlays/Mods/ModSearch.cs b/osu.Game/Overlays/Mods/ModSearch.cs deleted file mode 100644 index 0a82d967af..0000000000 --- a/osu.Game/Overlays/Mods/ModSearch.cs +++ /dev/null @@ -1,10 +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.Framework.Graphics.Containers; - -namespace osu.Game.Overlays.Mods; - -public partial class ModSearch : Container -{ -} diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs new file mode 100644 index 0000000000..29cc7d8132 --- /dev/null +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Overlays.Mods; + +public partial class ModSearchContainer : SearchContainer +{ + /// + /// A string that should match the children + /// + public string ForcedSearchTerm + { + get => SearchTerm; + set + { + if (value == SearchTerm) + return; + + SearchTerm = value; + Update(); + } + } +} diff --git a/osu.Game/Overlays/Mods/ModSelectColumn.cs b/osu.Game/Overlays/Mods/ModSelectColumn.cs index 8bf3fd404f..c80eb8c09c 100644 --- a/osu.Game/Overlays/Mods/ModSelectColumn.cs +++ b/osu.Game/Overlays/Mods/ModSelectColumn.cs @@ -45,13 +45,13 @@ namespace osu.Game.Overlays.Mods public string SearchTerm { - set => ItemsFlow.SearchTerm = value; + set => ItemsFlow.ForcedSearchTerm = value; } protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => base.ReceivePositionalInputAtSubTree(screenSpacePos) && Active.Value; protected readonly Container ControlContainer; - protected readonly SearchContainer ItemsFlow; + protected readonly ModSearchContainer ItemsFlow; private readonly TextFlowContainer headerText; private readonly Box headerBackground; @@ -155,7 +155,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.Both, ClampExtension = 100, ScrollbarOverlapsContent = false, - Child = ItemsFlow = new SearchContainer + Child = ItemsFlow = new ModSearchContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 12e894cfba..9efcd24048 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.Mods private ShearedSearchTextBox searchTextBox = null!; private DifficultyMultiplierDisplay? multiplierDisplay; - private ModSearch? modSearch; + private ModSearchContainer? modSearch; protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -215,7 +215,7 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Margin = new MarginPadding { Horizontal = 100 }, - Child = modSearch = new ModSearch() + Child = modSearch = new ModSearchContainer() }); FooterContent.Child = footerButtonFlow = new FillFlowContainer From 25bf4e68ec32b5fa68f40280aed8246cefcd42e8 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 22:53:13 +0900 Subject: [PATCH 0698/1400] remove useless wait --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index e9e2cc63c2..041556a5a6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -631,7 +631,6 @@ namespace osu.Game.Tests.Visual.Online InputManager.Click(MouseButton.Left); }); - AddWaitStep("Wait", 3); AddAssert("Nothing happened", () => this.ChildrenOfType().Any()); AddStep("Set report data", () => { From 3a15783a3c53e610b86ff71c891df125d3651bb1 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 22:56:47 +0900 Subject: [PATCH 0699/1400] remove wait, use AddUntilStep --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index c4c5584c5e..55fe142d9f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -301,7 +301,6 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); @@ -357,8 +356,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddAssert("present mod not changed", () => + + AddUntilStep("present mod not changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); @@ -388,8 +387,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(popover.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddWaitStep("wait some", 3); - AddAssert("present mod is changed", () => + + AddUntilStep("present mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } From c609e6345cf6c3b41b57917fe1dac841b1be9a4c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:01:31 +0900 Subject: [PATCH 0700/1400] remove `Use Current Mods` menu item --- .../UserInterface/TestSceneModPresetColumn.cs | 44 ------------------- osu.Game/Overlays/Mods/ModPresetPanel.cs | 21 ++------- 2 files changed, 4 insertions(+), 61 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 55fe142d9f..0cbbe00311 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -392,50 +392,6 @@ namespace osu.Game.Tests.Visual.UserInterface new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } - [Test] - public void TestEditPresetModInContextMenu() - { - ModPresetColumn modPresetColumn = null!; - var mods = new Mod[] { new OsuModHidden() }; - - AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); - AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); - - AddStep("right click first panel", () => - { - var panel = this.ChildrenOfType().First(); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddAssert("No Use Current Mods", () => this.ChildrenOfType().Count() == 2); - - AddStep("select mods", () => SelectedMods.Value = mods); - AddStep("right click second panel", () => - { - var panel = this.ChildrenOfType().ElementAt(1); - InputManager.MoveMouseTo(panel); - InputManager.Click(MouseButton.Right); - }); - - AddUntilStep("wait for context menu", () => this.ChildrenOfType().Any()); - AddAssert("Have Use Current Mods", () => this.ChildrenOfType().Count() == 3); - AddStep("Click Use Current Mods", () => - { - var editItem = this.ChildrenOfType().ElementAt(1); - InputManager.MoveMouseTo(editItem); - InputManager.Click(MouseButton.Left); - }); - AddAssert("present mod is changed", () => - new HashSet(this.ChildrenOfType().ElementAt(1).Preset.Value.Mods).SetEquals(mods)); - } - private ICollection createTestPresets() => new[] { new ModPreset diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index d01981d18c..6999f2cede 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -90,24 +90,11 @@ namespace osu.Game.Overlays.Mods #region IHasContextMenu - public MenuItem[] ContextMenuItems + public MenuItem[] ContextMenuItems => new MenuItem[] { - get - { - var menu = new List - { - new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), - new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), - }; - - if (CheckCurrentModCanBeSave()) - { - menu.Insert(1, new OsuMenuItem("Use Current Mods", MenuItemType.Destructive, () => SaveCurrentMod())); - } - - return menu.ToArray(); - } - } + new OsuMenuItem(CommonStrings.ButtonsEdit, MenuItemType.Highlighted, this.ShowPopover), + new OsuMenuItem(CommonStrings.ButtonsDelete, MenuItemType.Destructive, () => dialogOverlay?.Push(new DeleteModPresetDialog(Preset))), + }; #endregion From aa5a026c676c0503f6110c0d4fa610b3669bc9fd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:14:24 +0900 Subject: [PATCH 0701/1400] remove local button handle --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 27 ++++++--------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 0e21260493..77980ea629 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -95,7 +95,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Use Current Mods", - Action = trySaveCurrentMod + Action = saveCurrentMod }, createButton = new ShearedButton { @@ -123,19 +123,17 @@ namespace osu.Game.Overlays.Mods createButton.LighterColour = colours.Orange0; createButton.TextColour = colourProvider.Background6; + useCurrentModButton.DarkerColour = colours.Blue1; + useCurrentModButton.LighterColour = colours.Blue0; + useCurrentModButton.TextColour = colourProvider.Background6; + selectedMods.BindValueChanged(_ => updateActiveState(), true); scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); } - private void trySaveCurrentMod() + private void saveCurrentMod() { - if (!checkCanBeSave()) - { - Body.Shake(); - return; - } - saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); @@ -144,18 +142,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - if (checkCanBeSave()) - { - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; - } - else - { - useCurrentModButton.DarkerColour = colours.Blue3; - useCurrentModButton.LighterColour = colours.Blue4; - useCurrentModButton.TextColour = colourProvider.Background2; - } + useCurrentModButton.Enabled.Value = checkCanBeSave(); } private bool checkCanBeSave() From f4b1264cc9859acd275e0f99bf68c2b6cd59306b Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:22:46 +0900 Subject: [PATCH 0702/1400] use button `Enable` status to ensure preset name is not null --- osu.Game/Overlays/Mods/AddPresetPopover.cs | 15 ++++++------- osu.Game/Overlays/Mods/EditPresetPopover.cs | 25 ++++++++++----------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Mods/AddPresetPopover.cs b/osu.Game/Overlays/Mods/AddPresetPopover.cs index 33d72ff383..6fd4231f2c 100644 --- a/osu.Game/Overlays/Mods/AddPresetPopover.cs +++ b/osu.Game/Overlays/Mods/AddPresetPopover.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = ModSelectOverlayStrings.AddPreset, - Action = tryCreatePreset + Action = createPreset } } }; @@ -89,16 +89,15 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); + + nameTextBox.Current.BindValueChanged(s => + { + createButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + }, true); } - private void tryCreatePreset() + private void createPreset() { - if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) - { - Body.Shake(); - return; - } - realm.Write(r => r.Add(new ModPreset { Name = nameTextBox.Current.Value, diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 77980ea629..451c1ec712 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; private readonly ShearedButton useCurrentModButton; - private readonly ShearedButton createButton; + private readonly ShearedButton editButton; private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; @@ -97,12 +97,12 @@ namespace osu.Game.Overlays.Mods Text = "Use Current Mods", Action = saveCurrentMod }, - createButton = new ShearedButton + editButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = tryEditPreset + Action = editPreset }, } } @@ -119,9 +119,9 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - createButton.DarkerColour = colours.Orange1; - createButton.LighterColour = colours.Orange0; - createButton.TextColour = colourProvider.Background6; + editButton.DarkerColour = colours.Orange1; + editButton.LighterColour = colours.Orange0; + editButton.TextColour = colourProvider.Background6; useCurrentModButton.DarkerColour = colours.Blue1; useCurrentModButton.LighterColour = colours.Blue0; @@ -130,6 +130,11 @@ namespace osu.Game.Overlays.Mods selectedMods.BindValueChanged(_ => updateActiveState(), true); scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + + nameTextBox.Current.BindValueChanged(s => + { + editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + }, true); } private void saveCurrentMod() @@ -165,14 +170,8 @@ namespace osu.Game.Overlays.Mods ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); } - private void tryEditPreset() + private void editPreset() { - if (string.IsNullOrWhiteSpace(nameTextBox.Current.Value)) - { - Body.Shake(); - return; - } - button.Preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; From debbd376bd6e8155612ea8a2b6e2fe1db2a9c884 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:24:14 +0900 Subject: [PATCH 0703/1400] move `scrollContent` update logic to `updateActiveState()` --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 451c1ec712..e96168d8ff 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -129,8 +129,6 @@ namespace osu.Game.Overlays.Mods selectedMods.BindValueChanged(_ => updateActiveState(), true); - scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - nameTextBox.Current.BindValueChanged(s => { editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -141,12 +139,12 @@ namespace osu.Game.Overlays.Mods { saveModAfterClosed = selectedMods.Value.ToList(); scrollContent.Clear(); - scrollContent.ChildrenEnumerable = saveModAfterClosed.Select(mod => new ModPresetRow(mod)); updateActiveState(); } private void updateActiveState() { + scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); useCurrentModButton.Enabled.Value = checkCanBeSave(); } From 967e801f9c77cc4b745fd32625c674fd708d25e9 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 3 May 2023 23:26:58 +0900 Subject: [PATCH 0704/1400] code inspect --- osu.Game/Overlays/Mods/AddPresetPopover.cs | 1 - osu.Game/Overlays/Mods/EditPresetPopover.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/AddPresetPopover.cs b/osu.Game/Overlays/Mods/AddPresetPopover.cs index 6fd4231f2c..d9e350e560 100644 --- a/osu.Game/Overlays/Mods/AddPresetPopover.cs +++ b/osu.Game/Overlays/Mods/AddPresetPopover.cs @@ -9,7 +9,6 @@ using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Database; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index e96168d8ff..7f7b9472a7 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -8,7 +8,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; From d1d4b54c640df278987ff8ba8ccad28519e59e44 Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 3 May 2023 18:31:35 +0200 Subject: [PATCH 0705/1400] Simplified --- osu.Game/OsuGameBase.cs | 46 +++++++++++++---------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e6d6deabe9..076c1213ad 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -625,40 +625,22 @@ namespace osu.Game return; } - var previouslySelectedCommonMods = new List(SelectedMods.Value.Count); - var convertedCommonMods = new List(SelectedMods.Value.Count); - - foreach (var mod in SelectedMods.Value) - { - var convertedMod = instance.CreateModFromAcronym(mod.Acronym); - - if (convertedMod == null) - continue; - - previouslySelectedCommonMods.Add(mod); - - convertedMod.CopyCommonSettings(mod); - convertedCommonMods.Add(convertedMod); - } - - if (!ModUtils.CheckValidForGameplay(convertedCommonMods, out var invalid)) - { - invalid.ForEach(mod => - { - int index = convertedCommonMods.IndexOf(mod); - convertedCommonMods.RemoveAt(index); - previouslySelectedCommonMods.RemoveAt(index); - }); - } - - if (!SelectedMods.Disabled) - // Select common mods to play the deselect samples for other mods - SelectedMods.Value = previouslySelectedCommonMods; - AvailableMods.Value = dict; - if (!SelectedMods.Disabled) - SelectedMods.Value = convertedCommonMods; + if (SelectedMods.Disabled) + return; + + var convertedMods = SelectedMods.Value.Select(mod => + { + var newMod = instance.CreateModFromAcronym(mod.Acronym); + newMod?.CopyCommonSettings(mod); + return newMod; + }).Where(newMod => newMod != null).ToList(); + + if (!ModUtils.CheckValidForGameplay(convertedMods, out var invalid)) + invalid.ForEach(newMod => convertedMods.Remove(newMod)); + + SelectedMods.Value = convertedMods; void revertRulesetChange() => Ruleset.Value = r.OldValue?.Available == true ? r.OldValue : RulesetStore.AvailableRulesets.First(); } From 27fabd99fbc996705e5f700ebdc96f028c035872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 May 2023 19:21:16 +0200 Subject: [PATCH 0706/1400] Rename variables for legibility Having `typedComponents` and `typeComponents` next to each other is asking for trouble. --- .../Overlays/SkinEditor/SkinEditorChangeHandler.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index 3dddf639cc..f3c5bc9ce2 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -61,16 +61,16 @@ namespace osu.Game.Overlays.SkinEditor ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); // Store components based on type for later lookup - var typedComponents = new Dictionary>(); + var componentsPerTypeLookup = new Dictionary>(); foreach (ISerialisableDrawable component in targetComponents) { Type lookup = component.GetType(); - if (!typedComponents.TryGetValue(lookup, out Queue? typeComponents)) - typedComponents.Add(lookup, typeComponents = new Queue()); + if (!componentsPerTypeLookup.TryGetValue(lookup, out Queue? componentsOfSameType)) + componentsPerTypeLookup.Add(lookup, componentsOfSameType = new Queue()); - typeComponents.Enqueue((Drawable)component); + componentsOfSameType.Enqueue((Drawable)component); } // Remove all components @@ -81,13 +81,13 @@ namespace osu.Game.Overlays.SkinEditor { Type lookup = skinnableInfo.Type; - if (!typedComponents.TryGetValue(lookup, out Queue? typeComponents)) + if (!componentsPerTypeLookup.TryGetValue(lookup, out Queue? componentsOfSameType)) { firstTarget.Add((ISerialisableDrawable)skinnableInfo.CreateInstance()); continue; } - if (typeComponents.TryDequeue(out Drawable? component)) + if (componentsOfSameType.TryDequeue(out Drawable? component)) { // Re-use unused component component.ApplySerialisedInfo(skinnableInfo); @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.SkinEditor firstTarget.Add((ISerialisableDrawable)component); } - foreach ((Type _, Queue typeComponents) in typedComponents) + foreach ((Type _, Queue typeComponents) in componentsPerTypeLookup) { // Dispose extra components foreach (var component in typeComponents) From 1d4d31e35c8b85eb5104734a25b971ec8c827ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 May 2023 19:22:52 +0200 Subject: [PATCH 0707/1400] Trim comments Leaving only the ones that add anything useful and do not restate the code verbatim. --- osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs index f3c5bc9ce2..673ba873c4 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorChangeHandler.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.SkinEditor SerialisedDrawableInfo[] skinnableInfos = deserializedContent.ToArray(); ISerialisableDrawable[] targetComponents = firstTarget.Components.ToArray(); - // Store components based on type for later lookup + // Store components based on type for later reuse var componentsPerTypeLookup = new Dictionary>(); foreach (ISerialisableDrawable component in targetComponents) @@ -73,7 +73,6 @@ namespace osu.Game.Overlays.SkinEditor componentsOfSameType.Enqueue((Drawable)component); } - // Remove all components for (int i = targetComponents.Length - 1; i >= 0; i--) firstTarget.Remove(targetComponents[i], false); @@ -87,23 +86,22 @@ namespace osu.Game.Overlays.SkinEditor continue; } + // Wherever possible, attempt to reuse existing component instances. if (componentsOfSameType.TryDequeue(out Drawable? component)) { - // Re-use unused component component.ApplySerialisedInfo(skinnableInfo); } else { - // Create new one component = skinnableInfo.CreateInstance(); } firstTarget.Add((ISerialisableDrawable)component); } + // Dispose components which were not reused. foreach ((Type _, Queue typeComponents) in componentsPerTypeLookup) { - // Dispose extra components foreach (var component in typeComponents) component.Dispose(); } From 0a584f065235d3317067b9ed2860a686fe419122 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:07:09 +0900 Subject: [PATCH 0708/1400] Simplify check logic and improve variable naming --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 7f7b9472a7..9015218910 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -29,7 +29,8 @@ namespace osu.Game.Overlays.Mods private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; - private List saveModAfterClosed = new List(); + + private HashSet? newMods; [Resolved] private Bindable> selectedMods { get; set; } = null!; @@ -136,7 +137,7 @@ namespace osu.Game.Overlays.Mods private void saveCurrentMod() { - saveModAfterClosed = selectedMods.Value.ToList(); + newMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); updateActiveState(); } @@ -144,18 +145,16 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - useCurrentModButton.Enabled.Value = checkCanBeSave(); + useCurrentModButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } - private bool checkCanBeSave() + private bool checkSelectedModsDiffersFromSaved() { if (!selectedMods.Value.Any()) return false; - if (saveModAfterClosed.Any()) - { - return !new HashSet(saveModAfterClosed).SetEquals(selectedMods.Value); - } + if (newMods?.SetEquals(selectedMods.Value) == false) + return true; return button.CheckCurrentModCanBeSave(); } @@ -174,10 +173,8 @@ namespace osu.Game.Overlays.Mods s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - if (saveModAfterClosed.Any()) - { - s.Mods = saveModAfterClosed; - } + if (newMods != null) + s.Mods = newMods; }); this.HidePopover(); From b7abab6d8aff61e2e79c17f7fd367999f72857de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:10:05 +0900 Subject: [PATCH 0709/1400] More variable improvements --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 9015218910..91beea8e38 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -24,8 +24,8 @@ namespace osu.Game.Overlays.Mods private readonly LabelledTextBox nameTextBox; private readonly LabelledTextBox descriptionTextBox; - private readonly ShearedButton useCurrentModButton; - private readonly ShearedButton editButton; + private readonly ShearedButton useCurrentModsButton; + private readonly ShearedButton saveButton; private readonly FillFlowContainer scrollContent; private readonly ModPreset preset; @@ -90,19 +90,19 @@ namespace osu.Game.Overlays.Mods Spacing = new Vector2(7), Children = new Drawable[] { - useCurrentModButton = new ShearedButton + useCurrentModsButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Use Current Mods", - Action = saveCurrentMod + Action = useCurrentMods }, - editButton = new ShearedButton + saveButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = editPreset + Action = save }, } } @@ -119,23 +119,23 @@ namespace osu.Game.Overlays.Mods nameTextBox.Current.Value = preset.Name; descriptionTextBox.Current.Value = preset.Description; - editButton.DarkerColour = colours.Orange1; - editButton.LighterColour = colours.Orange0; - editButton.TextColour = colourProvider.Background6; + saveButton.DarkerColour = colours.Orange1; + saveButton.LighterColour = colours.Orange0; + saveButton.TextColour = colourProvider.Background6; - useCurrentModButton.DarkerColour = colours.Blue1; - useCurrentModButton.LighterColour = colours.Blue0; - useCurrentModButton.TextColour = colourProvider.Background6; + useCurrentModsButton.DarkerColour = colours.Blue1; + useCurrentModsButton.LighterColour = colours.Blue0; + useCurrentModsButton.TextColour = colourProvider.Background6; selectedMods.BindValueChanged(_ => updateActiveState(), true); nameTextBox.Current.BindValueChanged(s => { - editButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); + saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); }, true); } - private void saveCurrentMod() + private void useCurrentMods() { newMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); - useCurrentModButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); + useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } private bool checkSelectedModsDiffersFromSaved() @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Mods ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(nameTextBox)); } - private void editPreset() + private void save() { button.Preset.PerformWrite(s => { From be995f1359e19de4d9573fe1ad76645400c0949b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:11:19 +0900 Subject: [PATCH 0710/1400] Add localisation support for new button string --- osu.Game/Localisation/ModSelectOverlayStrings.cs | 5 +++++ osu.Game/Overlays/Mods/EditPresetPopover.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Localisation/ModSelectOverlayStrings.cs b/osu.Game/Localisation/ModSelectOverlayStrings.cs index d6a01c4794..f11c52ee20 100644 --- a/osu.Game/Localisation/ModSelectOverlayStrings.cs +++ b/osu.Game/Localisation/ModSelectOverlayStrings.cs @@ -34,6 +34,11 @@ namespace osu.Game.Localisation /// public static LocalisableString AddPreset => new TranslatableString(getKey(@"add_preset"), @"Add preset"); + /// + /// "Use current mods" + /// + public static LocalisableString UseCurrentMods => new TranslatableString(getKey(@"use_current_mods"), @"Use current mods"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 91beea8e38..b826bdf944 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -94,7 +94,7 @@ namespace osu.Game.Overlays.Mods { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Text = "Use Current Mods", + Text = ModSelectOverlayStrings.UseCurrentMods, Action = useCurrentMods }, saveButton = new ShearedButton From 99d2616c34d51b8e4027543f01b73a8efe499475 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:14:51 +0900 Subject: [PATCH 0711/1400] Move drawable construction to `load` for simplicity --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 58 ++++++++++----------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index b826bdf944..f02c200654 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -20,13 +20,13 @@ namespace osu.Game.Overlays.Mods { internal partial class EditPresetPopover : OsuPopover { - private readonly ModPresetPanel button; + private readonly ModPresetPanel presetPanel; - private readonly LabelledTextBox nameTextBox; - private readonly LabelledTextBox descriptionTextBox; - private readonly ShearedButton useCurrentModsButton; - private readonly ShearedButton saveButton; - private readonly FillFlowContainer scrollContent; + private LabelledTextBox nameTextBox = null!; + private LabelledTextBox descriptionTextBox = null!; + private ShearedButton useCurrentModsButton = null!; + private ShearedButton saveButton = null!; + private FillFlowContainer scrollContent = null!; private readonly ModPreset preset; @@ -41,11 +41,15 @@ namespace osu.Game.Overlays.Mods [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public EditPresetPopover(ModPresetPanel modPresetPanel) + public EditPresetPopover(ModPresetPanel presetPanel) { - button = modPresetPanel; - preset = button.Preset.Value; + this.presetPanel = presetPanel; + preset = presetPanel.Preset.Value; + } + [BackgroundDependencyLoader] + private void load() + { Child = new FillFlowContainer { Width = 300, @@ -59,14 +63,16 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Label = CommonStrings.Name, - TabbableContentContainer = this + TabbableContentContainer = this, + Current = { Value = preset.Name }, }, descriptionTextBox = new LabelledTextBox { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Label = CommonStrings.Description, - TabbableContentContainer = this + TabbableContentContainer = this, + Current = { Value = preset.Description }, }, new OsuScrollContainer { @@ -95,40 +101,30 @@ namespace osu.Game.Overlays.Mods Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = ModSelectOverlayStrings.UseCurrentMods, - Action = useCurrentMods + DarkerColour = colours.Blue1, + LighterColour = colours.Blue0, + TextColour = colourProvider.Background6, + Action = useCurrentMods, }, saveButton = new ShearedButton { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = Resources.Localisation.Web.CommonStrings.ButtonsSave, - Action = save + DarkerColour = colours.Orange1, + LighterColour = colours.Orange0, + TextColour = colourProvider.Background6, + Action = save, }, } } } }; - } - [BackgroundDependencyLoader] - private void load() - { Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; - nameTextBox.Current.Value = preset.Name; - descriptionTextBox.Current.Value = preset.Description; - - saveButton.DarkerColour = colours.Orange1; - saveButton.LighterColour = colours.Orange0; - saveButton.TextColour = colourProvider.Background6; - - useCurrentModsButton.DarkerColour = colours.Blue1; - useCurrentModsButton.LighterColour = colours.Blue0; - useCurrentModsButton.TextColour = colourProvider.Background6; - selectedMods.BindValueChanged(_ => updateActiveState(), true); - nameTextBox.Current.BindValueChanged(s => { saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -156,7 +152,7 @@ namespace osu.Game.Overlays.Mods if (newMods?.SetEquals(selectedMods.Value) == false) return true; - return button.CheckCurrentModCanBeSave(); + return presetPanel.CheckCurrentModCanBeSave(); } protected override void LoadComplete() @@ -168,7 +164,7 @@ namespace osu.Game.Overlays.Mods private void save() { - button.Preset.PerformWrite(s => + presetPanel.Preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; From b12d139317b55d47046eb0eaaf50756aaf07fb67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:16:52 +0900 Subject: [PATCH 0712/1400] Remove dead code --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 6999f2cede..3f5a764ab1 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,18 +98,6 @@ namespace osu.Game.Overlays.Mods #endregion - public bool SaveCurrentMod() - { - if (!CheckCurrentModCanBeSave()) - return false; - - Preset.PerformWrite(s => - { - s.Mods = selectedMods.Value.ToArray(); - }); - return true; - } - public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); protected override void Dispose(bool isDisposing) From 49fb5da1a237c30768f753d98d793733750bea5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:19:09 +0900 Subject: [PATCH 0713/1400] Stop passing preset panel to popover --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 23 ++++++++------------- osu.Game/Overlays/Mods/ModPresetPanel.cs | 4 +--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index f02c200654..3f5eca8ad0 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -20,15 +21,13 @@ namespace osu.Game.Overlays.Mods { internal partial class EditPresetPopover : OsuPopover { - private readonly ModPresetPanel presetPanel; - private LabelledTextBox nameTextBox = null!; private LabelledTextBox descriptionTextBox = null!; private ShearedButton useCurrentModsButton = null!; private ShearedButton saveButton = null!; private FillFlowContainer scrollContent = null!; - private readonly ModPreset preset; + private readonly Live preset; private HashSet? newMods; @@ -41,10 +40,9 @@ namespace osu.Game.Overlays.Mods [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public EditPresetPopover(ModPresetPanel presetPanel) + public EditPresetPopover(Live preset) { - this.presetPanel = presetPanel; - preset = presetPanel.Preset.Value; + this.preset = preset; } [BackgroundDependencyLoader] @@ -64,7 +62,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopCentre, Label = CommonStrings.Name, TabbableContentContainer = this, - Current = { Value = preset.Name }, + Current = { Value = preset.PerformRead(p => p.Name) }, }, descriptionTextBox = new LabelledTextBox { @@ -72,7 +70,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopCentre, Label = CommonStrings.Description, TabbableContentContainer = this, - Current = { Value = preset.Description }, + Current = { Value = preset.PerformRead(p => p.Description) }, }, new OsuScrollContainer { @@ -140,7 +138,7 @@ namespace osu.Game.Overlays.Mods private void updateActiveState() { - scrollContent.ChildrenEnumerable = preset.Mods.Select(mod => new ModPresetRow(mod)); + scrollContent.ChildrenEnumerable = preset.PerformRead(p => p.Mods.Select(mod => new ModPresetRow(mod))); useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } @@ -149,10 +147,7 @@ namespace osu.Game.Overlays.Mods if (!selectedMods.Value.Any()) return false; - if (newMods?.SetEquals(selectedMods.Value) == false) - return true; - - return presetPanel.CheckCurrentModCanBeSave(); + return newMods?.SetEquals(selectedMods.Value) == false; } protected override void LoadComplete() @@ -164,7 +159,7 @@ namespace osu.Game.Overlays.Mods private void save() { - presetPanel.Preset.PerformWrite(s => + preset.PerformWrite(s => { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 3f5a764ab1..8bcb5e4e4e 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -98,8 +98,6 @@ namespace osu.Game.Overlays.Mods #endregion - public bool CheckCurrentModCanBeSave() => (!Active.Value && selectedMods.Value.Any()); - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -107,6 +105,6 @@ namespace osu.Game.Overlays.Mods settingChangeTracker?.Dispose(); } - public Popover GetPopover() => new EditPresetPopover(this); + public Popover GetPopover() => new EditPresetPopover(Preset); } } From 26b8c5b852d31b1e0d340d0926821dfcd0910fa5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:23:51 +0900 Subject: [PATCH 0714/1400] Fix mod list display not updating after clicking "use current" This is not a regression from my changes. It was broken before them. --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 3f5eca8ad0..82d0bdb51e 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Mods private readonly Live preset; - private HashSet? newMods; + private HashSet saveableMods; [Resolved] private Bindable> selectedMods { get; set; } = null!; @@ -43,6 +43,7 @@ namespace osu.Game.Overlays.Mods public EditPresetPopover(Live preset) { this.preset = preset; + saveableMods = preset.PerformRead(p => p.Mods).ToHashSet(); } [BackgroundDependencyLoader] @@ -122,7 +123,7 @@ namespace osu.Game.Overlays.Mods Body.BorderThickness = 3; Body.BorderColour = colours.Orange1; - selectedMods.BindValueChanged(_ => updateActiveState(), true); + selectedMods.BindValueChanged(_ => updateState(), true); nameTextBox.Current.BindValueChanged(s => { saveButton.Enabled.Value = !string.IsNullOrWhiteSpace(s.NewValue); @@ -131,14 +132,14 @@ namespace osu.Game.Overlays.Mods private void useCurrentMods() { - newMods = selectedMods.Value.ToHashSet(); + saveableMods = selectedMods.Value.ToHashSet(); scrollContent.Clear(); - updateActiveState(); + updateState(); } - private void updateActiveState() + private void updateState() { - scrollContent.ChildrenEnumerable = preset.PerformRead(p => p.Mods.Select(mod => new ModPresetRow(mod))); + scrollContent.ChildrenEnumerable = saveableMods.Select(mod => new ModPresetRow(mod)); useCurrentModsButton.Enabled.Value = checkSelectedModsDiffersFromSaved(); } @@ -147,7 +148,7 @@ namespace osu.Game.Overlays.Mods if (!selectedMods.Value.Any()) return false; - return newMods?.SetEquals(selectedMods.Value) == false; + return !saveableMods.SetEquals(selectedMods.Value); } protected override void LoadComplete() @@ -163,9 +164,7 @@ namespace osu.Game.Overlays.Mods { s.Name = nameTextBox.Current.Value; s.Description = descriptionTextBox.Current.Value; - - if (newMods != null) - s.Mods = newMods; + s.Mods = saveableMods; }); this.HidePopover(); From 0034124d79ee949f00dc5ec7fcd98fe8780d250e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:25:10 +0900 Subject: [PATCH 0715/1400] Remove unnecessary content clear --- osu.Game/Overlays/Mods/EditPresetPopover.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/EditPresetPopover.cs b/osu.Game/Overlays/Mods/EditPresetPopover.cs index 82d0bdb51e..5220f6a391 100644 --- a/osu.Game/Overlays/Mods/EditPresetPopover.cs +++ b/osu.Game/Overlays/Mods/EditPresetPopover.cs @@ -133,7 +133,6 @@ namespace osu.Game.Overlays.Mods private void useCurrentMods() { saveableMods = selectedMods.Value.ToHashSet(); - scrollContent.Clear(); updateState(); } From 95b541ab39169f3f46e534c7652b0246e416bbf2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 May 2023 11:27:18 +0900 Subject: [PATCH 0716/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 3ede0b85da..59bef84bd2 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 085f78b27b..404fbada95 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 127994c670..c4df0a2347 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 2cb6642b0d8f805317f1458078e545c685c0a148 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Thu, 4 May 2023 13:18:25 +0900 Subject: [PATCH 0717/1400] use AddUntilStep or not wait --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 041556a5a6..339d861d3b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -645,8 +645,7 @@ namespace osu.Game.Tests.Visual.Online InputManager.Click(MouseButton.Left); }); - AddWaitStep("Wait", 3); - AddAssert("Overlay closed", () => !this.ChildrenOfType().Any()); + AddUntilStep("Overlay closed", () => !this.ChildrenOfType().Any()); AddStep("Complete request", () => requestLock.Set()); AddUntilStep("Request sent", () => request != null); } From 0d2396c5575cd34864e42974b7c99218e4074c2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:15:12 +0200 Subject: [PATCH 0718/1400] Rename method to better indicate directionality --- osu.Game.Tests/Mods/ModSettingsTest.cs | 14 +++++++------- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Rulesets/Mods/Mod.cs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index b3f6f8da7d..4dcc4511db 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -45,12 +45,12 @@ namespace osu.Game.Tests.Mods var modBool = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; var modInt = new TestNonMatchingSettingTypeModInt { TestSetting = { Value = (int)setting_change / 2 } }; - modDouble.CopyCommonSettings(modBool); - modDouble.CopyCommonSettings(modInt); - modBool.CopyCommonSettings(modDouble); - modBool.CopyCommonSettings(modInt); - modInt.CopyCommonSettings(modDouble); - modInt.CopyCommonSettings(modBool); + modDouble.CopyCommonSettingsFrom(modBool); + modDouble.CopyCommonSettingsFrom(modInt); + modBool.CopyCommonSettingsFrom(modDouble); + modBool.CopyCommonSettingsFrom(modInt); + modInt.CopyCommonSettingsFrom(modDouble); + modInt.CopyCommonSettingsFrom(modBool); Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Mods var modBoolTrue = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = true, Value = false } }; var modBoolFalse = new TestNonMatchingSettingTypeModBool { TestSetting = { Default = false, Value = true } }; - modBoolFalse.CopyCommonSettings(modBoolTrue); + modBoolFalse.CopyCommonSettingsFrom(modBoolTrue); Assert.That(modBoolFalse.TestSetting.Default, Is.EqualTo(false)); Assert.That(modBoolFalse.TestSetting.Value, Is.EqualTo(modBoolTrue.TestSetting.Value)); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 076c1213ad..c55b6c249f 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -633,7 +633,7 @@ namespace osu.Game var convertedMods = SelectedMods.Value.Select(mod => { var newMod = instance.CreateModFromAcronym(mod.Acronym); - newMod?.CopyCommonSettings(mod); + newMod?.CopyCommonSettingsFrom(mod); return newMod; }).Where(newMod => newMod != null).ToList(); diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 0af8717264..cf5a1c6fcc 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -168,7 +168,7 @@ namespace osu.Game.Rulesets.Mods /// /// Copied values are unchanged, even if they have different clamping ranges. /// The mod to extract settings from. - public void CopyCommonSettings(Mod source) + public void CopyCommonSettingsFrom(Mod source) { if (source.UsesDefaultConfiguration) return; From 1ac9d900e1f0ea8b66e5722174fc3f7f960b9e6b Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 4 May 2023 19:24:37 +0300 Subject: [PATCH 0719/1400] Clear search on `ModSelectOverlay.Hide` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9efcd24048..fa39c2b09d 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -112,8 +112,6 @@ namespace osu.Game.Overlays.Mods private ShearedSearchTextBox searchTextBox = null!; private DifficultyMultiplierDisplay? multiplierDisplay; - private ModSearchContainer? modSearch; - protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } @@ -215,7 +213,7 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Margin = new MarginPadding { Horizontal = 100 }, - Child = modSearch = new ModSearchContainer() + Child = new ModSearchContainer() }); FooterContent.Child = footerButtonFlow = new FillFlowContainer @@ -243,6 +241,14 @@ namespace osu.Game.Overlays.Mods globalAvailableMods.BindTo(game.AvailableMods); } + public override void Hide() + { + base.Hide(); + + //We want to clear search for next user iteraction with mod overlay + searchTextBox.Current.Value = string.Empty; + } + private ModSettingChangeTracker? modSettingChangeTracker; protected override void LoadComplete() From 26337dbcd8c7ca314cf0a8034ee2a6cdad9058b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:26:45 +0200 Subject: [PATCH 0720/1400] Do not rely on unspecified `Dictionary.Values` ordering --- osu.Game/Rulesets/Mods/Mod.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index cf5a1c6fcc..db7e7ce8e3 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -119,7 +119,11 @@ namespace osu.Game.Rulesets.Mods /// /// All settings within this mod. /// - internal IEnumerable SettingsBindables => Settings.Values; + /// + /// The settings are returned in ascending key order as per . + /// The ordering is intentionally enforced manually, as ordering of is unspecified. + /// + internal IEnumerable SettingsBindables => Settings.OrderBy(pair => pair.Key).Select(pair => pair.Value); /// /// Provides mapping of names to s of all settings within this mod. From 88e77ad390fad33752395905260f97ed95f86def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:30:41 +0200 Subject: [PATCH 0721/1400] Rename `Settings{-> Map}` --- osu.Game/Rulesets/Mods/Mod.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index db7e7ce8e3..cd89b45a5e 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -120,15 +120,15 @@ namespace osu.Game.Rulesets.Mods /// All settings within this mod. /// /// - /// The settings are returned in ascending key order as per . + /// The settings are returned in ascending key order as per . /// The ordering is intentionally enforced manually, as ordering of is unspecified. /// - internal IEnumerable SettingsBindables => Settings.OrderBy(pair => pair.Key).Select(pair => pair.Value); + internal IEnumerable SettingsBindables => SettingsMap.OrderBy(pair => pair.Key).Select(pair => pair.Value); /// /// Provides mapping of names to s of all settings within this mod. /// - internal IReadOnlyDictionary Settings => + internal IReadOnlyDictionary SettingsMap => settingsBacking ??= this.GetSettingsSourceProperties() .Select(p => p.Item2) .ToDictionary(property => property.Name.ToSnakeCase(), property => (IBindable)property.GetValue(this)!); @@ -177,9 +177,9 @@ namespace osu.Game.Rulesets.Mods if (source.UsesDefaultConfiguration) return; - foreach (var (name, targetSetting) in Settings) + foreach (var (name, targetSetting) in SettingsMap) { - if (!source.Settings.TryGetValue(name, out IBindable? sourceSetting)) + if (!source.SettingsMap.TryGetValue(name, out IBindable? sourceSetting)) continue; if (sourceSetting.IsDefault) From 1f1342b099752b99de109a2fc6a6fcbaa9b37bbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:33:49 +0200 Subject: [PATCH 0722/1400] Reword xmldoc --- osu.Game/Rulesets/Mods/Mod.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index cd89b45a5e..f5ccde01cf 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -167,10 +167,13 @@ namespace osu.Game.Rulesets.Mods } /// - /// When converting mods from one ruleset to the other, this method makes sure - /// to also copy the values of all settings sharing same between the two instances. + /// This method copies the values of all settings from that share the same names with this mod instance. + /// The most frequent use of this is when switching rulesets, in order to preserve values of common settings during the switch. /// - /// Copied values are unchanged, even if they have different clamping ranges. + /// + /// The values are copied directly, without adjusting for possibly different allowed ranges of values. + /// If the value of a setting is not valid for this instance due to not falling inside of the allowed range, it will be clamped accordingly. + /// /// The mod to extract settings from. public void CopyCommonSettingsFrom(Mod source) { From e43fc23606e4b579fdf46ee54aa3fb144bb85d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 18:46:36 +0200 Subject: [PATCH 0723/1400] Fix typos in test --- .../Visual/UserInterface/TestSceneModPresetColumn.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 0cbbe00311..3efdba8754 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -262,7 +262,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestEditPresentName() + public void TestEditPresetName() { ModPresetColumn modPresetColumn = null!; string presetName = null!; @@ -301,7 +301,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddAssert("present is not changed", () => panel.Preset.Value.Name == presetName); + AddAssert("preset is not changed", () => panel.Preset.Value.Name == presetName); AddUntilStep("popover is unchanged", () => this.ChildrenOfType().FirstOrDefault() == popover); AddStep("edit preset name", () => popover.ChildrenOfType().First().Current.Value = "something new"); AddStep("attempt preset edit", () => @@ -310,7 +310,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); AddUntilStep("popover closed", () => !this.ChildrenOfType().Any()); - AddAssert("present is changed", () => panel.Preset.Value.Name != presetName); + AddAssert("preset is changed", () => panel.Preset.Value.Name != presetName); } [Test] @@ -357,7 +357,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddUntilStep("present mod not changed", () => + AddUntilStep("preset mod not changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(previousMod)); AddStep("select mods", () => SelectedMods.Value = mods); @@ -388,7 +388,7 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.Click(MouseButton.Left); }); - AddUntilStep("present mod is changed", () => + AddUntilStep("preset mod is changed", () => new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } From 485b7282dce5a7c220fa534e2f5f9655935270e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 19:06:07 +0200 Subject: [PATCH 0724/1400] Clarify type check --- osu.Game/Rulesets/Mods/Mod.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index f5ccde01cf..787da926ea 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -188,10 +188,13 @@ namespace osu.Game.Rulesets.Mods if (sourceSetting.IsDefault) continue; - var targetType = targetSetting.GetType(); - var sourceType = sourceSetting.GetType(); + var targetBindableType = targetSetting.GetType(); + var sourceBindableType = sourceSetting.GetType(); - if (!targetType.IsAssignableFrom(sourceType) && !sourceType.IsAssignableFrom(targetType)) + // if either the target is assignable to the source or the source is assignable to the target, + // then we presume that the data types contained in both bindables are compatible and we can proceed with the copy. + // this handles cases like `Bindable` and `BindableInt`. + if (!targetBindableType.IsAssignableFrom(sourceBindableType) && !sourceBindableType.IsAssignableFrom(targetBindableType)) continue; // TODO: special case for handling number types From aa7885ab973a258c350ad26c19bc51d89befdf51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 19:11:51 +0200 Subject: [PATCH 0725/1400] Use better test step names --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index b4b5052f23..f079b65e23 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -399,7 +399,7 @@ namespace osu.Game.Tests.Visual.UserInterface changeRuleset(1); AddAssert("taiko variant selected", () => SelectedMods.Value.SingleOrDefault() is TaikoModDifficultyAdjust); - AddAssert("shared settings didn't change", () => + AddAssert("shared settings preserved", () => { var taikoMod = getMod(); @@ -408,7 +408,7 @@ namespace osu.Game.Tests.Visual.UserInterface taikoMod.OverallDifficulty.Value == setting_change; }); - AddAssert("non-shared settings unchanged", () => + AddAssert("non-shared settings remain default", () => { var taikoMod = getMod(); From 99e8b2ce70276a34d648960556373917b50d0e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 19:12:22 +0200 Subject: [PATCH 0726/1400] Make `getMod()` method generally better --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index f079b65e23..9993893a99 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -387,7 +387,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("change mod settings", () => { - var osuMod = getMod(); + var osuMod = getSelectedMod(); osuMod.ExtendedLimits.Value = true; osuMod.CircleSize.Value = setting_change; @@ -401,7 +401,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("shared settings preserved", () => { - var taikoMod = getMod(); + var taikoMod = getSelectedMod(); return taikoMod.ExtendedLimits.Value && taikoMod.DrainRate.Value == setting_change && @@ -410,7 +410,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("non-shared settings remain default", () => { - var taikoMod = getMod(); + var taikoMod = getSelectedMod(); return taikoMod.ScrollSpeed.IsDefault; }); @@ -626,7 +626,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert($"customisation toggle is {(active ? "" : "not ")}active", () => modSelectOverlay.CustomisationButton.AsNonNull().Active.Value == active); } - private T getMod() where T : Mod => (T)SelectedMods.Value.Single(); + private T getSelectedMod() where T : Mod => SelectedMods.Value.OfType().Single(); private ModPanel getPanelForMod(Type modType) => modSelectOverlay.ChildrenOfType().Single(panel => panel.Mod.GetType() == modType); From a1106d0a4e0a2522122f945d283f92368714f4f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 19:14:20 +0200 Subject: [PATCH 0727/1400] Be explicit in test --- osu.Game.Tests/Mods/ModSettingsTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Mods/ModSettingsTest.cs b/osu.Game.Tests/Mods/ModSettingsTest.cs index 4dcc4511db..5ec9629dc2 100644 --- a/osu.Game.Tests/Mods/ModSettingsTest.cs +++ b/osu.Game.Tests/Mods/ModSettingsTest.cs @@ -53,7 +53,7 @@ namespace osu.Game.Tests.Mods modInt.CopyCommonSettingsFrom(modBool); Assert.That(modDouble.TestSetting.Value, Is.EqualTo(setting_change)); - Assert.That(modBool.TestSetting.Value, Is.EqualTo(!modBool.TestSetting.Default)); + Assert.That(modBool.TestSetting.Value, Is.EqualTo(true)); Assert.That(modInt.TestSetting.Value, Is.EqualTo((int)setting_change / 2)); } From dcd2abae6d5f7a196fae601854f08a794999c470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 20:46:27 +0200 Subject: [PATCH 0728/1400] Add test coverage for mod equality with multiple settings --- .../Mods/ModSettingsEqualityComparison.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Tests/Mods/ModSettingsEqualityComparison.cs b/osu.Game.Tests/Mods/ModSettingsEqualityComparison.cs index cd6879cf01..a03b29f7bc 100644 --- a/osu.Game.Tests/Mods/ModSettingsEqualityComparison.cs +++ b/osu.Game.Tests/Mods/ModSettingsEqualityComparison.cs @@ -49,5 +49,31 @@ namespace osu.Game.Tests.Mods Assert.That(mod3, Is.EqualTo(mod2)); Assert.That(doubleConvertedMod3, Is.EqualTo(doubleConvertedMod2)); } + + [Test] + public void TestModWithMultipleSettings() + { + var ruleset = new OsuRuleset(); + + var mod1 = new OsuModDifficultyAdjust { OverallDifficulty = { Value = 10 }, CircleSize = { Value = 0 } }; + var mod2 = new OsuModDifficultyAdjust { OverallDifficulty = { Value = 10 }, CircleSize = { Value = 6 } }; + var mod3 = new OsuModDifficultyAdjust { OverallDifficulty = { Value = 10 }, CircleSize = { Value = 6 } }; + + var doubleConvertedMod1 = new APIMod(mod1).ToMod(ruleset); + var doubleConvertedMod2 = new APIMod(mod2).ToMod(ruleset); + var doubleConvertedMod3 = new APIMod(mod3).ToMod(ruleset); + + Assert.That(mod1, Is.Not.EqualTo(mod2)); + Assert.That(doubleConvertedMod1, Is.Not.EqualTo(doubleConvertedMod2)); + + Assert.That(mod2, Is.EqualTo(mod2)); + Assert.That(doubleConvertedMod2, Is.EqualTo(doubleConvertedMod2)); + + Assert.That(mod2, Is.EqualTo(mod3)); + Assert.That(doubleConvertedMod2, Is.EqualTo(doubleConvertedMod3)); + + Assert.That(mod3, Is.EqualTo(mod2)); + Assert.That(doubleConvertedMod3, Is.EqualTo(doubleConvertedMod2)); + } } } From 74e7a958bbbba4dc52159d19aabd758e28524cb6 Mon Sep 17 00:00:00 2001 From: tsrk Date: Fri, 5 May 2023 05:31:06 +0100 Subject: [PATCH 0729/1400] feat(ArgonKeyCounter): make animation Currently WIP. Do not consider this final. --- osu.Game/Screens/Play/ArgonKeyCounter.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs index 6818b30823..8635783d71 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounter.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -69,8 +69,19 @@ namespace osu.Game.Screens.Play { base.LoadComplete(); - IsActive.BindValueChanged(e => inputIndicator.Alpha = e.NewValue ? 1 : 0.5f, true); CountPresses.BindValueChanged(e => countText.Text = e.NewValue.ToString(@"#,0"), true); } + + protected override void Activate(bool forwardPlayback = true) + { + base.Activate(forwardPlayback); + inputIndicator.FadeIn().MoveToY(0).Then().MoveToY(3, 100, Easing.OutQuart); + } + + protected override void Deactivate(bool forwardPlayback = true) + { + base.Deactivate(forwardPlayback); + inputIndicator.MoveToY(0, 200, Easing.OutQuart).FadeTo(0.5f, 200, Easing.OutQuart); + } } } From 8391e2a538c7ca7777e2c04a9cdf90a9f191abf7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 13:58:13 +0900 Subject: [PATCH 0730/1400] Move reporting code out of `DrawableChatUsername` into more correct locations --- .../Visual/Online/TestSceneChatOverlay.cs | 2 +- osu.Game/Overlays/Chat/ChatLine.cs | 14 +++++--- .../Overlays/Chat/DrawableChatUsername.cs | 34 +++---------------- osu.Game/Overlays/Chat/ReportChatPopover.cs | 31 +++++++++++++++-- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 339d861d3b..99ce837665 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -616,7 +616,7 @@ namespace osu.Game.Tests.Visual.Online }; }); - AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); + AddStep("Show report popover", () => this.ChildrenOfType().First().ShowPopover()); AddStep("Set report reason to other", () => { diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index dca34128d1..2f4c175ac4 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,25 +1,28 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Linq; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; -using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Chat { - public partial class ChatLine : CompositeDrawable + public partial class ChatLine : CompositeDrawable, IHasPopover { private Message message = null!; @@ -92,7 +95,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername = new DrawableChatUsername(message.Sender, message.Id) + drawableUsername = new DrawableChatUsername(message.Sender) { Width = UsernameWidth, FontSize = FontSize, @@ -100,6 +103,7 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Margin = new MarginPadding { Horizontal = Spacing }, + ReportRequested = this.ShowPopover, }, drawableContentFlow = new LinkFlowContainer(styleMessageContent) { @@ -128,6 +132,8 @@ namespace osu.Game.Overlays.Chat FinishTransforms(true); } + public Popover GetPopover() => new ReportChatPopover(message); + /// /// Performs a highlight animation on this . /// diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index b3bbc74be7..4b4afc204c 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,7 +20,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Resources.Localisation.Web; @@ -31,8 +29,10 @@ using ChatStrings = osu.Game.Localisation.ChatStrings; namespace osu.Game.Overlays.Chat { - public partial class DrawableChatUsername : OsuClickableContainer, IHasContextMenu, IHasPopover + public partial class DrawableChatUsername : OsuClickableContainer, IHasContextMenu { + public Action? ReportRequested; + public Color4 AccentColour { get; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => @@ -73,15 +73,13 @@ namespace osu.Game.Overlays.Chat private Bindable? currentChannel { get; set; } private readonly APIUser user; - private readonly long? messageId; private readonly OsuSpriteText drawableText; private readonly Drawable colouredDrawable; - public DrawableChatUsername(APIUser user, long? messageId) + public DrawableChatUsername(APIUser user) { this.user = user; - this.messageId = messageId; Action = openUserProfile; @@ -174,34 +172,12 @@ namespace osu.Game.Overlays.Chat } if (!user.Equals(api.LocalUser.Value)) - items.Add(new OsuMenuItem("Report", MenuItemType.Destructive, this.ShowPopover)); + items.Add(new OsuMenuItem("Report", MenuItemType.Destructive, ReportRequested)); return items.ToArray(); } } - public Popover GetPopover() => new ReportChatPopover(user) - { - Action = report - }; - - private void report(ChatReportReason reason, string comments) - { - var request = new ChatReportRequest(messageId, reason, comments); - - request.Failure += _ => Schedule(() => - { - currentChannel?.Value?.AddNewMessages(new ErrorMessage("Report failed to send, please retry")); - }); - - request.Success += () => Schedule(() => - { - currentChannel?.Value?.AddNewMessages(new InfoMessage("Report has been sent")); - }); - - api.Queue(request); - } - private void openUserChannel() { chatManager?.OpenPrivateChannel(user); diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index de5f3268b8..f02e52eb2e 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -1,22 +1,47 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Game.Graphics.UserInterfaceV2; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.Chat; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat { public partial class ReportChatPopover : ReportPopover { - public ReportChatPopover(APIUser? user) - : base(ReportStrings.UserTitle(user?.Username ?? @"Someone")) + [Resolved] + private IAPIProvider api { get; set; } = null!; + + [Resolved] + private ChannelManager channelManager { get; set; } = null!; + + private readonly Message message; + + public ReportChatPopover(Message message) + : base(ReportStrings.UserTitle(message.Sender?.Username ?? @"Someone")) { + this.message = message; + Action = report; } protected override bool CheckCanSubmitEmptyComment(ChatReportReason reason) { return reason != ChatReportReason.Other; } + + private void report(ChatReportReason reason, string comments) + { + var request = new ChatReportRequest(message.Id, reason, comments); + + request.Success += () => Schedule(() => + { + channelManager.CurrentChannel.Value.AddNewMessages(new InfoMessage(UsersStrings.ReportThanks.ToString())); + }); + + api.Queue(request); + } } } From 560f71ef5366a673cd0f7e79ba55ef16c4c73610 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 14:29:03 +0900 Subject: [PATCH 0731/1400] Adjust `BlurredIcon` expansion ratio to fix glow getting cut off at lower resolutions Closes https://github.com/ppy/osu/issues/23210. Ballparked the fix to work down to the lowest resolution we support. The previous number (`2.5f`) was also likely ballparked so the fix seems in line with expectations. I don't want to put too much thought into this because the design of this screen is likely going to change in the mean time anyway. --- osu.Game/Screens/Play/Break/BlurredIcon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Break/BlurredIcon.cs b/osu.Game/Screens/Play/Break/BlurredIcon.cs index cd38390324..6ce1c2e686 100644 --- a/osu.Game/Screens/Play/Break/BlurredIcon.cs +++ b/osu.Game/Screens/Play/Break/BlurredIcon.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play.Break set { icon.Size = value; - base.Size = value + BlurSigma * 2.5f; + base.Size = value + BlurSigma * 5; ForceRedraw(); } get => base.Size; From 76b2f0e6dd57f50c956cc38ede5565aa6bda522e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 15:15:18 +0900 Subject: [PATCH 0732/1400] Show slider velocity in hit object inspector --- osu.Game/Rulesets/Edit/HitObjectInspector.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index 977d00ede2..7eeee7a6e9 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -98,6 +98,12 @@ namespace osu.Game.Rulesets.Edit addValue($"{distance.Distance:#,0.##}px"); } + if (selected is IHasSliderVelocity sliderVelocity) + { + addHeader("Slider Velocity"); + addValue($"{sliderVelocity.SliderVelocity:#,0.00}x"); + } + if (selected is IHasRepeats repeats) { addHeader("Repeats"); From 54757df51fefc2c8c3a19b7dc340036ceb5b6a29 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 5 May 2023 09:31:27 +0300 Subject: [PATCH 0733/1400] Fix mod deselect button not working properly when search applied --- osu.Game/Overlays/Mods/ModColumn.cs | 6 +++++- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 10 ---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index df2a7780d3..5da57ee4ed 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -206,8 +206,12 @@ namespace osu.Game.Overlays.Mods { pendingSelectionOperations.Clear(); - foreach (var button in availableMods.Where(b => b.Active.Value && b.MatchingFilter.Value)) + foreach (var button in availableMods.Where(b => b.Active.Value)) pendingSelectionOperations.Enqueue(() => button.Active.Value = false); + + //If column is hidden trigger selection manually + if (Alpha == 0f) + Update(); } /// diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index fa39c2b09d..d2af305d68 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -206,16 +206,6 @@ namespace osu.Game.Overlays.Mods }); } - MainAreaContent.Add(new Container - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.X, - Height = ModsEffectDisplay.HEIGHT, - Margin = new MarginPadding { Horizontal = 100 }, - Child = new ModSearchContainer() - }); - FooterContent.Child = footerButtonFlow = new FillFlowContainer { RelativeSizeAxes = Axes.X, From ab94b4dce194c85942bfa94d6c1f7bb16073dc93 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 5 May 2023 09:52:09 +0300 Subject: [PATCH 0734/1400] Update `ModPresetPanel.FilterTerms` to account mod names and acronyms --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 5b6146e106..5bc16abcab 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -83,11 +83,20 @@ namespace osu.Game.Overlays.Mods #region Filtering support - public override IEnumerable FilterTerms => new LocalisableString[] + public override IEnumerable FilterTerms => getFilterTerms(); + + private IEnumerable getFilterTerms() { - Preset.Value.Name, - Preset.Value.Description - }; + yield return Preset.Value.Name; + yield return Preset.Value.Description; + + foreach (Mod mod in Preset.Value.Mods) + { + yield return mod.Name; + yield return mod.Acronym; + yield return mod.Description; + } + } #endregion From 4663057060ee71e79aba79bfd99594ba24ebad73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 15:40:34 +0900 Subject: [PATCH 0735/1400] Split out `EditorInspector` implementation for reuse --- osu.Game/Rulesets/Edit/EditorInspector.cs | 50 ++++++++++ osu.Game/Rulesets/Edit/HitObjectInspector.cs | 99 ++++++-------------- 2 files changed, 79 insertions(+), 70 deletions(-) create mode 100644 osu.Game/Rulesets/Edit/EditorInspector.cs diff --git a/osu.Game/Rulesets/Edit/EditorInspector.cs b/osu.Game/Rulesets/Edit/EditorInspector.cs new file mode 100644 index 0000000000..ed7f305a28 --- /dev/null +++ b/osu.Game/Rulesets/Edit/EditorInspector.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Overlays; +using osu.Game.Screens.Edit; + +namespace osu.Game.Rulesets.Edit +{ + internal partial class EditorInspector : CompositeDrawable + { + protected OsuTextFlowContainer InspectorText = null!; + + [Resolved] + protected EditorBeatmap EditorBeatmap { get; private set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + + InternalChild = InspectorText = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + } + + protected void AddHeader(string header) => InspectorText.AddParagraph($"{header}: ", s => + { + s.Padding = new MarginPadding { Top = 2 }; + s.Font = s.Font.With(size: 12); + s.Colour = colourProvider.Content2; + }); + + protected void AddValue(string value) => InspectorText.AddParagraph(value, s => + { + s.Font = s.Font.With(weight: FontWeight.SemiBold); + s.Colour = colourProvider.Content1; + }); + } +} diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Rulesets/Edit/HitObjectInspector.cs index 7eeee7a6e9..d13190e484 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Rulesets/Edit/HitObjectInspector.cs @@ -2,43 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.TypeExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Threading; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Overlays; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Screens.Edit; namespace osu.Game.Rulesets.Edit { - internal partial class HitObjectInspector : CompositeDrawable + internal partial class HitObjectInspector : EditorInspector { - private OsuTextFlowContainer inspectorText = null!; - - [Resolved] - protected EditorBeatmap EditorBeatmap { get; private set; } = null!; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - [BackgroundDependencyLoader] - private void load() - { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; - - InternalChild = inspectorText = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -53,69 +25,69 @@ namespace osu.Game.Rulesets.Edit private void updateInspectorText() { - inspectorText.Clear(); + InspectorText.Clear(); rollingTextUpdate?.Cancel(); rollingTextUpdate = null; switch (EditorBeatmap.SelectedHitObjects.Count) { case 0: - addValue("No selection"); + AddValue("No selection"); break; case 1: var selected = EditorBeatmap.SelectedHitObjects.Single(); - addHeader("Type"); - addValue($"{selected.GetType().ReadableName()}"); + AddHeader("Type"); + AddValue($"{selected.GetType().ReadableName()}"); - addHeader("Time"); - addValue($"{selected.StartTime:#,0.##}ms"); + AddHeader("Time"); + AddValue($"{selected.StartTime:#,0.##}ms"); switch (selected) { case IHasPosition pos: - addHeader("Position"); - addValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); + AddHeader("Position"); + AddValue($"x:{pos.X:#,0.##} y:{pos.Y:#,0.##}"); break; case IHasXPosition x: - addHeader("Position"); + AddHeader("Position"); - addValue($"x:{x.X:#,0.##} "); + AddValue($"x:{x.X:#,0.##} "); break; case IHasYPosition y: - addHeader("Position"); + AddHeader("Position"); - addValue($"y:{y.Y:#,0.##}"); + AddValue($"y:{y.Y:#,0.##}"); break; } if (selected is IHasDistance distance) { - addHeader("Distance"); - addValue($"{distance.Distance:#,0.##}px"); + AddHeader("Distance"); + AddValue($"{distance.Distance:#,0.##}px"); } if (selected is IHasSliderVelocity sliderVelocity) { - addHeader("Slider Velocity"); - addValue($"{sliderVelocity.SliderVelocity:#,0.00}x"); + AddHeader("Slider Velocity"); + AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x"); } if (selected is IHasRepeats repeats) { - addHeader("Repeats"); - addValue($"{repeats.RepeatCount:#,0.##}"); + AddHeader("Repeats"); + AddValue($"{repeats.RepeatCount:#,0.##}"); } if (selected is IHasDuration duration) { - addHeader("End Time"); - addValue($"{duration.EndTime:#,0.##}ms"); - addHeader("Duration"); - addValue($"{duration.Duration:#,0.##}ms"); + AddHeader("End Time"); + AddValue($"{duration.EndTime:#,0.##}ms"); + AddHeader("Duration"); + AddValue($"{duration.Duration:#,0.##}ms"); } // I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes. @@ -124,29 +96,16 @@ namespace osu.Game.Rulesets.Edit break; default: - addHeader("Selected Objects"); - addValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); + AddHeader("Selected Objects"); + AddValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}"); - addHeader("Start Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}ms"); + AddHeader("Start Time"); + AddValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}ms"); - addHeader("End Time"); - addValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}ms"); + AddHeader("End Time"); + AddValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}ms"); break; } - - void addHeader(string header) => inspectorText.AddParagraph($"{header}: ", s => - { - s.Padding = new MarginPadding { Top = 2 }; - s.Font = s.Font.With(size: 12); - s.Colour = colourProvider.Content2; - }); - - void addValue(string value) => inspectorText.AddParagraph(value, s => - { - s.Font = s.Font.With(weight: FontWeight.SemiBold); - s.Colour = colourProvider.Content1; - }); } } } From cc70d89bf94269d34b3e32cfc24a66884d26f6dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 15:42:34 +0900 Subject: [PATCH 0736/1400] Move editor inspector classes out of ruleset namespace --- .../Edit/Compose/Components}/EditorInspector.cs | 3 +-- .../Edit/Compose/Components}/HitObjectInspector.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) rename osu.Game/{Rulesets/Edit => Screens/Edit/Compose/Components}/EditorInspector.cs (96%) rename osu.Game/{Rulesets/Edit => Screens/Edit/Compose/Components}/HitObjectInspector.cs (98%) diff --git a/osu.Game/Rulesets/Edit/EditorInspector.cs b/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs similarity index 96% rename from osu.Game/Rulesets/Edit/EditorInspector.cs rename to osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs index ed7f305a28..442454f97a 100644 --- a/osu.Game/Rulesets/Edit/EditorInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorInspector.cs @@ -7,9 +7,8 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays; -using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Edit +namespace osu.Game.Screens.Edit.Compose.Components { internal partial class EditorInspector : CompositeDrawable { diff --git a/osu.Game/Rulesets/Edit/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs similarity index 98% rename from osu.Game/Rulesets/Edit/HitObjectInspector.cs rename to osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index d13190e484..597925e3e2 100644 --- a/osu.Game/Rulesets/Edit/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -7,7 +7,7 @@ using osu.Framework.Threading; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Rulesets.Edit +namespace osu.Game.Screens.Edit.Compose.Components { internal partial class HitObjectInspector : EditorInspector { From b7a287869a5867c6ed5c2388e29ddff36ea94084 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 15:54:27 +0900 Subject: [PATCH 0737/1400] Add display of beatmap slider velocity when adjusting --- .../Timeline/DifficultyPointPiece.cs | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 4741b75641..9192913fa0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -95,7 +95,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Text = "Hold shift while dragging the end of an object to adjust velocity while snapping." - } + }, + new SliderVelocityInspector(), } } }; @@ -105,7 +106,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).Where(o => o is IHasSliderVelocity).ToArray(); // even if there are multiple objects selected, we can still display a value if they all have the same value. - var selectedPointBindable = relevantObjects.Select(point => ((IHasSliderVelocity)point).SliderVelocity).Distinct().Count() == 1 ? ((IHasSliderVelocity)relevantObjects.First()).SliderVelocityBindable : null; + var selectedPointBindable = relevantObjects.Select(point => ((IHasSliderVelocity)point).SliderVelocity).Distinct().Count() == 1 + ? ((IHasSliderVelocity)relevantObjects.First()).SliderVelocityBindable + : null; if (selectedPointBindable != null) { @@ -139,4 +142,37 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } } + + internal partial class SliderVelocityInspector : EditorInspector + { + [BackgroundDependencyLoader] + private void load() + { + EditorBeatmap.TransactionBegan += updateInspectorText; + EditorBeatmap.TransactionEnded += updateInspectorText; + updateInspectorText(); + } + + private void updateInspectorText() + { + InspectorText.Clear(); + + double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray(); + + if (sliderVelocities.Length < 2) + return; + + double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key; + double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2]; + + AddHeader("Beatmap average velocity"); + AddValue($"{medianSliderVelocity:#,0.00}x"); + + AddHeader("Most used velocity"); + AddValue($"{modeSliderVelocity:#,0.00}x"); + + AddHeader("Velocity range"); + AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); + } + } } From 3d55a0291f2c1378b0a28e360afd9a6189a4a5cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 15:40:43 +0900 Subject: [PATCH 0738/1400] Prefer block scoped namespaces --- .editorconfig | 2 ++ osu.sln.DotSettings | 1 + 2 files changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index c0ea55f4c8..67c47000d3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -191,6 +191,8 @@ csharp_style_prefer_index_operator = false:silent csharp_style_prefer_range_operator = false:silent csharp_style_prefer_switch_expression = false:none +csharp_style_namespace_declarations = block_scoped:warning + [*.{yaml,yml}] insert_final_newline = true indent_style = space diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 367dfccb71..d7486273fb 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -277,6 +277,7 @@ Explicit ExpressionBody BlockBody + BlockScoped ExplicitlyTyped True NEXT_LINE From 01581024678c6f4d99a54892cb95cbe7599f0f3c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:19:09 +0900 Subject: [PATCH 0739/1400] Rename class back to original name so I can read the diff --- osu.Game.Tests/Database/LegacyModelExporterTest.cs | 2 +- osu.Game/Database/LegacyArchiveExporter.cs | 2 +- .../Database/{LegacyModelExporter.cs => LegacyExporter.cs} | 4 ++-- osu.Game/Database/LegacyScoreExporter.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game/Database/{LegacyModelExporter.cs => LegacyExporter.cs} (98%) diff --git a/osu.Game.Tests/Database/LegacyModelExporterTest.cs b/osu.Game.Tests/Database/LegacyModelExporterTest.cs index 27059c3058..1e9cdfd67d 100644 --- a/osu.Game.Tests/Database/LegacyModelExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyModelExporterTest.cs @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Database storage.Dispose(); } - private class TestLegacyModelExporter : LegacyModelExporter + private class TestLegacyModelExporter : LegacyExporter { public TestLegacyModelExporter(Storage storage) : base(storage) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 297139a20e..d37f9a5dca 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -17,7 +17,7 @@ using Logger = osu.Framework.Logging.Logger; namespace osu.Game.Database { - public abstract class LegacyArchiveExporter : LegacyModelExporter + public abstract class LegacyArchiveExporter : LegacyExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { protected LegacyArchiveExporter(Storage storage) diff --git a/osu.Game/Database/LegacyModelExporter.cs b/osu.Game/Database/LegacyExporter.cs similarity index 98% rename from osu.Game/Database/LegacyModelExporter.cs rename to osu.Game/Database/LegacyExporter.cs index 0e4fefae5c..bb2143178b 100644 --- a/osu.Game/Database/LegacyModelExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -19,7 +19,7 @@ namespace osu.Game.Database /// /// A class which handles exporting legacy user data of a single type from osu-stable. /// - public abstract class LegacyModelExporter + public abstract class LegacyExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { /// @@ -54,7 +54,7 @@ namespace osu.Game.Database /// Create a new exporter for each export, otherwise it will cause confusing notifications. /// /// Storage for storing exported files. Basically it is used to provide export stream - protected LegacyModelExporter(Storage storage) + protected LegacyExporter(Storage storage) { exportStorage = storage.GetStorageForDirectory(@"exports"); UserFileStorage = storage.GetStorageForDirectory(@"files"); diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index e7473c963b..927d36ea03 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -11,7 +11,7 @@ using osu.Game.Scoring; namespace osu.Game.Database { - public class LegacyScoreExporter : LegacyModelExporter + public class LegacyScoreExporter : LegacyExporter { public LegacyScoreExporter(Storage storage) : base(storage) From 6a4933a31c0cd861925826dec4d13595399e4fe6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:30:01 +0900 Subject: [PATCH 0740/1400] Remove need for `TestRealmLive` nonsense --- .../Database/LegacyModelExporterTest.cs | 42 ++++++------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyModelExporterTest.cs b/osu.Game.Tests/Database/LegacyModelExporterTest.cs index 1e9cdfd67d..09f776e8ea 100644 --- a/osu.Game.Tests/Database/LegacyModelExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyModelExporterTest.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameTest() { - var item = new TestRealmObject(short_filename); + var item = new TestModel(short_filename); Assert.That(item.Filename.Length, Is.LessThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Database [Test] public void ExportFileWithNormalNameMultipleTimesTest() { - var item = new TestRealmObject(short_filename); + var item = new TestModel(short_filename); Assert.That(item.Filename.Length, Is.LessThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Database int expectedLength = TestLegacyModelExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); - var item = new TestRealmObject(long_filename); + var item = new TestModel(long_filename); Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); exportItemAndAssert(item, expectedName); @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Database int expectedLength = TestLegacyModelExporter.MAX_FILENAME_LENGTH - (legacyExporter.GetExtension().Length); string expectedName = long_filename.Remove(expectedLength); - var item = new TestRealmObject(long_filename); + var item = new TestModel(long_filename); Assert.That(item.Filename.Length, Is.GreaterThan(TestLegacyModelExporter.MAX_FILENAME_LENGTH)); @@ -90,11 +90,11 @@ namespace osu.Game.Tests.Database } } - private void exportItemAndAssert(TestRealmObject item, string expectedName) + private void exportItemAndAssert(TestModel item, string expectedName) { Assert.DoesNotThrow(() => { - Task t = Task.Run(() => legacyExporter.ExportAsync(new TestRealmLive(item))); + Task t = Task.Run(() => legacyExporter.ExportAsync(new RealmLiveUnmanaged(item))); t.WaitSafely(); }); Assert.That(storage.Exists($"exports/{expectedName}{legacyExporter.GetExtension()}"), Is.True); @@ -107,7 +107,7 @@ namespace osu.Game.Tests.Database storage.Dispose(); } - private class TestLegacyModelExporter : LegacyExporter + private class TestLegacyModelExporter : LegacyExporter { public TestLegacyModelExporter(Storage storage) : base(storage) @@ -116,45 +116,27 @@ namespace osu.Game.Tests.Database public string GetExtension() => FileExtension; - protected override void ExportToStream(TestRealmObject model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) + protected override void ExportToStream(TestModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { } protected override string FileExtension => ".test"; } - private class TestRealmObject : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey + private class TestModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { - public Guid ID => throw new NotImplementedException(); + public Guid ID => Guid.Empty; + public string Filename { get; } public IEnumerable Files { get; } = new List(); - public TestRealmObject(string filename) + public TestModel(string filename) { Filename = filename; } public override string ToString() => Filename; } - - private class TestRealmLive : Live - { - public override void PerformRead(Action perform) => perform(Value); - - public override TReturn PerformRead(Func perform) => perform(Value); - - public override void PerformWrite(Action perform) => throw new NotImplementedException(); - - public override bool IsManaged => throw new NotImplementedException(); - - public override TestRealmObject Value { get; } - - public TestRealmLive(TestRealmObject model) - : base(Guid.Empty) - { - Value = model; - } - } } } From f2dd457b3de9ae4c2cf66d259de86fa5e0f8ff6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:31:48 +0900 Subject: [PATCH 0741/1400] Remove unnecessary local variable --- osu.Game.Tests/Database/LegacyModelExporterTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyModelExporterTest.cs b/osu.Game.Tests/Database/LegacyModelExporterTest.cs index 09f776e8ea..2169bc73cd 100644 --- a/osu.Game.Tests/Database/LegacyModelExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyModelExporterTest.cs @@ -94,8 +94,7 @@ namespace osu.Game.Tests.Database { Assert.DoesNotThrow(() => { - Task t = Task.Run(() => legacyExporter.ExportAsync(new RealmLiveUnmanaged(item))); - t.WaitSafely(); + Task.Run(() => legacyExporter.ExportAsync(new RealmLiveUnmanaged(item))).WaitSafely(); }); Assert.That(storage.Exists($"exports/{expectedName}{legacyExporter.GetExtension()}"), Is.True); } From 4ec98b0578869237d5cd60b7e27779740351ae1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:45:45 +0900 Subject: [PATCH 0742/1400] Improve xmldoc and fix silly progress text in `LegacyArchiveExporter` --- osu.Game/Database/LegacyArchiveExporter.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index d37f9a5dca..01d00b311d 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -17,6 +17,9 @@ using Logger = osu.Framework.Logging.Logger; namespace osu.Game.Database { + /// + /// An exporter which handles the common scenario of exporting a model to a zip-based archive, usually with a custom file extension. + /// public abstract class LegacyArchiveExporter : LegacyExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey { @@ -31,17 +34,18 @@ namespace osu.Game.Database /// /// Exports an item to Stream as a legacy (.zip based) package. /// - /// The model will be exported. + /// The model to be exported. /// The output stream to export to. - /// The notification will displayed to the user - /// The Cancellation token that can cancel the exporting. + /// An optional target notification to update with ongoing export progress. + /// The cancellation token. private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { try { using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); - float i = 0; + int i = 0; + int fileCount = model.Files.Count(); bool fileMissing = false; foreach (var file in model.Files) @@ -66,13 +70,12 @@ namespace osu.Game.Database } } - i++; - if (notification != null) { - notification.Progress = i / model.Files.Count(); - notification.Text = $"Exporting... ({i}/{model.Files.Count()})"; + notification.Progress = (float)(i + 1) / fileCount; } + + i++; } } catch (ObjectDisposedException) From 9cafb20fcbe650580d5d1bea6510319cf61e5a5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:50:05 +0900 Subject: [PATCH 0743/1400] Move file missing logging to a better location, and log actual filenames to logs --- osu.Game/Database/LegacyArchiveExporter.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 01d00b311d..f148d6951d 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -54,20 +54,14 @@ namespace osu.Game.Database using (var stream = UserFileStorage.GetStream(file.File.GetStoragePath())) { - // Sometimes we cannot find the file(probably deleted by the user), so we handle this and post a error. if (stream == null) { - // Only pop up once to prevent spam. - if (!fileMissing) - { - Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); - fileMissing = true; - } - } - else - { - writer.Write(file.Filename, stream); + Logger.Log($"File {file.Filename} is missing in local storage and will not be included in the export", LoggingTarget.Database); + fileMissing = true; + continue; } + + writer.Write(file.Filename, stream); } if (notification != null) @@ -77,6 +71,12 @@ namespace osu.Game.Database i++; } + + // Only pop up once to prevent spam. + if (fileMissing) + { + Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); + } } catch (ObjectDisposedException) { From fc2d2de34c3b20fb012dadde3bf029686f9005b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 16:53:27 +0900 Subject: [PATCH 0744/1400] Fix notification text not including export filename --- osu.Game/Database/LegacyExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index bb2143178b..e5df2a4337 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -112,7 +112,7 @@ namespace osu.Game.Database ProgressNotification notification = new ProgressNotification { State = ProgressNotificationState.Active, - Text = "Exporting...", + Text = $"Exporting {itemFilename}...", }; PostNotification?.Invoke(notification); From 4ccfebc02be0c0c1275d8ae76344f11d18be1a79 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 21:01:10 +0900 Subject: [PATCH 0745/1400] Simplify `ExportToStreamAsync` implementation --- osu.Game/Database/LegacyExporter.cs | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index e5df2a4337..bc86420cd2 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Extensions; using osu.Game.Overlays.Notifications; @@ -159,30 +158,8 @@ namespace osu.Game.Database /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. /// Whether the export was successful - public Task ExportToStreamAsync(Live model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) - { - return Task.Run(() => - { - model.PerformRead(s => - { - ExportToStream(s, stream, notification, cancellationToken); - }); - }, cancellationToken).ContinueWith(t => - { - if (cancellationToken.IsCancellationRequested) - { - return false; - } - - if (t.IsFaulted) - { - Logger.Error(t.Exception, "An error occurred while exporting", LoggingTarget.Database); - throw t.Exception!; - } - - return true; - }, CancellationToken.None); - } + public Task ExportToStreamAsync(Live model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) => + Task.Run(() => { model.PerformRead(s => ExportToStream(s, stream, notification, cancellationToken)); }, cancellationToken); /// /// Exports model to Stream. From 2a3e03695cad820002999e420797de7a0faf4cba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 21:04:13 +0900 Subject: [PATCH 0746/1400] Simplify `ExportAsync`, remove weird dedupe logic and unnecessary return `success` code --- osu.Game/Database/LegacyExporter.cs | 60 ++++++++--------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index bc86420cd2..a8d2fb116c 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -45,9 +45,6 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } - // Store the model being exporting. - private static readonly List> exporting_models = new List>(); - /// /// Construct exporter. /// Create a new exporter for each export, otherwise it will cause confusing notifications. @@ -69,10 +66,8 @@ namespace osu.Game.Database /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. /// /// - public Task ExportAsync(TModel model, RealmAccess realm, CancellationToken cancellationToken = default) - { - return ExportAsync(model.ToLive(realm), cancellationToken); - } + public Task ExportAsync(TModel model, RealmAccess realm, CancellationToken cancellationToken = default) => + ExportAsync(model.ToLive(realm), cancellationToken); /// /// Export the model to default folder. @@ -83,71 +78,46 @@ namespace osu.Game.Database /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. /// /// - public async Task ExportAsync(Live model, CancellationToken cancellationToken = default) + public async Task ExportAsync(Live model, CancellationToken cancellationToken = default) { - // check if the model is being exporting already - if (!exporting_models.Contains(model)) - { - exporting_models.Add(model); - } - else - { - // model is being exported - return false; - } - string itemFilename = model.PerformRead(s => GetFilename(s).GetValidFilename()); if (itemFilename.Length > MAX_FILENAME_LENGTH - FileExtension.Length) itemFilename = itemFilename.Remove(MAX_FILENAME_LENGTH - FileExtension.Length); - IEnumerable existingExports = - exportStorage - .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") - .Concat(exportStorage.GetDirectories(string.Empty)); + IEnumerable existingExports = exportStorage + .GetFiles(string.Empty, $"{itemFilename}*{FileExtension}") + .Concat(exportStorage.GetDirectories(string.Empty)); + string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{FileExtension}"); - bool success; ProgressNotification notification = new ProgressNotification { State = ProgressNotificationState.Active, Text = $"Exporting {itemFilename}...", }; + PostNotification?.Invoke(notification); try { using (var stream = exportStorage.CreateFileSafely(filename)) { - success = await ExportToStreamAsync(model, stream, notification, - cancellationToken == CancellationToken.None ? notification.CancellationToken : cancellationToken).ConfigureAwait(false); + await ExportToStreamAsync(model, stream, notification, cancellationToken == CancellationToken.None ? notification.CancellationToken : cancellationToken).ConfigureAwait(false); } } catch { notification.State = ProgressNotificationState.Cancelled; + + // cleanup if export is failed or canceled. + exportStorage.Delete(filename); throw; } - finally - { - // Determines whether to export repeatedly, so he must be removed from the list at the end whether there is a error. - exporting_models.Remove(model); - } - // cleanup if export is failed or canceled. - if (!success) - { - notification.State = ProgressNotificationState.Cancelled; - exportStorage.Delete(filename); - } - else - { - notification.CompletionText = $"Exported {itemFilename}! Click to view."; - notification.CompletionClickAction = () => exportStorage.PresentFileExternally(filename); - notification.State = ProgressNotificationState.Completed; - } - - return success; + notification.CompletionText = $"Exported {itemFilename}! Click to view."; + notification.CompletionClickAction = () => exportStorage.PresentFileExternally(filename); + notification.State = ProgressNotificationState.Completed; } /// From 5d78561aa36fb6dd2cbbdec343b7fcbb63c10683 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 21:05:57 +0900 Subject: [PATCH 0747/1400] Remove weird catch logic --- osu.Game/Database/LegacyArchiveExporter.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index f148d6951d..306ac5f6a4 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.IO; using System.Linq; using System.Threading; @@ -40,10 +39,8 @@ namespace osu.Game.Database /// The cancellation token. private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { - try + using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) { - using var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate)); - int i = 0; int fileCount = model.Files.Count(); bool fileMissing = false; @@ -78,14 +75,6 @@ namespace osu.Game.Database Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); } } - catch (ObjectDisposedException) - { - // outputStream may close before writing when request cancel. - if (cancellationToken.IsCancellationRequested) - return; - - throw; - } } } } From 747f912af5d49ffe56cd1a1cca75b0b42d86bf06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 21:08:01 +0900 Subject: [PATCH 0748/1400] Fix incorrect cancellation logic --- osu.Game/Database/LegacyExporter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index a8d2fb116c..906e2083ff 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -99,11 +99,13 @@ namespace osu.Game.Database PostNotification?.Invoke(notification); + using var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, notification.CancellationToken); + try { using (var stream = exportStorage.CreateFileSafely(filename)) { - await ExportToStreamAsync(model, stream, notification, cancellationToken == CancellationToken.None ? notification.CancellationToken : cancellationToken).ConfigureAwait(false); + await ExportToStreamAsync(model, stream, notification, linkedSource.Token).ConfigureAwait(false); } } catch From 490df8073ca1f0950f7f22dda30317ac1ae82003 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 May 2023 21:15:26 +0900 Subject: [PATCH 0749/1400] Fix one incorrect namespace syntax file --- .../Objects/Types/IHasSliderVelocity.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs index c0ac5036ee..80fd8dd8dc 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasSliderVelocity.cs @@ -3,17 +3,18 @@ using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Objects.Types; - -/// -/// A HitObject that has a slider velocity multiplier. -/// -public interface IHasSliderVelocity +namespace osu.Game.Rulesets.Objects.Types { /// - /// The slider velocity multiplier. + /// A HitObject that has a slider velocity multiplier. /// - double SliderVelocity { get; set; } + public interface IHasSliderVelocity + { + /// + /// The slider velocity multiplier. + /// + double SliderVelocity { get; set; } - BindableNumber SliderVelocityBindable { get; } + BindableNumber SliderVelocityBindable { get; } + } } From 4393e53b4310cc30d9301095cdbcfe3cd2dc7fcb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 5 May 2023 21:28:43 +0900 Subject: [PATCH 0750/1400] ExportToStream should be public --- osu.Game.Tests/Database/LegacyModelExporterTest.cs | 2 +- osu.Game/Database/LegacyArchiveExporter.cs | 2 +- osu.Game/Database/LegacyExporter.cs | 2 +- osu.Game/Database/LegacyScoreExporter.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Database/LegacyModelExporterTest.cs b/osu.Game.Tests/Database/LegacyModelExporterTest.cs index 2169bc73cd..0c4b0cc9c4 100644 --- a/osu.Game.Tests/Database/LegacyModelExporterTest.cs +++ b/osu.Game.Tests/Database/LegacyModelExporterTest.cs @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Database public string GetExtension() => FileExtension; - protected override void ExportToStream(TestModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) + public override void ExportToStream(TestModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { } diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 306ac5f6a4..1afa19a162 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -27,7 +27,7 @@ namespace osu.Game.Database { } - protected override void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) + public override void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) => exportZipArchive(model, outputStream, notification, cancellationToken); /// diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 906e2083ff..3b24ab4f4a 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -140,6 +140,6 @@ namespace osu.Game.Database /// The output stream to export to. /// The notification will displayed to the user /// The Cancellation token that can cancel the exporting. - protected abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default); + public abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default); } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index 927d36ea03..fe5d1e8b47 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -28,7 +28,7 @@ namespace osu.Game.Database protected override string FileExtension => ".osr"; - protected override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification? notification, CancellationToken cancellationToken = default) + public override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification? notification, CancellationToken cancellationToken = default) { var file = model.Files.SingleOrDefault(); if (file == null) From 71864fbb932b980931033d2e8808d90a569d2a7c Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Fri, 5 May 2023 21:29:06 +0900 Subject: [PATCH 0751/1400] remove meanless comment --- osu.Game/Database/LegacyArchiveExporter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 1afa19a162..19ccc13a29 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -69,7 +69,6 @@ namespace osu.Game.Database i++; } - // Only pop up once to prevent spam. if (fileMissing) { Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); From f536238554873f27cd8424e0a3547032b3c1e737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 5 May 2023 20:30:50 +0200 Subject: [PATCH 0752/1400] Use shorter copy --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 9192913fa0..e737d6b0ce 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key; double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2]; - AddHeader("Beatmap average velocity"); + AddHeader("Average velocity"); AddValue($"{medianSliderVelocity:#,0.00}x"); AddHeader("Most used velocity"); From e808a47811d0027f82037cbc5d58b0c7117cffba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 5 May 2023 20:33:27 +0200 Subject: [PATCH 0753/1400] Fix delegate leak --- .../Compose/Components/Timeline/DifficultyPointPiece.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index e737d6b0ce..13a1c30cfe 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -174,5 +174,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AddHeader("Velocity range"); AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + EditorBeatmap.TransactionBegan -= updateInspectorText; + EditorBeatmap.TransactionEnded -= updateInspectorText; + } } } From 7422b5285ce8e9631111c20ab9a1baf40d81152a Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 5 May 2023 22:41:30 +0300 Subject: [PATCH 0754/1400] Fix wrong filtering in testing --- .../UserInterface/TestSceneModColumn.cs | 2 +- .../TestSceneModSelectOverlay.cs | 12 ++++---- osu.Game/Overlays/Mods/ModColumn.cs | 3 +- osu.Game/Overlays/Mods/ModPanel.cs | 30 +++++++++++++++++-- osu.Game/Overlays/Mods/ModState.cs | 5 ++++ osu.Game/Overlays/Mods/SelectAllModsButton.cs | 2 +- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index ec6084aa8e..2ae95a3a09 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -291,7 +291,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) - modState.MatchingFilter.Value = filter?.Invoke(modState.Mod) == false; + modState.MatchingFilter.Value = filter?.Invoke(modState.Mod) ?? true; } private partial class TestModColumn : ModColumn diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 9c6ec653e9..006a6abbc2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -431,15 +431,15 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); changeRuleset(0); - AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.MatchingFilter)); + AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.IsValid)); AddStep("make double time invalid", () => modSelectOverlay.IsValidMod = m => !(m is OsuModDoubleTime)); - AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => !panel.MatchingFilter)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => panel.MatchingFilter)); + AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => !panel.IsValid)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => panel.IsValid)); AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = _ => true); - AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.MatchingFilter)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => panel.MatchingFilter)); + AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.IsValid)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => panel.IsValid)); } [Test] @@ -465,7 +465,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set ruleset", () => Ruleset.Value = testRuleset.RulesetInfo); waitForColumnLoad(); - AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).MatchingFilter); + AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).IsValid); } [Test] diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 5da57ee4ed..c8822d78fd 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -47,6 +47,7 @@ namespace osu.Game.Overlays.Mods { mod.Active.BindValueChanged(_ => updateState()); mod.MatchingFilter.BindValueChanged(_ => updateState()); + mod.ValidForSelection.BindValueChanged(_ => updateState()); } updateState(); @@ -145,7 +146,7 @@ namespace osu.Game.Overlays.Mods private void updateState() { - Alpha = availableMods.All(mod => !mod.MatchingFilter.Value) ? 0 : 1; + Alpha = availableMods.All(mod => !mod.MatchingFilter.Value || !mod.ValidForSelection.Value) ? 0 : 1; if (toggleAllCheckbox != null && !SelectionAnimationRunning) { diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index a5ff52dfd2..cd94226d8f 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -56,7 +56,8 @@ namespace osu.Game.Overlays.Mods { base.LoadComplete(); - canBeShown.BindTo(modState.ValidForSelection); + modState.ValidForSelection.BindValueChanged(_ => updateFilterState()); + modState.MatchingFilter.BindValueChanged(_ => updateFilterState(), true); } protected override void Select() @@ -71,6 +72,23 @@ namespace osu.Game.Overlays.Mods Active.Value = false; } + /// + /// Determine if is valid and can be shown + /// + public bool IsValid => modState.IsValid; + + public bool ValidForSelection + { + get => modState.ValidForSelection.Value; + set + { + if (modState.ValidForSelection.Value == value) + return; + + modState.ValidForSelection.Value = value; + } + } + #region Filtering support public override IEnumerable FilterTerms => new[] @@ -89,13 +107,21 @@ namespace osu.Game.Overlays.Mods return; modState.MatchingFilter.Value = value; - this.FadeTo(value ? 1 : 0); } } + /// + /// This property is always because it affects search result + /// private readonly BindableBool canBeShown = new BindableBool(true); + IBindable IConditionalFilterable.CanBeShown => canBeShown; + private void updateFilterState() + { + this.FadeTo(IsValid ? 1 : 0); + } + #endregion } } diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index 35b264fe71..be770ec937 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.cs @@ -38,6 +38,11 @@ namespace osu.Game.Overlays.Mods /// public BindableBool ValidForSelection { get; } = new BindableBool(true); + /// + /// Determine if is valid and can be shown + /// + public bool IsValid => MatchingFilter.Value && ValidForSelection.Value; + /// /// Whether the mod is matching the current filter, i.e. it is available for user selection. /// diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index 212563de7d..dad4f7b629 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Mods { Enabled.Value = availableMods.Value .SelectMany(pair => pair.Value) - .Any(modState => !modState.Active.Value && !modState.MatchingFilter.Value); + .Any(modState => !modState.Active.Value && modState.IsValid); } public bool OnPressed(KeyBindingPressEvent e) From a226caff560afc897e3c596e08a0fcfa74b6a3a0 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 6 May 2023 11:09:44 +0300 Subject: [PATCH 0755/1400] Fix testing --- .../TestSceneMultiplayerMatchSubScreen.cs | 2 +- .../Visual/UserInterface/TestSceneModColumn.cs | 14 +++++++------- .../Overlays/Mods/Input/ClassicModHotkeyHandler.cs | 2 +- .../Mods/Input/SequentialModHotkeyHandler.cs | 2 +- osu.Game/Overlays/Mods/ModColumn.cs | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 8fd16fb723..40acea475b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -203,7 +203,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("mod select contains only double time mod", () => this.ChildrenOfType().Single().UserModsSelectOverlay .ChildrenOfType() - .SingleOrDefault(panel => panel.MatchingFilter)?.Mod is OsuModDoubleTime); + .SingleOrDefault(panel => panel.IsValid)?.Mod is OsuModDoubleTime); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 2ae95a3a09..fc1db3c644 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -106,26 +106,26 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.MatchingFilter) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.IsValid) == 2); clickToggle(); AddUntilStep("wait for animation", () => !column.SelectionAnimationRunning); - AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => panel.MatchingFilter)); + AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => panel.IsValid)); AddStep("unset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.MatchingFilter)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); AddAssert("checkbox not selected", () => !column.ChildrenOfType().Single().Current.Value); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.MatchingFilter) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.IsValid) == 2); AddAssert("checkbox selected", () => column.ChildrenOfType().Single().Current.Value); AddStep("filter out everything", () => setFilter(_ => false)); - AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => !panel.MatchingFilter)); + AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => !panel.IsValid)); AddUntilStep("checkbox hidden", () => !column.ChildrenOfType().Single().IsPresent); AddStep("inset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.MatchingFilter)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); AddUntilStep("checkbox visible", () => column.ChildrenOfType().Single().IsPresent); void clickToggle() => AddStep("click toggle", () => @@ -291,7 +291,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) - modState.MatchingFilter.Value = filter?.Invoke(modState.Mod) ?? true; + modState.ValidForSelection.Value = filter?.Invoke(modState.Mod) ?? true; } private partial class TestModColumn : ModColumn diff --git a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs index 566e741880..343f7242f1 100644 --- a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Mods.Input if (!mod_type_lookup.TryGetValue(e.Key, out var typesToMatch)) return false; - var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && modState.MatchingFilter.Value).ToArray(); + var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && modState.IsValid).ToArray(); if (matchingMods.Length == 0) return false; diff --git a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs index b4ec8ad4c8..cbfa96307d 100644 --- a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Mods.Input if (index < 0) return false; - var modState = availableMods.Where(modState => modState.MatchingFilter.Value).ElementAtOrDefault(index); + var modState = availableMods.Where(modState => modState.IsValid).ElementAtOrDefault(index); if (modState == null) return false; diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index c8822d78fd..b53e621759 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -146,12 +146,12 @@ namespace osu.Game.Overlays.Mods private void updateState() { - Alpha = availableMods.All(mod => !mod.MatchingFilter.Value || !mod.ValidForSelection.Value) ? 0 : 1; + Alpha = availableMods.All(mod => !mod.IsValid) ? 0 : 1; if (toggleAllCheckbox != null && !SelectionAnimationRunning) { - toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.MatchingFilter.Value) ? 1 : 0; - toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.MatchingFilter.Value).All(panel => panel.Active.Value); + toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.IsValid) ? 1 : 0; + toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.IsValid).All(panel => panel.Active.Value); } } @@ -196,7 +196,7 @@ namespace osu.Game.Overlays.Mods { pendingSelectionOperations.Clear(); - foreach (var button in availableMods.Where(b => !b.Active.Value && b.MatchingFilter.Value)) + foreach (var button in availableMods.Where(b => !b.Active.Value && b.IsValid)) pendingSelectionOperations.Enqueue(() => button.Active.Value = true); } From cbb9f0100e2dad808ae7309d74b8f3bb701aa5d1 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 6 May 2023 11:27:06 +0300 Subject: [PATCH 0756/1400] Update `PopIn` and `PopOut` filtering. Expose `SearchTerm` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d2af305d68..cb8eddca62 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -64,6 +64,21 @@ namespace osu.Game.Overlays.Mods } } + /// + /// Search term applied on mod overlay + /// + public string SearchTerm + { + get => searchTextBox.Current.Value; + set + { + if (searchTextBox.Current.Value == value) + return; + + searchTextBox.Current.Value = value; + } + } + /// /// Whether the total score multiplier calculated from the current selected set of mods should be shown. /// @@ -494,7 +509,7 @@ namespace osu.Game.Overlays.Mods { var column = columnFlow[i].Column; - bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => !modState.MatchingFilter.Value); + bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => !modState.IsValid); double delay = allFiltered ? 0 : nonFilteredColumnCount * 30; double duration = allFiltered ? 0 : fade_in_duration; @@ -556,7 +571,7 @@ namespace osu.Game.Overlays.Mods if (column is ModColumn modColumn) { - allFiltered = modColumn.AvailableMods.All(modState => !modState.MatchingFilter.Value); + allFiltered = modColumn.AvailableMods.All(modState => !modState.IsValid); modColumn.FlushPendingSelections(); } From 5aca3a78dac91fb940d3ccdf82e077db374f708a Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 6 May 2023 12:21:32 +0300 Subject: [PATCH 0757/1400] Add basic tests for external search --- .../UserInterface/TestSceneModColumn.cs | 43 ++++++++++++ .../TestSceneModSelectOverlay.cs | 65 +++++++++++++++++-- 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index fc1db3c644..394a38fe5d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -288,6 +288,49 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("no change", () => this.ChildrenOfType().Count(panel => panel.Active.Value) == 2); } + [Test] + public void TestApplySearchTerms() + { + Mod hidden = getExampleModsFor(ModType.DifficultyIncrease).Where(modState => modState.Mod is ModHidden).Select(modState => modState.Mod).Single(); + + ModColumn column = null!; + AddStep("create content", () => Child = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(30), + Child = column = new ModColumn(ModType.DifficultyIncrease, false) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AvailableMods = getExampleModsFor(ModType.DifficultyIncrease) + } + }); + + applySearchAndAssert(hidden.Name); + + clearSearch(); + + applySearchAndAssert(hidden.Acronym); + + clearSearch(); + + applySearchAndAssert(hidden.Description.ToString()); + + void applySearchAndAssert(string searchTerm) + { + AddStep("search by mod name", () => column.SearchTerm = searchTerm); + + AddAssert("only hidden is visible", () => column.ChildrenOfType().Where(panel => panel.IsValid).All(panel => panel.Mod is ModHidden)); + } + + void clearSearch() + { + AddStep("clear search", () => column.SearchTerm = string.Empty); + + AddAssert("all mods are visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); + } + } + private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 006a6abbc2..e8a835a330 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -521,8 +521,11 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mod select hidden", () => modSelectOverlay.State.Value == Visibility.Hidden); } + /// + /// Internal search applies from code by setting + /// [Test] - public void TestColumnHiding() + public void TestColumnHidingOnInternalSearch() { AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay { @@ -551,6 +554,56 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("3 columns visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 3); } + /// + /// External search applies by user by entering search term into search bar + /// + [Test] + public void TestColumnHidingOnExternalSearch() + { + AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.Both, + State = { Value = Visibility.Visible }, + SelectedMods = { BindTarget = SelectedMods } + }); + waitForColumnLoad(); + changeRuleset(0); + + AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); + + AddStep("set search", () => modSelectOverlay.SearchTerm = "HD"); + AddAssert("one column visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 1); + + AddStep("filter out everything", () => modSelectOverlay.SearchTerm = "Some long search term with no matches"); + AddAssert("no columns visible", () => this.ChildrenOfType().All(col => !col.IsPresent)); + + AddStep("clear search bar", () => modSelectOverlay.SearchTerm = ""); + AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); + } + + [Test] + public void TestHidingOverlayClearsSearch() + { + AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.Both, + State = { Value = Visibility.Visible }, + SelectedMods = { BindTarget = SelectedMods } + }); + waitForColumnLoad(); + changeRuleset(0); + + AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); + + AddStep("set search", () => modSelectOverlay.SearchTerm = "fail"); + AddAssert("one column visible", () => this.ChildrenOfType().Count(col => col.IsPresent) == 2); + + AddStep("hide", () => modSelectOverlay.Hide()); + AddStep("show", () => modSelectOverlay.Show()); + + AddAssert("all columns visible", () => this.ChildrenOfType().All(col => col.IsPresent)); + } + [Test] public void TestColumnHidingOnRulesetChange() { @@ -605,12 +658,10 @@ namespace osu.Game.Tests.Visual.UserInterface { public override string ShortName => "unimplemented"; - public override IEnumerable GetModsFor(ModType type) - { - if (type == ModType.Conversion) return base.GetModsFor(type).Concat(new[] { new TestUnimplementedMod() }); - - return base.GetModsFor(type); - } + public override IEnumerable GetModsFor(ModType type) => + type == ModType.Conversion + ? base.GetModsFor(type).Concat(new[] { new TestUnimplementedMod() }) + : base.GetModsFor(type); } } } From 7d1e73e36dcf67a5052395aa84f9c241d2d6696b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 4 May 2023 21:24:31 +0200 Subject: [PATCH 0758/1400] Add workflow for automated osu-web mod definition updates --- .../workflows/update-web-mod-definitions.yml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/update-web-mod-definitions.yml diff --git a/.github/workflows/update-web-mod-definitions.yml b/.github/workflows/update-web-mod-definitions.yml new file mode 100644 index 0000000000..32d3d37ffe --- /dev/null +++ b/.github/workflows/update-web-mod-definitions.yml @@ -0,0 +1,53 @@ +name: Update osu-web mod definitions +on: + push: + tags: + - '*' + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + update-mod-definitions: + name: Update osu-web mod definitions + runs-on: ubuntu-latest + steps: + - name: Install .NET 6.0.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: "6.0.x" + + - name: Checkout ppy/osu + uses: actions/checkout@v3 + with: + path: osu + + - name: Checkout ppy/osu-tools + uses: actions/checkout@v3 + with: + repository: ppy/osu-tools + path: osu-tools + + - name: Checkout ppy/osu-web + uses: actions/checkout@v3 + with: + repository: ppy/osu-web + path: osu-web + + - name: Setup local game checkout for tools + run: ./UseLocalOsu.sh + working-directory: ./osu-tools + + - name: Regenerate mod definitions + run: dotnet run --project PerformanceCalculator -- mods > ../osu-web/database/mods.json + working-directory: ./osu-tools + + - name: Create pull request with changes + uses: peter-evans/create-pull-request@v5 + with: + title: Update mod definitions + body: "This PR has been auto-generated to update the mod definitions to match ppy/osu@${{ github.ref_name }}." + branch: update-mod-definitions + commit-message: Update mod definitions + path: osu-web + token: ${{ secrets.OSU_WEB_PULL_REQUEST_PAT }} From 52e5835be6e8ae544ec9917d67409a2493b04c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 14:52:33 +0200 Subject: [PATCH 0759/1400] Document and retouch `ReportPopover` --- .../Graphics/UserInterfaceV2/ReportPopover.cs | 32 +++++++++++++------ osu.Game/Overlays/Chat/ReportChatPopover.cs | 5 +-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs index a5c60bb9e6..393cdef76d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs @@ -16,17 +16,29 @@ using osuTK; namespace osu.Game.Graphics.UserInterfaceV2 { - public abstract partial class ReportPopover : OsuPopover - where T : struct, Enum + /// + /// A generic popover for sending an online report about something. + /// + /// An enumeration type with all valid reasons for the report. + public abstract partial class ReportPopover : OsuPopover + where TReportReason : struct, Enum { - public Action? Action; + /// + /// The action to run when the report is finalised. + /// The arguments to this action are: the reason for the report, and an optional additional comment. + /// + public Action? Action; - private OsuEnumDropdown reasonDropdown = null!; + private OsuEnumDropdown reasonDropdown = null!; private OsuTextBox commentsTextBox = null!; private RoundedButton submitButton = null!; private readonly LocalisableString header; + /// + /// Creates a new . + /// + /// The text to display in the header of the popover. protected ReportPopover(LocalisableString headerString) { header = headerString; @@ -68,7 +80,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 { RelativeSizeAxes = Axes.X, Height = 40, - Child = reasonDropdown = new OsuEnumDropdown + Child = reasonDropdown = new OsuEnumDropdown { RelativeSizeAxes = Axes.X } @@ -110,12 +122,12 @@ namespace osu.Game.Graphics.UserInterfaceV2 private void updateStatus() { - submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(commentsTextBox.Current.Value) || CheckCanSubmitEmptyComment(reasonDropdown.Current.Value); + submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(commentsTextBox.Current.Value) || IsCommentRequired(reasonDropdown.Current.Value); } - protected virtual bool CheckCanSubmitEmptyComment(T reason) - { - return false; - } + /// + /// Determines whether an additional comment is required for submitting the report with the supplied . + /// + protected virtual bool IsCommentRequired(TReportReason reason) => false; } } diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index f02e52eb2e..625f44505b 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -27,10 +27,7 @@ namespace osu.Game.Overlays.Chat Action = report; } - protected override bool CheckCanSubmitEmptyComment(ChatReportReason reason) - { - return reason != ChatReportReason.Other; - } + protected override bool IsCommentRequired(ChatReportReason reason) => reason != ChatReportReason.Other; private void report(ChatReportReason reason, string comments) { From 6b4050ea5253bd70c1a4c2d691d7c49d2c53fbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 15:01:57 +0200 Subject: [PATCH 0760/1400] Remove invalid report reason (and add osu-web references) --- osu.Game/Overlays/Chat/ChatReportReason.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatReportReason.cs b/osu.Game/Overlays/Chat/ChatReportReason.cs index 55593d29ad..5fda11b61e 100644 --- a/osu.Game/Overlays/Chat/ChatReportReason.cs +++ b/osu.Game/Overlays/Chat/ChatReportReason.cs @@ -7,6 +7,11 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat { + /// + /// References: + /// https://github.com/ppy/osu-web/blob/0a41b13acf5f47bb0d2b08bab42a9646b7ab5821/app/Models/UserReport.php#L50 + /// https://github.com/ppy/osu-web/blob/0a41b13acf5f47bb0d2b08bab42a9646b7ab5821/app/Models/UserReport.php#L39 + /// public enum ChatReportReason { [Description("Insulting People")] @@ -17,10 +22,6 @@ namespace osu.Game.Overlays.Chat [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsSpam))] Spam, - [Description("Cheating")] - [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsCheating))] - FoulPlay, - [Description("Unwanted Content")] [LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ReportOptionsUnwantedContent))] UnwantedContent, From fba3c587cfd11278247840de290463dbc19e1201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 15:26:29 +0200 Subject: [PATCH 0761/1400] Add test coverage for info message failing to display --- osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs index 99ce837665..55e6b54af7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs @@ -648,6 +648,7 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("Overlay closed", () => !this.ChildrenOfType().Any()); AddStep("Complete request", () => requestLock.Set()); AddUntilStep("Request sent", () => request != null); + AddUntilStep("Info message displayed", () => channelManager.CurrentChannel.Value.Messages.Last(), () => Is.InstanceOf(typeof(InfoMessage))); } private void joinTestChannel(int i) From 1da5e69d5a6aeb573d0d538e84257ecbf6752455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 15:27:27 +0200 Subject: [PATCH 0762/1400] Fix API success callback scheduling to dead drawable --- osu.Game/Overlays/Chat/ReportChatPopover.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index 625f44505b..999c76ca10 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -33,10 +33,7 @@ namespace osu.Game.Overlays.Chat { var request = new ChatReportRequest(message.Id, reason, comments); - request.Success += () => Schedule(() => - { - channelManager.CurrentChannel.Value.AddNewMessages(new InfoMessage(UsersStrings.ReportThanks.ToString())); - }); + request.Success += () => channelManager.CurrentChannel.Value.AddNewMessages(new InfoMessage(UsersStrings.ReportThanks.ToString())); api.Queue(request); } From 3942281d13a4a23b3d8efbd2aed96e155831753d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 15:34:55 +0200 Subject: [PATCH 0763/1400] Fix back-to-front logic --- osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs | 4 ++-- osu.Game/Overlays/Chat/ReportChatPopover.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs index 393cdef76d..7b3c32d60d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/ReportPopover.cs @@ -122,12 +122,12 @@ namespace osu.Game.Graphics.UserInterfaceV2 private void updateStatus() { - submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(commentsTextBox.Current.Value) || IsCommentRequired(reasonDropdown.Current.Value); + submitButton.Enabled.Value = !string.IsNullOrWhiteSpace(commentsTextBox.Current.Value) || !IsCommentRequired(reasonDropdown.Current.Value); } /// /// Determines whether an additional comment is required for submitting the report with the supplied . /// - protected virtual bool IsCommentRequired(TReportReason reason) => false; + protected virtual bool IsCommentRequired(TReportReason reason) => true; } } diff --git a/osu.Game/Overlays/Chat/ReportChatPopover.cs b/osu.Game/Overlays/Chat/ReportChatPopover.cs index 999c76ca10..265a17c799 100644 --- a/osu.Game/Overlays/Chat/ReportChatPopover.cs +++ b/osu.Game/Overlays/Chat/ReportChatPopover.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Chat Action = report; } - protected override bool IsCommentRequired(ChatReportReason reason) => reason != ChatReportReason.Other; + protected override bool IsCommentRequired(ChatReportReason reason) => reason == ChatReportReason.Other; private void report(ChatReportReason reason, string comments) { From e75ff33d629dfe4f8e368026ec55010637097479 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 May 2023 23:10:09 +0900 Subject: [PATCH 0764/1400] Remove redundant xmldoc and reword some remaining --- osu.Game/Database/LegacyExporter.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 3b24ab4f4a..468370809a 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -16,7 +16,7 @@ using Realms; namespace osu.Game.Database { /// - /// A class which handles exporting legacy user data of a single type from osu-stable. + /// Handles exporting models to files for sharing / consumption outside the game. /// public abstract class LegacyExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey @@ -45,11 +45,6 @@ namespace osu.Game.Database public Action? PostNotification { get; set; } - /// - /// Construct exporter. - /// Create a new exporter for each export, otherwise it will cause confusing notifications. - /// - /// Storage for storing exported files. Basically it is used to provide export stream protected LegacyExporter(Storage storage) { exportStorage = storage.GetStorageForDirectory(@"exports"); From 0d095c4bb703304b2df127db32de69ef3c69bef1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 May 2023 23:10:18 +0900 Subject: [PATCH 0765/1400] Remove non-`Live` pathway --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Database/LegacyExporter.cs | 13 ------------- osu.Game/Scoring/ScoreManager.cs | 2 +- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e87e71ae33..61b234d88a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -400,7 +400,7 @@ namespace osu.Game.Beatmaps public Task?> ImportAsUpdate(ProgressNotification notification, ImportTask importTask, BeatmapSetInfo original) => beatmapImporter.ImportAsUpdate(notification, importTask, original); - public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap, Realm); + public Task Export(BeatmapSetInfo beatmap) => beatmapExporter.ExportAsync(beatmap.ToLive(Realm)); private void updateHashAndMarkDirty(BeatmapSetInfo setInfo) { diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index 468370809a..bd38e38888 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -51,19 +51,6 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } - /// - /// Export the model to default folder. - /// - /// The model should export. - /// Realm that convert model to Live. - /// - /// The Cancellation token that can cancel the exporting. - /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. - /// - /// - public Task ExportAsync(TModel model, RealmAccess realm, CancellationToken cancellationToken = default) => - ExportAsync(model.ToLive(realm), cancellationToken); - /// /// Export the model to default folder. /// diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 5e432b6a96..3e6d09b74a 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -193,7 +193,7 @@ namespace osu.Game.Scoring public Task>> Import(ProgressNotification notification, ImportTask[] tasks, ImportParameters parameters = default) => scoreImporter.Import(notification, tasks); - public Task Export(ScoreInfo score) => scoreExporter.ExportAsync(score, Realm); + public Task Export(ScoreInfo score) => scoreExporter.ExportAsync(score.ToLive(Realm)); public Task> ImportAsUpdate(ProgressNotification notification, ImportTask task, ScoreInfo original) => scoreImporter.ImportAsUpdate(notification, task, original); From 38ebce8ee978738fbc1ccf1f57f07ad8b8c00d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 16:21:48 +0200 Subject: [PATCH 0766/1400] Update framework again --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 59bef84bd2..e9ecbaa10b 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 404fbada95..7ab9810ab5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index c4df0a2347..bfa0dc63bb 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 808a44ac0c33377aae9b37ab64bd27d3049cb22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 16:23:00 +0200 Subject: [PATCH 0767/1400] Resolve code quality inspection --- osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs index e951197643..555610a3b6 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuResumeOverlay.cs @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Osu.UI localCursorContainer?.Expire(); localCursorContainer = null; - GameplayCursor?.ActiveCursor?.Show(); + GameplayCursor?.ActiveCursor.Show(); } protected override bool OnHover(HoverEvent e) => true; From d2591368a6f21496fb4a00d326d0aac737f6a6d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 6 May 2023 23:53:35 +0900 Subject: [PATCH 0768/1400] More xmldoc fixes --- osu.Game/Database/LegacyArchiveExporter.cs | 9 +---- osu.Game/Database/LegacyExporter.cs | 38 ++++++++++------------ 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 19ccc13a29..d18c6b1497 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -17,7 +17,7 @@ using Logger = osu.Framework.Logging.Logger; namespace osu.Game.Database { /// - /// An exporter which handles the common scenario of exporting a model to a zip-based archive, usually with a custom file extension. + /// Handles the common scenario of exporting a model to a zip-based archive, usually with a custom file extension. /// public abstract class LegacyArchiveExporter : LegacyExporter where TModel : RealmObject, IHasNamedFiles, IHasGuidPrimaryKey @@ -30,13 +30,6 @@ namespace osu.Game.Database public override void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) => exportZipArchive(model, outputStream, notification, cancellationToken); - /// - /// Exports an item to Stream as a legacy (.zip based) package. - /// - /// The model to be exported. - /// The output stream to export to. - /// An optional target notification to update with ongoing export progress. - /// The cancellation token. private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index bd38e38888..c86873ea3f 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -52,14 +52,11 @@ namespace osu.Game.Database } /// - /// Export the model to default folder. + /// Exports a model to the default export location. + /// This will create a notification tracking the progress of the export, visible to the user. /// - /// The model should export. - /// - /// The Cancellation token that can cancel the exporting. - /// If specified CancellationToken, then use it. Otherwise use PostNotification's CancellationToken. - /// - /// + /// The model to export. + /// A cancellation token. public async Task ExportAsync(Live model, CancellationToken cancellationToken = default) { string itemFilename = model.PerformRead(s => GetFilename(s).GetValidFilename()); @@ -105,23 +102,22 @@ namespace osu.Game.Database } /// - /// Export model to stream. - /// - /// The model which have . - /// The stream to export. - /// The notification will displayed to the user - /// The Cancellation token that can cancel the exporting. - /// Whether the export was successful - public Task ExportToStreamAsync(Live model, Stream stream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) => - Task.Run(() => { model.PerformRead(s => ExportToStream(s, stream, notification, cancellationToken)); }, cancellationToken); - - /// - /// Exports model to Stream. + /// Exports a model to a provided stream. /// /// The model to export. /// The output stream to export to. - /// The notification will displayed to the user - /// The Cancellation token that can cancel the exporting. + /// An optional notification to be updated with export progress. + /// A cancellation token. + public Task ExportToStreamAsync(Live model, Stream outputStream, ProgressNotification? notification = null, CancellationToken cancellationToken = default) => + Task.Run(() => { model.PerformRead(s => ExportToStream(s, outputStream, notification, cancellationToken)); }, cancellationToken); + + /// + /// Exports a model to a provided stream. + /// + /// The model to export. + /// The output stream to export to. + /// An optional notification to be updated with export progress. + /// A cancellation token. public abstract void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default); } } From 64d7e0d8966fe1e1f922d5d20d4cc12119c4914f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 00:24:30 +0900 Subject: [PATCH 0769/1400] Rename `outputStream` variable to match base class --- osu.Game/Database/LegacyScoreExporter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index fe5d1e8b47..f0514d5350 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -28,14 +28,14 @@ namespace osu.Game.Database protected override string FileExtension => ".osr"; - public override void ExportToStream(ScoreInfo model, Stream stream, ProgressNotification? notification, CancellationToken cancellationToken = default) + public override void ExportToStream(ScoreInfo model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { var file = model.Files.SingleOrDefault(); if (file == null) return; using (var inputStream = UserFileStorage.GetStream(file.File.GetStoragePath())) - inputStream.CopyTo(stream); + inputStream.CopyTo(outputStream); } } } From 5e64d25b2a977bc0edb6538aa8929763050c2fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:26:51 +0200 Subject: [PATCH 0770/1400] Make `UserFileStorage` `readonly` again --- osu.Game/Database/LegacyExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index c86873ea3f..d1feb5f0cc 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -39,7 +39,7 @@ namespace osu.Game.Database /// protected abstract string FileExtension { get; } - protected Storage UserFileStorage; + protected readonly Storage UserFileStorage; private readonly Storage exportStorage; protected virtual string GetFilename(TModel item) => item.GetDisplayString(); From e0823ffd036b15fd202eb8169ab6c673d54b4951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:29:08 +0200 Subject: [PATCH 0771/1400] Move lower and xmldoc `GetFilename(TModel)` --- osu.Game/Database/LegacyExporter.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyExporter.cs b/osu.Game/Database/LegacyExporter.cs index d1feb5f0cc..f9164e34cd 100644 --- a/osu.Game/Database/LegacyExporter.cs +++ b/osu.Game/Database/LegacyExporter.cs @@ -41,7 +41,6 @@ namespace osu.Game.Database protected readonly Storage UserFileStorage; private readonly Storage exportStorage; - protected virtual string GetFilename(TModel item) => item.GetDisplayString(); public Action? PostNotification { get; set; } @@ -51,6 +50,16 @@ namespace osu.Game.Database UserFileStorage = storage.GetStorageForDirectory(@"files"); } + /// + /// Returns the baseline name of the file to which the will be exported. + /// + /// + /// The name of the file will be run through to eliminate characters + /// which are not permitted by various filesystems. + /// + /// The item being exported. + protected virtual string GetFilename(TModel item) => item.GetDisplayString(); + /// /// Exports a model to the default export location. /// This will create a notification tracking the progress of the export, visible to the user. From 3afe198d1dfa840d97830271c17dc94e8165c2c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:34:22 +0200 Subject: [PATCH 0772/1400] Remove weird single-use private method --- osu.Game/Database/LegacyArchiveExporter.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index d18c6b1497..4d5a1a767c 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -28,9 +28,6 @@ namespace osu.Game.Database } public override void ExportToStream(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) - => exportZipArchive(model, outputStream, notification, cancellationToken); - - private void exportZipArchive(TModel model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { using (var writer = new ZipWriter(outputStream, new ZipWriterOptions(CompressionType.Deflate))) { From a56a5d563c6c4d80b6fca50a21c8d1468f57c0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:38:05 +0200 Subject: [PATCH 0773/1400] Unify error message wording --- osu.Game/Database/LegacyArchiveExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 4d5a1a767c..4ba6025e6a 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -61,7 +61,7 @@ namespace osu.Game.Database if (fileMissing) { - Logger.Log("Some of model files are missing, they will not be included in the archive", LoggingTarget.Database, LogLevel.Error); + Logger.Log("Some files are missing in local storage and will not be included in the export", LoggingTarget.Database, LogLevel.Error); } } } From bb17b684b00da1a0f00e36d4c0e62098cba27f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:38:41 +0200 Subject: [PATCH 0774/1400] Rename flag --- osu.Game/Database/LegacyArchiveExporter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index 4ba6025e6a..feddf602b9 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Database { int i = 0; int fileCount = model.Files.Count(); - bool fileMissing = false; + bool anyFileMissing = false; foreach (var file in model.Files) { @@ -44,7 +44,7 @@ namespace osu.Game.Database if (stream == null) { Logger.Log($"File {file.Filename} is missing in local storage and will not be included in the export", LoggingTarget.Database); - fileMissing = true; + anyFileMissing = true; continue; } @@ -59,7 +59,7 @@ namespace osu.Game.Database i++; } - if (fileMissing) + if (anyFileMissing) { Logger.Log("Some files are missing in local storage and will not be included in the export", LoggingTarget.Database, LogLevel.Error); } From 3f63fd7f4d1f8ee6d87258bb309879e6f540cf8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:39:52 +0200 Subject: [PATCH 0775/1400] Reorder increment to make progress update less weird --- osu.Game/Database/LegacyArchiveExporter.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyArchiveExporter.cs b/osu.Game/Database/LegacyArchiveExporter.cs index feddf602b9..7689ffc13d 100644 --- a/osu.Game/Database/LegacyArchiveExporter.cs +++ b/osu.Game/Database/LegacyArchiveExporter.cs @@ -51,12 +51,12 @@ namespace osu.Game.Database writer.Write(file.Filename, stream); } + i++; + if (notification != null) { - notification.Progress = (float)(i + 1) / fileCount; + notification.Progress = (float)i / fileCount; } - - i++; } if (anyFileMissing) From 510484011c836cfd90c38c385fcaf8f4399a758c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 6 May 2023 19:42:28 +0200 Subject: [PATCH 0776/1400] Mark exporter extensions as untranslatable --- osu.Game/Database/LegacyBeatmapExporter.cs | 2 +- osu.Game/Database/LegacyScoreExporter.cs | 2 +- osu.Game/Database/LegacySkinExporter.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/LegacyBeatmapExporter.cs b/osu.Game/Database/LegacyBeatmapExporter.cs index e89d3da8c7..4ee8c0636e 100644 --- a/osu.Game/Database/LegacyBeatmapExporter.cs +++ b/osu.Game/Database/LegacyBeatmapExporter.cs @@ -13,6 +13,6 @@ namespace osu.Game.Database { } - protected override string FileExtension => ".osz"; + protected override string FileExtension => @".osz"; } } diff --git a/osu.Game/Database/LegacyScoreExporter.cs b/osu.Game/Database/LegacyScoreExporter.cs index f0514d5350..690070af85 100644 --- a/osu.Game/Database/LegacyScoreExporter.cs +++ b/osu.Game/Database/LegacyScoreExporter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Database return filename; } - protected override string FileExtension => ".osr"; + protected override string FileExtension => @".osr"; public override void ExportToStream(ScoreInfo model, Stream outputStream, ProgressNotification? notification, CancellationToken cancellationToken = default) { diff --git a/osu.Game/Database/LegacySkinExporter.cs b/osu.Game/Database/LegacySkinExporter.cs index 4775a54c13..14a3907916 100644 --- a/osu.Game/Database/LegacySkinExporter.cs +++ b/osu.Game/Database/LegacySkinExporter.cs @@ -13,6 +13,6 @@ namespace osu.Game.Database { } - protected override string FileExtension => ".osk"; + protected override string FileExtension => @".osk"; } } From e9d7cd7a795c85846895a0a98c295841f4ee00eb Mon Sep 17 00:00:00 2001 From: tsrk Date: Sat, 6 May 2023 19:08:30 +0100 Subject: [PATCH 0777/1400] feat(ArgonKeyCounter): flash key name --- osu.Game/Screens/Play/ArgonKeyCounter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs index 8635783d71..53305901ee 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounter.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -14,6 +14,7 @@ namespace osu.Game.Screens.Play public partial class ArgonKeyCounter : KeyCounter { private Circle inputIndicator = null!; + private OsuSpriteText keyNameText = null!; private OsuSpriteText countText = null!; // These values were taken from Figma @@ -42,7 +43,7 @@ namespace osu.Game.Screens.Play Height = line_height * scale_factor, Alpha = 0.5f }, - new OsuSpriteText + keyNameText = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -75,6 +76,7 @@ namespace osu.Game.Screens.Play protected override void Activate(bool forwardPlayback = true) { base.Activate(forwardPlayback); + keyNameText.FlashColour(Colour4.White, 200); inputIndicator.FadeIn().MoveToY(0).Then().MoveToY(3, 100, Easing.OutQuart); } From 4d235105d14d0b1ed91fedae09c6eaea6bdf13bf Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 7 May 2023 15:14:49 +0300 Subject: [PATCH 0778/1400] Convert `ModSearchContainer` to block-scoped namespace --- osu.Game/Overlays/Mods/ModSearchContainer.cs | 27 ++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs index 29cc7d8132..f9bf11d1f1 100644 --- a/osu.Game/Overlays/Mods/ModSearchContainer.cs +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -3,23 +3,24 @@ using osu.Framework.Graphics.Containers; -namespace osu.Game.Overlays.Mods; - -public partial class ModSearchContainer : SearchContainer +namespace osu.Game.Overlays.Mods { - /// - /// A string that should match the children - /// - public string ForcedSearchTerm + public partial class ModSearchContainer : SearchContainer { - get => SearchTerm; - set + /// + /// A string that should match the children + /// + public string ForcedSearchTerm { - if (value == SearchTerm) - return; + get => SearchTerm; + set + { + if (value == SearchTerm) + return; - SearchTerm = value; - Update(); + SearchTerm = value; + Update(); + } } } } From 60bad35145ac63e0d357d801c4a6fcf2a56a5812 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 7 May 2023 15:34:01 +0300 Subject: [PATCH 0779/1400] Remove weird update usage when 'deselect all' pressed --- osu.Game/Overlays/Mods/ModColumn.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index b53e621759..71d964c618 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -208,11 +208,12 @@ namespace osu.Game.Overlays.Mods pendingSelectionOperations.Clear(); foreach (var button in availableMods.Where(b => b.Active.Value)) - pendingSelectionOperations.Enqueue(() => button.Active.Value = false); - - //If column is hidden trigger selection manually - if (Alpha == 0f) - Update(); + { + if (Alpha == 0f) + button.Active.Value = false; //If column is hidden change state manually without any animation + else + pendingSelectionOperations.Enqueue(() => button.Active.Value = false); + } } /// From 4c3af6ecfed1f17dcf3f60193247c3394a4f152c Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 7 May 2023 15:50:21 +0300 Subject: [PATCH 0780/1400] Add test coverage for deselect all with filtered mods selected --- .../TestSceneModSelectOverlay.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index e8a835a330..8e4f437f44 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -502,6 +502,31 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("deselect all button disabled", () => !this.ChildrenOfType().Single().Enabled.Value); } + [Test] + public void TestDeselectAllViaButton_WithSearchApplied() + { + createScreen(); + changeRuleset(0); + + AddAssert("deselect all button disabled", () => !this.ChildrenOfType().Single().Enabled.Value); + + AddStep("select DT + HD + RD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden(), new OsuModRandom() }); + AddAssert("DT + HD + RD selected", () => modSelectOverlay.ChildrenOfType().Count(panel => panel.Active.Value) == 3); + AddAssert("deselect all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + + AddStep("apply search", () => modSelectOverlay.SearchTerm = "Easy"); + AddAssert("DT + HD + RD are hidden and selected", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.IsValid && panel.Active.Value) == 3); + AddAssert("deselect all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + + AddStep("click deselect all button", () => + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + }); + AddUntilStep("all mods deselected", () => !SelectedMods.Value.Any()); + AddAssert("deselect all button disabled", () => !this.ChildrenOfType().Single().Enabled.Value); + } + [Test] public void TestCloseViaBackButton() { From 8514b2758a69d344e59941427572c6b4d41db9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 7 May 2023 21:07:38 +0200 Subject: [PATCH 0781/1400] Fix rapid back button test failure --- osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 0d081e8138..193cec8907 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -700,7 +700,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("press escape twice rapidly", () => { InputManager.Key(Key.Escape); - InputManager.Key(Key.Escape); + Schedule(InputManager.Key, Key.Escape); }); pushEscape(); From 85d0c56cd28d8a299e570b891f3f208b7832674c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:00:45 +0900 Subject: [PATCH 0782/1400] Fix incorrect special style description text Closes https://github.com/ppy/osu/issues/23428. --- osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs index 508733ad14..98635c10a3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup specialStyle = new LabelledSwitchButton { Label = "Use special (N+1) style", - Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 5k (4+1) or 8key (7+1) configurations.", + Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6k (5+1) or 8k (7+1) configurations.", Current = { Value = Beatmap.BeatmapInfo.SpecialStyle } } }; From f7d44c3013f3bb11d6e2aa5476950e1d4036f3ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 12:32:38 +0900 Subject: [PATCH 0783/1400] Rename `SliderMultiplier` to `BaseSliderVelocity` --- .../Editor/TestSceneJuiceStreamPlacementBlueprint.cs | 2 +- .../Editor/TestSceneJuiceStreamSelectionBlueprint.cs | 2 +- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 4 ++-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Editor/TestSceneSliderStreamConversion.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Editor/TestSceneTaikoEditorSaving.cs | 4 ++-- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- .../Mods/TaikoModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 2 +- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 2 +- .../TestSceneHitObjectComposerDistanceSnapping.cs | 12 ++++++------ .../Visual/Editing/TestSceneDistanceSnapGrid.cs | 2 +- .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 4 ++-- .../Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- osu.Game/Beatmaps/BeatmapDifficulty.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs | 7 ++++--- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 6 +++--- 30 files changed, 49 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index 2426f8c886..e729a09a18 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor { var playable = base.GetPlayableBeatmap(); playable.Difficulty.SliderTickRate = 5; - playable.Difficulty.SliderMultiplier = velocity_factor * 10; + playable.Difficulty.BaseSliderVelocity = velocity_factor * 10; return playable; } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index beba5811fe..634e1f5cbb 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor X = x, Path = sliderPath, }; - EditorBeatmap.Difficulty.SliderMultiplier = velocity; + EditorBeatmap.Difficulty.BaseSliderVelocity = velocity; EditorBeatmap.Add(hitObject); EditorBeatmap.Update(hitObject); Assert.That(hitObject.Velocity, Is.EqualTo(velocity)); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 40dc7d2403..d1f3f06971 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index c91f07891c..71cb8964c3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 }, + Difficulty = new BeatmapDifficulty { CircleSize = 5, BaseSliderVelocity = 2 }, Ruleset = ruleset }, HitObjects = new List diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 169e99c90c..301ecd6d66 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Catch.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - velocityFactor = base_scoring_distance * difficulty.SliderMultiplier / timingPoint.BeatLength; - tickDistanceFactor = base_scoring_distance * difficulty.SliderMultiplier / difficulty.SliderTickRate; + velocityFactor = base_scoring_distance * difficulty.BaseSliderVelocity / timingPoint.BeatLength; + tickDistanceFactor = base_scoring_distance * difficulty.BaseSliderVelocity / difficulty.SliderTickRate; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 91b7be6e8f..ab6f5e8269 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy StartTime = (int)Math.Round(hitObject.StartTime); // This matches stable's calculation. - EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.SliderMultiplier); + EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.BaseSliderVelocity); SegmentDuration = (EndTime - StartTime) / SpanCount; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index af8758fb5e..cb38551a43 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Mania doesn't care about global velocity p.Velocity = 1; - p.BaseBeatLength *= Beatmap.Difficulty.SliderMultiplier; + p.BaseBeatLength *= Beatmap.Difficulty.BaseSliderVelocity; // For non-mania beatmap, speed changes should only happen through timing points if (!isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index 7579e8077b..b79d4efe1b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [SetUp] public void Setup() => Schedule(() => { - editorBeatmap.Difficulty.SliderMultiplier = 1; + editorBeatmap.Difficulty.BaseSliderVelocity = 1; editorBeatmap.ControlPointInfo.Clear(); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); snapProvider.DistanceSpacingMultiplier.Value = 1; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index a162d9a491..938e093489 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("change to these specific circumstances", () => { - EditorBeatmap.Difficulty.SliderMultiplier = 1; + EditorBeatmap.Difficulty.BaseSliderVelocity = 1; var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(slider.StartTime); timingPoint.BeatLength = 352.941176470588; slider.Path.ControlPoints[^1].Position = new Vector2(-110, 16); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4189f8ba1e..b86351e7cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index 93b26624de..d79ca28c8f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor [Test] public void TestTaikoSliderMultiplier() { - AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.BaseSliderVelocity = 2); SaveEditor(); @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor // therefore, ensure that we have that difficulty type by calling .CopyFrom(), which is a no-op if the type is already correct. var taikoDifficulty = new TaikoBeatmapConverter.TaikoMultiplierAppliedDifficulty(); taikoDifficulty.CopyFrom(EditorBeatmap.Difficulty); - return Precision.AlmostEquals(taikoDifficulty.SliderMultiplier, 2); + return Precision.AlmostEquals(taikoDifficulty.BaseSliderVelocity, 2); } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index e298e313df..932211695a 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps else beatLength = timingPoint.BeatLength; - double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate; + double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.BaseSliderVelocity / beatmap.Difficulty.SliderTickRate; // The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll. double taikoVelocity = sliderScoringPointDistance * beatmap.Difficulty.SliderTickRate; @@ -239,14 +239,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { base.CopyTo(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - other.SliderMultiplier /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + other.BaseSliderVelocity /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } public override void CopyFrom(IBeatmapDifficultyInfo other) { base.CopyFrom(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + BaseSliderVelocity *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } #endregion diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 99a064d35f..fe9c1f5815 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { base.ApplySettings(difficulty); - if (ScrollSpeed.Value != null) difficulty.SliderMultiplier *= ScrollSpeed.Value.Value; + if (ScrollSpeed.Value != null) difficulty.BaseSliderVelocity *= ScrollSpeed.Value.Value; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 009f2854f8..5aeb5a87d7 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.SliderMultiplier *= slider_multiplier; + difficulty.BaseSliderVelocity *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index ba41175461..0f68750535 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.SliderMultiplier *= slider_multiplier; + difficulty.BaseSliderVelocity *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index b4a12fd314..014fec9319 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = base_distance * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; tickSpacing = timingPoint.BeatLength / TickRate; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 2c4f193327..98ad6fc18d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.SliderMultiplier); + Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); Assert.AreEqual(2, difficulty.SliderTickRate); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 3764467047..11c5f2a2fc 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.SliderMultiplier); + Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); Assert.AreEqual(2, difficulty.SliderTickRate); } diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index 6399507aa0..ffbe16260b 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Editing BeatDivisor.Value = 1; - composer.EditorBeatmap.Difficulty.SliderMultiplier = 1; + composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 1; composer.EditorBeatmap.ControlPointInfo.Clear(); composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); }); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSliderMultiplier(float multiplier) { - AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier); + AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = multiplier); assertSnapDistance(100 * multiplier, null, true); } @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Editing assertDurationToDistance(500, 50); assertDurationToDistance(1000, 100); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertDurationToDistance(500, 100); assertDurationToDistance(1000, 200); @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Editing assertDistanceToDuration(50, 500); assertDistanceToDuration(100, 1000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertDistanceToDuration(100, 500); assertDistanceToDuration(200, 1000); @@ -174,7 +174,7 @@ namespace osu.Game.Tests.Editing assertSnappedDuration(200, 2000); assertSnappedDuration(250, 3000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertSnappedDuration(0, 0); assertSnappedDuration(50, 0); @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Editing assertSnappedDistance(200, 200); assertSnappedDistance(250, 200); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); assertSnappedDistance(50, 0); assertSnappedDistance(100, 0); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index 21b925a257..a99bd72e40 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Editing } }); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); - editorBeatmap.Difficulty.SliderMultiplier = 1; + editorBeatmap.Difficulty.BaseSliderVelocity = 1; } [SetUp] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 287b7d43b4..735af9493c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.SliderMultiplier = 2; + beatmap.Difficulty.BaseSliderVelocity = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.SliderMultiplier = 2; + beatmap.Difficulty.BaseSliderVelocity = 2; createTest(beatmap); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 114c554d28..28cc890fce 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, Ruleset = ruleset }, ControlPointInfo = controlPointInfo diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index f4bc5e7b77..cbea30f3b0 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// public const float DEFAULT_DIFFICULTY = 5; @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps public float OverallDifficulty { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; public float ApproachRate { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; - public double SliderMultiplier { get; set; } = 1; + public double BaseSliderVelocity { get; set; } = 1; public double SliderTickRate { get; set; } = 1; public BeatmapDifficulty() @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps difficulty.CircleSize = CircleSize; difficulty.OverallDifficulty = OverallDifficulty; - difficulty.SliderMultiplier = SliderMultiplier; + difficulty.BaseSliderVelocity = BaseSliderVelocity; difficulty.SliderTickRate = SliderTickRate; } @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps CircleSize = other.CircleSize; OverallDifficulty = other.OverallDifficulty; - SliderMultiplier = other.SliderMultiplier; + BaseSliderVelocity = other.BaseSliderVelocity; SliderTickRate = other.SliderTickRate; } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 4731a70753..e96e38d249 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -353,7 +353,7 @@ namespace osu.Game.Beatmaps CircleSize = decodedDifficulty.CircleSize, OverallDifficulty = decodedDifficulty.OverallDifficulty, ApproachRate = decodedDifficulty.ApproachRate, - SliderMultiplier = decodedDifficulty.SliderMultiplier, + BaseSliderVelocity = decodedDifficulty.BaseSliderVelocity, SliderTickRate = decodedDifficulty.SliderTickRate, }; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 5e98025c9a..891e627435 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,7 +384,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); + difficulty.BaseSliderVelocity = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index 7fbcca9adb..fffead3a6c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -155,8 +155,8 @@ namespace osu.Game.Beatmaps.Formats // Taiko adjusts the slider multiplier (see: LEGACY_TAIKO_VELOCITY_MULTIPLIER) writer.WriteLine(onlineRulesetID == 1 - ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") - : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier}")); + ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") + : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity}")); writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.Difficulty.SliderTickRate}")); } diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index dad9bbbd0b..bc2ee23da7 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps public interface IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// const float DEFAULT_DIFFICULTY = 5; @@ -34,9 +34,10 @@ namespace osu.Game.Beatmaps float ApproachRate { get; } /// - /// The slider multiplier of the associated beatmap. + /// The base slider velocity of the associated beatmap. + /// This was known as "SliderMultiplier" in the .osu format and stable editor. /// - double SliderMultiplier { get; } + double BaseSliderVelocity { get; } /// /// The slider tick rate of the associated beatmap. diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index a8972775de..4adbb356da 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 + return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.BaseSliderVelocity * 1 / BeatSnapProvider.BeatDivisor); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 7ddd372dc9..bdcf539033 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Objects.Legacy TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * SliderVelocity; + double scoringDistance = base_scoring_distance * difficulty.BaseSliderVelocity * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 4c7564b791..da1110506a 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.UI.Scrolling // The slider multiplier is post-multiplied to determine the final velocity, but for relative scale beat lengths // the multiplier should not affect the effective timing point (the longest in the beatmap), so it is factored out here - baseBeatLength /= Beatmap.Difficulty.SliderMultiplier; + baseBeatLength /= Beatmap.Difficulty.BaseSliderVelocity; } // Merge sequences of timing and difficulty control points to create the aggregate "multiplier" control point @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.UI.Scrolling return new MultiplierControlPoint(c.Time) { - Velocity = Beatmap.Difficulty.SliderMultiplier, + Velocity = Beatmap.Difficulty.BaseSliderVelocity, BaseBeatLength = baseBeatLength, TimingPoint = lastTimingPoint, EffectPoint = lastEffectPoint @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.UI.Scrolling ControlPoints.AddRange(timingChanges); if (ControlPoints.Count == 0) - ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.SliderMultiplier }); + ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.BaseSliderVelocity }); } protected override void LoadComplete() From b109ee74a631a32df7195b077cd237e70ead1530 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:20:57 +0900 Subject: [PATCH 0784/1400] Add "base velocity" adjustment to difficulty setup screen --- osu.Game/Localisation/EditorSetupStrings.cs | 10 ++++++++++ osu.Game/Screens/Edit/Setup/DifficultySection.cs | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/osu.Game/Localisation/EditorSetupStrings.cs b/osu.Game/Localisation/EditorSetupStrings.cs index 4ddacf2c5b..caea3dd130 100644 --- a/osu.Game/Localisation/EditorSetupStrings.cs +++ b/osu.Game/Localisation/EditorSetupStrings.cs @@ -126,6 +126,16 @@ namespace osu.Game.Localisation public static LocalisableString OverallDifficultyDescription => new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + /// + /// "Base Velocity" + /// + public static LocalisableString BaseVelocity => new TranslatableString(getKey(@"base_velocity"), @"Base Velocity"); + + /// + /// "The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets." + /// + public static LocalisableString BaseVelocityDescription => new TranslatableString(getKey(@"base_velocity_description"), @"The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets."); + /// /// "Metadata" /// diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 7026bde681..7c4b0e72d7 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -19,6 +19,7 @@ namespace osu.Game.Screens.Edit.Setup private LabelledSliderBar healthDrainSlider = null!; private LabelledSliderBar approachRateSlider = null!; private LabelledSliderBar overallDifficultySlider = null!; + private LabelledSliderBar baseVelocitySlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; @@ -79,6 +80,19 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.1f, } }, + baseVelocitySlider = new LabelledSliderBar + { + Label = EditorSetupStrings.BaseVelocity, + FixedLabelWidth = LABEL_WIDTH, + Description = EditorSetupStrings.BaseVelocityDescription, + Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) + { + Default = 1, + MinValue = 0.01, + MaxValue = 10, + Precision = 0.1f, + } + }, }; foreach (var item in Children.OfType>()) @@ -93,6 +107,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; + Beatmap.Difficulty.BaseSliderVelocity = baseVelocitySlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 31de4de72031afdfa1e02ed201a5bbcacf9d8333 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:21:39 +0900 Subject: [PATCH 0785/1400] Remove median/mode slider velocity display The intention was to give an idea of what the most common velocity of the beatmap is, but in hindsight, because the "base" velocity is being set elsewhere this doesn't make sense. It will/should be 1.0x. Showing this range is still valuable, though. --- .../Timeline/DifficultyPointPiece.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 13a1c30cfe..545e54254a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -159,20 +159,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray(); - if (sliderVelocities.Length < 2) - return; + if (sliderVelocities.First() != sliderVelocities.Last()) + { + AddHeader("Used velocity range"); + AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); + } - double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key; - double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2]; - - AddHeader("Average velocity"); - AddValue($"{medianSliderVelocity:#,0.00}x"); - - AddHeader("Most used velocity"); - AddValue($"{modeSliderVelocity:#,0.00}x"); - - AddHeader("Velocity range"); - AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); } protected override void Dispose(bool isDisposing) From d9dd35c0202d10694721737c16675e4db236c45f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 7 May 2023 13:22:48 +0900 Subject: [PATCH 0786/1400] Show base velocity in slider adjustment popover --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 545e54254a..a02a3be430 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -165,6 +165,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); } + AddHeader("Beatmap base velocity"); + AddValue($"{EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x"); } protected override void Dispose(bool isDisposing) From 451af9d1b5b04e58cf034f65a2480366c3b9a34b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:23:13 +0900 Subject: [PATCH 0787/1400] Fix beatmap values not being updated due to a varying data type --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 7c4b0e72d7..66bb8a9b84 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -96,10 +96,13 @@ namespace osu.Game.Screens.Edit.Setup }; foreach (var item in Children.OfType>()) - item.Current.ValueChanged += onValueChanged; + item.Current.ValueChanged += _ => updateValues(); + + foreach (var item in Children.OfType>()) + item.Current.ValueChanged += _ => updateValues(); } - private void onValueChanged(ValueChangedEvent args) + private void updateValues() { // for now, update these on commit rather than making BeatmapMetadata bindables. // after switching database engines we can reconsider if switching to bindables is a good direction. From a91edd68d976df038c654feea6c1714d03ac11bc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:42:25 +0900 Subject: [PATCH 0788/1400] Show post-multiplied velocity in main hit object inspector --- osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index 597925e3e2..60b9010aa8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (selected is IHasSliderVelocity sliderVelocity) { AddHeader("Slider Velocity"); - AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x"); + AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x)"); } if (selected is IHasRepeats repeats) From a6cb1f90e4c9ab1b2e06bda043321f2795a56b8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:43:21 +0900 Subject: [PATCH 0789/1400] Change difficulty popover inspector display (yet again) I think this makes the most sense of the iterations I've tested so far, albeit maybe being a touch too verbose. --- .../Timeline/DifficultyPointPiece.cs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index a02a3be430..ac37101060 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.X, Text = "Hold shift while dragging the end of an object to adjust velocity while snapping." }, - new SliderVelocityInspector(), + new SliderVelocityInspector(sliderVelocitySlider.Current), } } }; @@ -145,28 +145,48 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline internal partial class SliderVelocityInspector : EditorInspector { + private readonly Bindable current; + + public SliderVelocityInspector(Bindable current) + { + this.current = current; + } + [BackgroundDependencyLoader] private void load() { EditorBeatmap.TransactionBegan += updateInspectorText; EditorBeatmap.TransactionEnded += updateInspectorText; + EditorBeatmap.BeatmapReprocessed += updateInspectorText; + current.ValueChanged += _ => updateInspectorText(); + updateInspectorText(); } private void updateInspectorText() { + double beatmapVelocity = EditorBeatmap.Difficulty.BaseSliderVelocity; + InspectorText.Clear(); double[] sliderVelocities = EditorBeatmap.HitObjects.OfType().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray(); + AddHeader("Base velocity (from beatmap setup)"); + AddValue($"{beatmapVelocity:#,0.00}x"); + + AddHeader("Final velocity"); + AddValue($"{beatmapVelocity * current.Value:#,0.00}x"); + if (sliderVelocities.First() != sliderVelocities.Last()) { - AddHeader("Used velocity range"); - AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"); - } + AddHeader("Beatmap velocity range"); - AddHeader("Beatmap base velocity"); - AddValue($"{EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x"); + string range = $"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x"; + if (beatmapVelocity != 1) + range += $" ({beatmapVelocity * sliderVelocities.First():#,0.00}x - {beatmapVelocity * sliderVelocities.Last():#,0.00}x)"; + + AddValue(range); + } } protected override void Dispose(bool isDisposing) From 8c44d528e9f640d56a4834cb81d99cbf81bc630a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 13:51:52 +0900 Subject: [PATCH 0790/1400] Use min/max values from stable --- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 66bb8a9b84..6c7e96f91d 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -88,9 +88,9 @@ namespace osu.Game.Screens.Edit.Setup Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) { Default = 1, - MinValue = 0.01, - MaxValue = 10, - Precision = 0.1f, + MinValue = 0.4, + MaxValue = 3.6, + Precision = 0.01f, } }, }; From f0020381377f77f58d5374007aebbe16e70e8776 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 15:29:04 +0900 Subject: [PATCH 0791/1400] Add test coverage of failing wiki return to page scenario --- .../Visual/Online/TestSceneWikiOverlay.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index b0e4303ca4..310e34262e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.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. -#nullable disable - using System; using System.Linq; using System.Net; @@ -20,7 +18,7 @@ namespace osu.Game.Tests.Visual.Online { private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; - private WikiOverlay wiki; + private WikiOverlay wiki = null!; [SetUp] public void SetUp() => Schedule(() => Child = wiki = new WikiOverlay()); @@ -73,7 +71,23 @@ namespace osu.Game.Tests.Visual.Online AddUntilStep("Error message correct", () => wiki.ChildrenOfType().Any(text => text.Text == "\"This_page_will_error_out\".")); } - private void setUpWikiResponse(APIWikiPage r, string redirectionPath = null) + [Test] + public void TestReturnAfterErrorPage() + { + setUpWikiResponse(responseArticlePage); + + AddStep("Show article page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); + AddUntilStep("Wait for non-error page", () => wiki.CurrentPath == "Article_styling_criteria/Formatting"); + + AddStep("Show nonexistent page", () => wiki.ShowPage("This_page_will_error_out")); + AddUntilStep("Wait for error page", () => wiki.CurrentPath == "error"); + + AddStep("Show article page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); + AddUntilStep("Wait for non-error page", () => wiki.CurrentPath == "Article_styling_criteria/Formatting"); + AddUntilStep("Error message not displayed", () => wiki.ChildrenOfType().All(text => text.Text != "\"This_page_will_error_out\".")); + } + + private void setUpWikiResponse(APIWikiPage r, string? redirectionPath = null) => AddStep("set up response", () => { dummyAPI.HandleRequest = request => From 715b735131d8c1c1b3073222175ebe8753fc51ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 15:20:17 +0900 Subject: [PATCH 0792/1400] Fix "Return to main page" link not working on wiki after error --- osu.Game/Overlays/WikiOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 2444aa4fa2..c816eca776 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -157,7 +157,9 @@ namespace osu.Game.Overlays private void onFail(string originalPath) { + wikiData.Value = null; path.Value = "error"; + LoadDisplay(articlePage = new WikiArticlePage($@"{api.WebsiteRootUrl}/wiki/", $"Something went wrong when trying to fetch page \"{originalPath}\".\n\n[Return to the main page](Main_Page).")); } From 9160711470035a7fbe6fd8227debe1934c943742 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 15:32:00 +0900 Subject: [PATCH 0793/1400] Change "Show main page" test steps to actually load the main page --- osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index 310e34262e..79c7e3a22e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -27,13 +27,13 @@ namespace osu.Game.Tests.Visual.Online public void TestMainPage() { setUpWikiResponse(responseMainPage); - AddStep("Show main page", () => wiki.Show()); + AddStep("Show main page", () => wiki.ShowPage()); } [Test] public void TestCancellationDoesntShowError() { - AddStep("Show main page", () => wiki.Show()); + AddStep("Show main page", () => wiki.ShowPage()); AddStep("Show another page", () => wiki.ShowPage("Article_styling_criteria/Formatting")); AddUntilStep("Current path is not error", () => wiki.CurrentPath != "error"); From 814f0b3fedf27661b721aecb17c1a9fbb7c5f000 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 15:43:11 +0900 Subject: [PATCH 0794/1400] Add back early return in `OnReleased` for safety --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 20daab2447..e5a6aa1049 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -329,6 +329,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (HoldStartTime == null) return; + // do not run any of this logic when rewinding, as it inverts order of presses/releases. + if (Time.Elapsed < 0) + return; + Tail.UpdateResult(); endHold(); From 1b7dd32eb1f006393fb73969f215a4b2421619c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 16:55:29 +0900 Subject: [PATCH 0795/1400] Apply nullability in related classes and remove unused variable --- .../TestSceneHoldNoteInput.cs | 12 ++++-------- .../UI/Scrolling/Algorithms/IScrollAlgorithm.cs | 2 -- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 42e2099e3f..ce6a118d9b 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; @@ -40,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests private const double time_tail = 4000; private const double time_after_tail = 5250; - private List judgementResults; + private List judgementResults = new List(); /// /// -----[ ]----- @@ -521,9 +519,9 @@ namespace osu.Game.Rulesets.Mania.Tests private void assertLastTickJudgement(HitResult result) => AddAssert($"last tick judged as {result}", () => judgementResults.Last(j => j.HitObject is HoldNoteTick).Type, () => Is.EqualTo(result)); - private ScoreAccessibleReplayPlayer currentPlayer; + private ScoreAccessibleReplayPlayer currentPlayer = null!; - private void performTest(List frames, Beatmap beatmap = null) + private void performTest(List frames, Beatmap? beatmap = null) { if (beatmap == null) { @@ -569,15 +567,13 @@ namespace osu.Game.Rulesets.Mania.Tests AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); - AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor?.HasCompleted.Value == true); + AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } private partial class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; - public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; - protected override bool PauseOnFocusLost => false; public ScoreAccessibleReplayPlayer(Score score) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index f78509f919..437e5a5e38 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.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. -#nullable disable - namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public interface IScrollAlgorithm From d6ce56e6b1d7eec37ea19a32d5034f467fb96226 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 16:55:48 +0900 Subject: [PATCH 0796/1400] Fix `GetMostCommonBeatLength` returning zero in case of not timing points --- osu.Game/Beatmaps/Beatmap.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 416d655cc3..4f81b26c3e 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -107,9 +107,12 @@ namespace osu.Game.Beatmaps // Aggregate durations into a set of (beatLength, duration) tuples for each beat length .GroupBy(t => Math.Round(t.beatLength * 1000) / 1000) .Select(g => (beatLength: g.Key, duration: g.Sum(t => t.duration))) - // Get the most common one, or 0 as a suitable default + // Get the most common one, or 0 as a suitable default (see handling below) .OrderByDescending(i => i.duration).FirstOrDefault(); + if (mostCommon.beatLength == 0) + return TimingControlPoint.DEFAULT_BEAT_LENGTH; + return mostCommon.beatLength; } From bcabe967141d8a55b42b4e3da42546c8f2520749 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 17:49:41 +0900 Subject: [PATCH 0797/1400] Add extra tests of hold note input in more standard scenarios --- .../TestSceneHoldNoteInput.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index ce6a118d9b..77db1b0bd8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -59,6 +59,44 @@ namespace osu.Game.Rulesets.Mania.Tests assertNoteJudgement(HitResult.IgnoreMiss); } + /// + /// -----[ ]----- + /// x o + /// + [Test] + public void TestCorrectInput() + { + performTest(new List + { + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.LargeTickHit); + assertTailJudgement(HitResult.Perfect); + assertNoteJudgement(HitResult.IgnoreHit); + } + + /// + /// -----[ ]----- + /// x o + /// + [Test] + public void TestLateRelease() + { + performTest(new List + { + new ManiaReplayFrame(time_head, ManiaAction.Key1), + new ManiaReplayFrame(time_after_tail), + }); + + assertHeadJudgement(HitResult.Perfect); + assertTickJudgement(HitResult.LargeTickHit); + assertTailJudgement(HitResult.Miss); + assertNoteJudgement(HitResult.IgnoreMiss); + } + /// /// -----[ ]----- /// x o From d2380bd8401491d13d70bf0122ce1df341f8620e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 8 May 2023 18:12:56 +0900 Subject: [PATCH 0798/1400] Remove usages of [ExcludeFromDynamicCompile] --- osu.Game/Beatmaps/BeatmapDifficulty.cs | 2 -- osu.Game/Beatmaps/BeatmapImporter.cs | 2 -- osu.Game/Beatmaps/BeatmapInfo.cs | 2 -- osu.Game/Beatmaps/BeatmapManager.cs | 2 -- osu.Game/Beatmaps/BeatmapMetadata.cs | 2 -- osu.Game/Beatmaps/BeatmapSetInfo.cs | 2 -- osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs | 2 -- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 -- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 -- osu.Game/Configuration/DevelopmentOsuConfigManager.cs | 2 -- osu.Game/Configuration/OsuConfigManager.cs | 2 -- osu.Game/Database/RealmFileStore.cs | 2 -- osu.Game/Models/RealmFile.cs | 2 -- osu.Game/Models/RealmNamedFileUsage.cs | 2 -- osu.Game/Overlays/Settings/SettingsSubsection.cs | 2 -- osu.Game/Rulesets/Mods/Mod.cs | 2 -- osu.Game/Rulesets/Ruleset.cs | 2 -- osu.Game/Rulesets/RulesetInfo.cs | 2 -- osu.Game/Scoring/ScoreInfo.cs | 2 -- osu.Game/Skinning/SkinInfo.cs | 2 -- osu.Game/Skinning/SkinManager.cs | 2 -- osu.Game/Tests/Visual/OsuTestScene.cs | 1 - 22 files changed, 43 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index f4bc5e7b77..217f3b89a4 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -1,12 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Testing; using Realms; namespace osu.Game.Beatmaps { - [ExcludeFromDynamicCompile] [MapTo("BeatmapDifficulty")] public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo { diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 4731a70753..7d367ef77d 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -12,7 +12,6 @@ using osu.Framework.Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Beatmaps.Formats; using osu.Game.Collections; using osu.Game.Database; @@ -28,7 +27,6 @@ namespace osu.Game.Beatmaps /// /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. /// - [ExcludeFromDynamicCompile] public class BeatmapImporter : RealmArchiveModelImporter { public override IEnumerable HandledExtensions => new[] { ".osz" }; diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 63e878b80d..393feff087 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; -using osu.Framework.Testing; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Collections; using osu.Game.Database; @@ -27,7 +26,6 @@ namespace osu.Game.Beatmaps /// /// There are some legacy fields in this model which are not persisted to realm. These are isolated in a code region within the class and should eventually be migrated to `Beatmap`. /// - [ExcludeFromDynamicCompile] [Serializable] [MapTo("Beatmap")] public class BeatmapInfo : RealmObject, IHasGuidPrimaryKey, IBeatmapInfo, IEquatable diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 61b234d88a..305dc01844 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -15,7 +15,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Extensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.Extensions; @@ -33,7 +32,6 @@ namespace osu.Game.Beatmaps /// /// Handles general operations related to global beatmap management. /// - [ExcludeFromDynamicCompile] public class BeatmapManager : ModelManager, IModelImporter, IWorkingBeatmapCache { public ITrackStore BeatmapTrackStore { get; } diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index f645d914b1..811dc54e16 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -4,7 +4,6 @@ using System; using JetBrains.Annotations; using Newtonsoft.Json; -using osu.Framework.Testing; using osu.Game.Models; using osu.Game.Users; using osu.Game.Utils; @@ -23,7 +22,6 @@ namespace osu.Game.Beatmaps /// /// Note that difficulty name is not stored in this metadata but in . /// - [ExcludeFromDynamicCompile] [Serializable] [MapTo("BeatmapMetadata")] public class BeatmapMetadata : RealmObject, IBeatmapMetadataInfo, IDeepCloneable diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index b90dfdba05..59e413d935 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; -using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Extensions; using osu.Game.Models; @@ -17,7 +16,6 @@ namespace osu.Game.Beatmaps /// /// A realm model containing metadata for a beatmap set (containing multiple s). /// - [ExcludeFromDynamicCompile] [MapTo("BeatmapSet")] public class BeatmapSetInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IBeatmapSetInfo { diff --git a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs index 71d40b1a48..fac91c23f5 100644 --- a/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs +++ b/osu.Game/Beatmaps/BeatmapUpdaterMetadataLookup.cs @@ -13,7 +13,6 @@ using osu.Framework.Development; using osu.Framework.IO.Network; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -30,7 +29,6 @@ namespace osu.Game.Beatmaps /// On creating the component, a copy of a database containing metadata for a large subset of beatmaps (stored to ) will be downloaded if not already present locally. /// This will always be checked before doing a second online query to get required metadata. /// - [ExcludeFromDynamicCompile] public class BeatmapUpdaterMetadataLookup : IDisposable { private readonly IAPIProvider api; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index ab790617bb..59a71fd80c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -16,7 +16,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Extensions; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; -using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; @@ -25,7 +24,6 @@ using osu.Game.Storyboards; namespace osu.Game.Beatmaps { - [ExcludeFromDynamicCompile] public abstract class WorkingBeatmap : IWorkingBeatmap { public readonly BeatmapInfo BeatmapInfo; diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 76a31a6f78..ef843909d8 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -17,7 +17,6 @@ using osu.Framework.Lists; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Statistics; -using osu.Framework.Testing; using osu.Game.Beatmaps.Formats; using osu.Game.Database; using osu.Game.IO; @@ -121,7 +120,6 @@ namespace osu.Game.Beatmaps #endregion - [ExcludeFromDynamicCompile] private class BeatmapManagerWorkingBeatmap : WorkingBeatmap { [NotNull] diff --git a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs index dda30c1d00..33329002a9 100644 --- a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs +++ b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs @@ -4,11 +4,9 @@ #nullable disable using osu.Framework.Platform; -using osu.Framework.Testing; namespace osu.Game.Configuration { - [ExcludeFromDynamicCompile] public class DevelopmentOsuConfigManager : OsuConfigManager { protected override string Filename => base.Filename.Replace(".ini", ".dev.ini"); diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 1e7d3cf84f..365ad37f4c 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -12,7 +12,6 @@ using osu.Framework.Extensions; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Input; using osu.Game.Input.Bindings; @@ -26,7 +25,6 @@ using osu.Game.Skinning; namespace osu.Game.Configuration { - [ExcludeFromDynamicCompile] public class OsuConfigManager : IniConfigManager, IGameplaySettings { public OsuConfigManager(Storage storage) diff --git a/osu.Game/Database/RealmFileStore.cs b/osu.Game/Database/RealmFileStore.cs index f75d3be725..1da64d5be8 100644 --- a/osu.Game/Database/RealmFileStore.cs +++ b/osu.Game/Database/RealmFileStore.cs @@ -8,7 +8,6 @@ using osu.Framework.Extensions; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Models; @@ -19,7 +18,6 @@ namespace osu.Game.Database /// /// Handles the storing of files to the file system (and database) backing. /// - [ExcludeFromDynamicCompile] public class RealmFileStore { private readonly RealmAccess realm; diff --git a/osu.Game/Models/RealmFile.cs b/osu.Game/Models/RealmFile.cs index f96b717937..2faa3f0ca6 100644 --- a/osu.Game/Models/RealmFile.cs +++ b/osu.Game/Models/RealmFile.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Testing; using osu.Game.IO; using Realms; namespace osu.Game.Models { - [ExcludeFromDynamicCompile] [MapTo("File")] public class RealmFile : RealmObject, IFileInfo { diff --git a/osu.Game/Models/RealmNamedFileUsage.cs b/osu.Game/Models/RealmNamedFileUsage.cs index c4310c4edb..c8e2c6f6d0 100644 --- a/osu.Game/Models/RealmNamedFileUsage.cs +++ b/osu.Game/Models/RealmNamedFileUsage.cs @@ -3,14 +3,12 @@ using System; using JetBrains.Annotations; -using osu.Framework.Testing; using osu.Game.Database; using osu.Game.IO; using Realms; namespace osu.Game.Models { - [ExcludeFromDynamicCompile] public class RealmNamedFileUsage : EmbeddedObject, INamedFile, INamedFileUsage { public RealmFile File { get; set; } = null!; diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 784f20a6e8..eda18abaef 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -10,12 +10,10 @@ using osu.Game.Graphics.Sprites; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Localisation; -using osu.Framework.Testing; using osu.Game.Graphics; namespace osu.Game.Overlays.Settings { - [ExcludeFromDynamicCompile] public abstract partial class SettingsSubsection : FillFlowContainer, IFilterable { protected override Container Content => FlowContent; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 787da926ea..f9812d6c00 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Framework.Testing; using osu.Game.Configuration; using osu.Game.Extensions; using osu.Game.Rulesets.UI; @@ -21,7 +20,6 @@ namespace osu.Game.Rulesets.Mods /// /// The base class for gameplay modifiers. /// - [ExcludeFromDynamicCompile] public abstract class Mod : IMod, IEquatable, IDeepCloneable { [JsonIgnore] diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index fcf7a78090..a77068eb14 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.IO.Stores; using osu.Framework.Localisation; -using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Legacy; using osu.Game.Configuration; @@ -34,7 +33,6 @@ using osu.Game.Users; namespace osu.Game.Rulesets { - [ExcludeFromDynamicCompile] public abstract class Ruleset { public RulesetInfo RulesetInfo { get; } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 6a4e0f0b48..56f073f74c 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -3,13 +3,11 @@ using System; using JetBrains.Annotations; -using osu.Framework.Testing; using osu.Game.Rulesets.Difficulty; using Realms; namespace osu.Game.Rulesets { - [ExcludeFromDynamicCompile] [MapTo("Ruleset")] public class RulesetInfo : RealmObject, IEquatable, IComparable, IRulesetInfo { diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 02c7acf350..e084c45de0 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -7,7 +7,6 @@ using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Localisation; -using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Models; @@ -25,7 +24,6 @@ namespace osu.Game.Scoring /// /// A realm model containing metadata for a single score. /// - [ExcludeFromDynamicCompile] [MapTo("Score")] public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IScoreInfo { diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 9ad91f8725..c2b80b7ead 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; -using osu.Framework.Testing; using osu.Game.Database; using osu.Game.IO; using osu.Game.Models; @@ -13,7 +12,6 @@ using Realms; namespace osu.Game.Skinning { - [ExcludeFromDynamicCompile] [MapTo("Skin")] [JsonObject(MemberSerialization.OptIn)] public class SkinInfo : RealmObject, IHasRealmFiles, IEquatable, IHasGuidPrimaryKey, ISoftDelete, IHasNamedFiles diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 45536e04eb..51605c6045 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -18,7 +18,6 @@ using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Platform; -using osu.Framework.Testing; using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Audio; @@ -36,7 +35,6 @@ namespace osu.Game.Skinning /// This is also exposed and cached as to allow for any component to potentially have skinning support. /// For gameplay components, see which adds extra legacy and toggle logic that may affect the lookup process. /// - [ExcludeFromDynamicCompile] public class SkinManager : ModelManager, ISkinSource, IStorageResourceProvider, IModelImporter { /// diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 46c7c3a57c..0ec5a4c5c2 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -36,7 +36,6 @@ using osu.Game.Tests.Rulesets; namespace osu.Game.Tests.Visual { - [ExcludeFromDynamicCompile] public abstract partial class OsuTestScene : TestScene { [Cached] From 27c10cbdb7082e219400873ae72de33029e131bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 18:14:07 +0900 Subject: [PATCH 0799/1400] Remove clamping of `sizingContainer` in `DrawableHoldNote` to fix head note alignment --- .../Objects/Drawables/DrawableHoldNote.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 372ef1e164..09976827fe 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -3,7 +3,6 @@ #nullable disable -using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -246,8 +245,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Head.IsHit && releaseTime == null && DrawHeight > 0) { // How far past the hit target this hold note is. Always a positive value. - float yOffset = Math.Max(0, Direction.Value == ScrollingDirection.Up ? -Y : Y); - sizingContainer.Height = Math.Clamp(1 - yOffset / DrawHeight, 0, 1); + float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; + sizingContainer.Height = 1 - yOffset / DrawHeight; } } From 64498e95a46915843625de96156c9e6ec6e0c0aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 18:56:29 +0900 Subject: [PATCH 0800/1400] Add an `IAnimationTimeReference` to `DrawableHitObject` to synchronise all animations --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 79fc778287..07c0d1f8a1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -30,7 +30,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Objects.Drawables { [Cached(typeof(DrawableHitObject))] - public abstract partial class DrawableHitObject : PoolableDrawableWithLifetime + public abstract partial class DrawableHitObject : PoolableDrawableWithLifetime, IAnimationTimeReference { /// /// Invoked after this 's applied has had its defaults applied. @@ -425,11 +425,13 @@ namespace osu.Game.Rulesets.Objects.Drawables LifetimeEnd = double.MaxValue; - double transformTime = HitObject.StartTime - InitialLifetimeOffset; - clearExistingStateTransforms(); - using (BeginAbsoluteSequence(transformTime)) + double initialTransformsTime = HitObject.StartTime - InitialLifetimeOffset; + + AnimationStartTime.Value = initialTransformsTime; + + using (BeginAbsoluteSequence(initialTransformsTime)) UpdateInitialTransforms(); using (BeginAbsoluteSequence(StateUpdateTime)) @@ -721,6 +723,8 @@ namespace osu.Game.Rulesets.Objects.Drawables if (CurrentSkin != null) CurrentSkin.SourceChanged -= skinSourceChanged; } + + public Bindable AnimationStartTime { get; } = new BindableDouble(); } public abstract partial class DrawableHitObject : DrawableHitObject From 1ff17309484e02aceb14efa3ba2fea8ebce67b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 8 May 2023 22:35:41 +0200 Subject: [PATCH 0801/1400] Remove no-longer-correct remark --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 9ffd338d7c..ce34addeff 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // 2. The head note will move along with the new "head position" in the container. if (Head.IsHit && releaseTime == null && DrawHeight > 0) { - // How far past the hit target this hold note is. Always a positive value. + // How far past the hit target this hold note is. float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; sizingContainer.Height = 1 - yOffset / DrawHeight; } From 0a47ffcbdd4bacdba6a0ab1739e7eaaeaedef35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 May 2023 07:03:13 +0200 Subject: [PATCH 0802/1400] Match generally used casing Co-authored-by: Joseph Madamba --- osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs index 98635c10a3..d5a9a311bc 100644 --- a/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs +++ b/osu.Game.Rulesets.Mania/Edit/Setup/ManiaSetupSection.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup specialStyle = new LabelledSwitchButton { Label = "Use special (N+1) style", - Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6k (5+1) or 8k (7+1) configurations.", + Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6K (5+1) or 8K (7+1) configurations.", Current = { Value = Beatmap.BeatmapInfo.SpecialStyle } } }; From 944da06c108b9240190c297b5825365e10ccf49b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 May 2023 16:58:19 +0900 Subject: [PATCH 0803/1400] Rename slider multiplier variable back for now --- .../Editor/TestSceneJuiceStreamPlacementBlueprint.cs | 2 +- .../Editor/TestSceneJuiceStreamSelectionBlueprint.cs | 2 +- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneJuiceStream.cs | 2 +- osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 4 ++-- .../Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 2 +- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 2 +- .../Editor/TestSceneSliderStreamConversion.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Editor/TestSceneTaikoEditorSaving.cs | 4 ++-- .../Beatmaps/TaikoBeatmapConverter.cs | 6 +++--- .../Mods/TaikoModDifficultyAdjust.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 2 +- .../Beatmaps/Formats/OsuJsonDecoderTest.cs | 2 +- .../TestSceneHitObjectComposerDistanceSnapping.cs | 12 ++++++------ .../Visual/Editing/TestSceneDistanceSnapGrid.cs | 2 +- .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 4 ++-- .../Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- osu.Game/Beatmaps/BeatmapDifficulty.cs | 8 ++++---- osu.Game/Beatmaps/BeatmapImporter.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs | 4 ++-- osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../UI/Scrolling/DrawableScrollingRuleset.cs | 6 +++--- .../Edit/Compose/Components/HitObjectInspector.cs | 2 +- .../Components/Timeline/DifficultyPointPiece.cs | 2 +- osu.Game/Screens/Edit/Setup/DifficultySection.cs | 4 ++-- 33 files changed, 51 insertions(+), 51 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs index e729a09a18..2426f8c886 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamPlacementBlueprint.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor { var playable = base.GetPlayableBeatmap(); playable.Difficulty.SliderTickRate = 5; - playable.Difficulty.BaseSliderVelocity = velocity_factor * 10; + playable.Difficulty.SliderMultiplier = velocity_factor * 10; return playable; } diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs index 634e1f5cbb..beba5811fe 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneJuiceStreamSelectionBlueprint.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor X = x, Path = sliderPath, }; - EditorBeatmap.Difficulty.BaseSliderVelocity = velocity; + EditorBeatmap.Difficulty.SliderMultiplier = velocity; EditorBeatmap.Add(hitObject); EditorBeatmap.Update(hitObject); Assert.That(hitObject.Velocity, Is.EqualTo(velocity)); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index d1f3f06971..40dc7d2403 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, Ruleset = ruleset } }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index 71cb8964c3..c91f07891c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 5, BaseSliderVelocity = 2 }, + Difficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 }, Ruleset = ruleset }, HitObjects = new List diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 301ecd6d66..169e99c90c 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -64,8 +64,8 @@ namespace osu.Game.Rulesets.Catch.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - velocityFactor = base_scoring_distance * difficulty.BaseSliderVelocity / timingPoint.BeatLength; - tickDistanceFactor = base_scoring_distance * difficulty.BaseSliderVelocity / difficulty.SliderTickRate; + velocityFactor = base_scoring_distance * difficulty.SliderMultiplier / timingPoint.BeatLength; + tickDistanceFactor = base_scoring_distance * difficulty.SliderMultiplier / difficulty.SliderTickRate; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index ab6f5e8269..91b7be6e8f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy StartTime = (int)Math.Round(hitObject.StartTime); // This matches stable's calculation. - EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.BaseSliderVelocity); + EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.SliderMultiplier); SegmentDuration = (EndTime - StartTime) / SpanCount; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index cb38551a43..af8758fb5e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI { // Mania doesn't care about global velocity p.Velocity = 1; - p.BaseBeatLength *= Beatmap.Difficulty.BaseSliderVelocity; + p.BaseBeatLength *= Beatmap.Difficulty.SliderMultiplier; // For non-mania beatmap, speed changes should only happen through timing points if (!isForCurrentRuleset) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index b79d4efe1b..7579e8077b 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor [SetUp] public void Setup() => Schedule(() => { - editorBeatmap.Difficulty.BaseSliderVelocity = 1; + editorBeatmap.Difficulty.SliderMultiplier = 1; editorBeatmap.ControlPointInfo.Clear(); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); snapProvider.DistanceSpacingMultiplier.Value = 1; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs index 938e093489..a162d9a491 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderStreamConversion.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("change to these specific circumstances", () => { - EditorBeatmap.Difficulty.BaseSliderVelocity = 1; + EditorBeatmap.Difficulty.SliderMultiplier = 1; var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(slider.StartTime); timingPoint.BeatLength = 352.941176470588; slider.Path.ControlPoints[^1].Position = new Vector2(-110, 16); diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index b86351e7cd..4189f8ba1e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = BASE_SCORING_DISTANCE * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = BASE_SCORING_DISTANCE * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = GenerateTicks ? (scoringDistance / difficulty.SliderTickRate * TickDistanceMultiplier) : double.PositiveInfinity; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index d79ca28c8f..93b26624de 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor [Test] public void TestTaikoSliderMultiplier() { - AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("Set slider multiplier", () => EditorBeatmap.Difficulty.SliderMultiplier = 2); SaveEditor(); @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Editor // therefore, ensure that we have that difficulty type by calling .CopyFrom(), which is a no-op if the type is already correct. var taikoDifficulty = new TaikoBeatmapConverter.TaikoMultiplierAppliedDifficulty(); taikoDifficulty.CopyFrom(EditorBeatmap.Difficulty); - return Precision.AlmostEquals(taikoDifficulty.BaseSliderVelocity, 2); + return Precision.AlmostEquals(taikoDifficulty.SliderMultiplier, 2); } } } diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 932211695a..e298e313df 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -189,7 +189,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps else beatLength = timingPoint.BeatLength; - double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.BaseSliderVelocity / beatmap.Difficulty.SliderTickRate; + double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate; // The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll. double taikoVelocity = sliderScoringPointDistance * beatmap.Difficulty.SliderTickRate; @@ -239,14 +239,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { base.CopyTo(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - other.BaseSliderVelocity /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + other.SliderMultiplier /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } public override void CopyFrom(IBeatmapDifficultyInfo other) { base.CopyFrom(other); if (!(other is TaikoMultiplierAppliedDifficulty)) - BaseSliderVelocity *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; + SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER; } #endregion diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index fe9c1f5815..99a064d35f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { base.ApplySettings(difficulty); - if (ScrollSpeed.Value != null) difficulty.BaseSliderVelocity *= ScrollSpeed.Value.Value; + if (ScrollSpeed.Value != null) difficulty.SliderMultiplier *= ScrollSpeed.Value.Value; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 5aeb5a87d7..009f2854f8 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.BaseSliderVelocity *= slider_multiplier; + difficulty.SliderMultiplier *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 0f68750535..ba41175461 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Mods public override void ApplyToDifficulty(BeatmapDifficulty difficulty) { base.ApplyToDifficulty(difficulty); - difficulty.BaseSliderVelocity *= slider_multiplier; + difficulty.SliderMultiplier *= slider_multiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 014fec9319..b4a12fd314 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_distance * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; tickSpacing = timingPoint.BeatLength / TickRate; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 98ad6fc18d..2c4f193327 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); + Assert.AreEqual(1.8, difficulty.SliderMultiplier); Assert.AreEqual(2, difficulty.SliderTickRate); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 11c5f2a2fc..3764467047 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(4, difficulty.CircleSize); Assert.AreEqual(8, difficulty.OverallDifficulty); Assert.AreEqual(9, difficulty.ApproachRate); - Assert.AreEqual(1.8, difficulty.BaseSliderVelocity); + Assert.AreEqual(1.8, difficulty.SliderMultiplier); Assert.AreEqual(2, difficulty.SliderTickRate); } diff --git a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs index ffbe16260b..6399507aa0 100644 --- a/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs +++ b/osu.Game.Tests/Editing/TestSceneHitObjectComposerDistanceSnapping.cs @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Editing BeatDivisor.Value = 1; - composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 1; + composer.EditorBeatmap.Difficulty.SliderMultiplier = 1; composer.EditorBeatmap.ControlPointInfo.Clear(); composer.EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }); }); @@ -66,7 +66,7 @@ namespace osu.Game.Tests.Editing [TestCase(2)] public void TestSliderMultiplier(float multiplier) { - AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = multiplier); + AddStep($"set slider multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier); assertSnapDistance(100 * multiplier, null, true); } @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Editing assertDurationToDistance(500, 50); assertDurationToDistance(1000, 100); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertDurationToDistance(500, 100); assertDurationToDistance(1000, 200); @@ -149,7 +149,7 @@ namespace osu.Game.Tests.Editing assertDistanceToDuration(50, 500); assertDistanceToDuration(100, 1000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertDistanceToDuration(100, 500); assertDistanceToDuration(200, 1000); @@ -174,7 +174,7 @@ namespace osu.Game.Tests.Editing assertSnappedDuration(200, 2000); assertSnappedDuration(250, 3000); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertSnappedDuration(0, 0); assertSnappedDuration(50, 0); @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Editing assertSnappedDistance(200, 200); assertSnappedDistance(250, 200); - AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.BaseSliderVelocity = 2); + AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2); assertSnappedDistance(50, 0); assertSnappedDistance(100, 0); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index a99bd72e40..21b925a257 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.Editing } }); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); - editorBeatmap.Difficulty.BaseSliderVelocity = 1; + editorBeatmap.Difficulty.SliderMultiplier = 1; } [SetUp] diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 735af9493c..287b7d43b4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.BaseSliderVelocity = 2; + beatmap.Difficulty.SliderMultiplier = 2; createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = createBeatmap(); beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range }); - beatmap.Difficulty.BaseSliderVelocity = 2; + beatmap.Difficulty.SliderMultiplier = 2; createTest(beatmap); AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index 28cc890fce..114c554d28 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay { BeatmapInfo = new BeatmapInfo { - Difficulty = new BeatmapDifficulty { CircleSize = 6, BaseSliderVelocity = 3 }, + Difficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 }, Ruleset = ruleset }, ControlPointInfo = controlPointInfo diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index cbea30f3b0..f4bc5e7b77 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// public const float DEFAULT_DIFFICULTY = 5; @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps public float OverallDifficulty { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; public float ApproachRate { get; set; } = IBeatmapDifficultyInfo.DEFAULT_DIFFICULTY; - public double BaseSliderVelocity { get; set; } = 1; + public double SliderMultiplier { get; set; } = 1; public double SliderTickRate { get; set; } = 1; public BeatmapDifficulty() @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps difficulty.CircleSize = CircleSize; difficulty.OverallDifficulty = OverallDifficulty; - difficulty.BaseSliderVelocity = BaseSliderVelocity; + difficulty.SliderMultiplier = SliderMultiplier; difficulty.SliderTickRate = SliderTickRate; } @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps CircleSize = other.CircleSize; OverallDifficulty = other.OverallDifficulty; - BaseSliderVelocity = other.BaseSliderVelocity; + SliderMultiplier = other.SliderMultiplier; SliderTickRate = other.SliderTickRate; } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index e96e38d249..4731a70753 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -353,7 +353,7 @@ namespace osu.Game.Beatmaps CircleSize = decodedDifficulty.CircleSize, OverallDifficulty = decodedDifficulty.OverallDifficulty, ApproachRate = decodedDifficulty.ApproachRate, - BaseSliderVelocity = decodedDifficulty.BaseSliderVelocity, + SliderMultiplier = decodedDifficulty.SliderMultiplier, SliderTickRate = decodedDifficulty.SliderTickRate, }; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 891e627435..5e98025c9a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,7 +384,7 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.BaseSliderVelocity = Parsing.ParseDouble(pair.Value); + difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index fffead3a6c..7fbcca9adb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -155,8 +155,8 @@ namespace osu.Game.Beatmaps.Formats // Taiko adjusts the slider multiplier (see: LEGACY_TAIKO_VELOCITY_MULTIPLIER) writer.WriteLine(onlineRulesetID == 1 - ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") - : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.BaseSliderVelocity}")); + ? FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier / LEGACY_TAIKO_VELOCITY_MULTIPLIER}") + : FormattableString.Invariant($"SliderMultiplier: {beatmap.Difficulty.SliderMultiplier}")); writer.WriteLine(FormattableString.Invariant($"SliderTickRate: {beatmap.Difficulty.SliderTickRate}")); } diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index bc2ee23da7..78234a9dd9 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -9,7 +9,7 @@ namespace osu.Game.Beatmaps public interface IBeatmapDifficultyInfo { /// - /// The default value used for all difficulty settings except and . + /// The default value used for all difficulty settings except and . /// const float DEFAULT_DIFFICULTY = 5; @@ -37,7 +37,7 @@ namespace osu.Game.Beatmaps /// The base slider velocity of the associated beatmap. /// This was known as "SliderMultiplier" in the .osu format and stable editor. /// - double BaseSliderVelocity { get; } + double SliderMultiplier { get; } /// /// The slider tick rate of the associated beatmap. diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index 4adbb356da..a8972775de 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Edit public virtual float GetBeatSnapDistanceAt(HitObject referenceObject, bool useReferenceSliderVelocity = true) { - return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.BaseSliderVelocity * 1 + return (float)(100 * (useReferenceSliderVelocity && referenceObject is IHasSliderVelocity hasSliderVelocity ? hasSliderVelocity.SliderVelocity : 1) * EditorBeatmap.Difficulty.SliderMultiplier * 1 / BeatSnapProvider.BeatDivisor); } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index bdcf539033..7ddd372dc9 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Objects.Legacy TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.BaseSliderVelocity * SliderVelocity; + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; } diff --git a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index da1110506a..4c7564b791 100644 --- a/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.UI.Scrolling // The slider multiplier is post-multiplied to determine the final velocity, but for relative scale beat lengths // the multiplier should not affect the effective timing point (the longest in the beatmap), so it is factored out here - baseBeatLength /= Beatmap.Difficulty.BaseSliderVelocity; + baseBeatLength /= Beatmap.Difficulty.SliderMultiplier; } // Merge sequences of timing and difficulty control points to create the aggregate "multiplier" control point @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.UI.Scrolling return new MultiplierControlPoint(c.Time) { - Velocity = Beatmap.Difficulty.BaseSliderVelocity, + Velocity = Beatmap.Difficulty.SliderMultiplier, BaseBeatLength = baseBeatLength, TimingPoint = lastTimingPoint, EffectPoint = lastEffectPoint @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.UI.Scrolling ControlPoints.AddRange(timingChanges); if (ControlPoints.Count == 0) - ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.BaseSliderVelocity }); + ControlPoints.Add(new MultiplierControlPoint { Velocity = Beatmap.Difficulty.SliderMultiplier }); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs index 60b9010aa8..7beaf7d086 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectInspector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (selected is IHasSliderVelocity sliderVelocity) { AddHeader("Slider Velocity"); - AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.BaseSliderVelocity:#,0.00}x)"); + AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.SliderMultiplier:#,0.00}x)"); } if (selected is IHasRepeats repeats) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index ac37101060..76ad3e5b6a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private void updateInspectorText() { - double beatmapVelocity = EditorBeatmap.Difficulty.BaseSliderVelocity; + double beatmapVelocity = EditorBeatmap.Difficulty.SliderMultiplier; InspectorText.Clear(); diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 6c7e96f91d..3a3fe7f747 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -85,7 +85,7 @@ namespace osu.Game.Screens.Edit.Setup Label = EditorSetupStrings.BaseVelocity, FixedLabelWidth = LABEL_WIDTH, Description = EditorSetupStrings.BaseVelocityDescription, - Current = new BindableDouble(Beatmap.Difficulty.BaseSliderVelocity) + Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier) { Default = 1, MinValue = 0.4, @@ -110,7 +110,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value; Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; - Beatmap.Difficulty.BaseSliderVelocity = baseVelocitySlider.Current.Value; + Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 2085833a842c023ddb26e85e6fd54a2375867119 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 9 May 2023 17:08:03 +0900 Subject: [PATCH 0804/1400] Fix missing delegate unsubscribe --- .../Edit/Compose/Components/Timeline/DifficultyPointPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs index 76ad3e5b6a..173a665d5c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/DifficultyPointPiece.cs @@ -195,6 +195,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline EditorBeatmap.TransactionBegan -= updateInspectorText; EditorBeatmap.TransactionEnded -= updateInspectorText; + EditorBeatmap.BeatmapReprocessed -= updateInspectorText; } } } From 5afe57033ddc19da134009b4967409022b2f8dea Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 9 May 2023 19:30:54 +0900 Subject: [PATCH 0805/1400] Add parent hitobject to strong hits --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 7 ++++++- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 6 +++++- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 6 +++++- osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs | 7 +++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index b4a12fd314..80553a1033 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -109,12 +109,17 @@ namespace osu.Game.Rulesets.Taiko.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit(this) { StartTime = startTime }; public class StrongNestedHit : StrongNestedHitObject { // The strong hit of the drum roll doesn't actually provide any score. public override Judgement CreateJudgement() => new IgnoreJudgement(); + + public StrongNestedHit(TaikoHitObject parent) + : base(parent) + { + } } #region LegacyBeatmapEncoder diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 6bcb8674e6..56dbe3ce38 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -33,10 +33,14 @@ namespace osu.Game.Rulesets.Taiko.Objects public override double MaximumJudgementOffset => HitWindow; - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit(this) { StartTime = startTime }; public class StrongNestedHit : StrongNestedHitObject { + public StrongNestedHit(TaikoHitObject parent) + : base(parent) + { + } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 787079bfee..6a3c8467e9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -72,10 +72,14 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit(this) { StartTime = startTime }; public class StrongNestedHit : StrongNestedHitObject { + public StrongNestedHit(TaikoHitObject parent) + : base(parent) + { + } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs index 628c41d878..316115f44d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs @@ -15,6 +15,13 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public abstract class StrongNestedHitObject : TaikoHitObject { + public readonly TaikoHitObject Parent; + + protected StrongNestedHitObject(TaikoHitObject parent) + { + Parent = parent; + } + public override Judgement CreateJudgement() => new TaikoStrongJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; From 3c3c812ed6dfca27d7ffa2db07703c93d57d52b9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 9 May 2023 19:33:33 +0900 Subject: [PATCH 0806/1400] Initial implementation of ScoreV2 --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Scoring/CatchScoreProcessor.cs | 78 +++- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Scoring/ManiaScoreProcessor.cs | 49 ++- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 37 +- .../Scoring/TaikoScoreProcessor.cs | 58 ++- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- .../Spectator/SpectatorScoreProcessor.cs | 3 +- .../PerformanceBreakdownCalculator.cs | 4 +- .../Rulesets/Mods/ModAccuracyChallenge.cs | 4 +- osu.Game/Rulesets/Ruleset.cs | 21 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 392 ++++-------------- osu.Game/Scoring/ScoreManager.cs | 4 +- .../OnlinePlay/Playlists/PlaylistsPlayer.cs | 3 +- 15 files changed, 300 insertions(+), 361 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 8a0b8250d5..e2255fa6f7 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableCatchRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index b6a42407da..bf5c3a91d6 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,17 +1,87 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Scoring { public partial class CatchScoreProcessor : ScoreProcessor { - public CatchScoreProcessor() - : base(new CatchRuleset()) + private const int combo_cap = 200; + private const double combo_base = 4; + + protected override double ClassicScoreMultiplier => 28; + + private double tinyDropletScale; + + private int maximumTinyDroplets; + private int hitTinyDroplets; + + public CatchScoreProcessor(Ruleset ruleset) + : base(ruleset) { } - protected override double ClassicScoreMultiplier => 28; + protected override double ComputeTotalScore() + { + double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; + + const int tiny_droplets_portion = 400000; + + return + (int)Math.Round + (( + ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion + + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + + BonusPortion + ) * ScoreMultiplier); + } + + protected override void AddScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + ComboPortion += change.combo; + BonusPortion += change.bonus; + hitTinyDroplets += change.tinyDropletHits; + } + + protected override void RemoveScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + ComboPortion -= change.combo; + BonusPortion -= change.bonus; + hitTinyDroplets -= change.tinyDropletHits; + } + + private (double combo, double bonus, int tinyDropletHits) computeScoreChange(JudgementResult result) + { + if (result.HitObject is TinyDroplet) + return (0, 0, 1); + + if (result.Type.IsBonus()) + return (0, Judgement.ToNumericResult(result.Type), 0); + + return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0); + } + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + + if (storeResults) + { + maximumTinyDroplets = hitTinyDroplets; + + if (maximumTinyDroplets + MaxBasicJudgements == 0) + tinyDropletScale = 0; + else + tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + MaxBasicJudgements); + } + + hitTinyDroplets = 0; + } } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index d324682989..c6065c9b96 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableManiaRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index f724972a29..7d188c6786 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,23 +1,54 @@ -// 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. -#nullable disable - +using System; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring { - internal partial class ManiaScoreProcessor : ScoreProcessor + public partial class ManiaScoreProcessor : ScoreProcessor { - public ManiaScoreProcessor() - : base(new ManiaRuleset()) + private const double combo_base = 4; + + protected override double ClassicScoreMultiplier => 16; + + public ManiaScoreProcessor(Ruleset ruleset) + : base(ruleset) { } - protected override double DefaultAccuracyPortion => 0.99; + protected override double ComputeTotalScore() + { + return + (int)Math.Round + (( + 200000 * ComboPortion / MaxComboPortion + + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier); + } - protected override double DefaultComboPortion => 0.01; + protected override void AddScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + ComboPortion += change.combo; + BonusPortion += change.bonus; + } - protected override double ClassicScoreMultiplier => 16; + protected override void RemoveScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + ComboPortion -= change.combo; + BonusPortion -= change.bonus; + } + + private (double combo, double bonus) computeScoreChange(JudgementResult result) + { + if (result.Type.IsBonus()) + return (0, Judgement.ToNumericResult(result.Type)); + + return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(400, combo_base)), 0); + } } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 922594a93a..497d405436 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableOsuRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 50d4eb6258..5f5997b0c1 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,38 +1,29 @@ -// 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. -#nullable disable - -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Osu.Objects; +using System; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Scoring { public partial class OsuScoreProcessor : ScoreProcessor { - public OsuScoreProcessor() - : base(new OsuRuleset()) + protected override double ClassicScoreMultiplier => 36; + + public OsuScoreProcessor(Ruleset ruleset) + : base(ruleset) { } - protected override double ClassicScoreMultiplier => 36; - - protected override HitEvent CreateHitEvent(JudgementResult result) - => base.CreateHitEvent(result).With((result as OsuHitCircleJudgementResult)?.CursorPositionAtHit); - - protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) + protected override double ComputeTotalScore() { - switch (hitObject) - { - case HitCircle: - return new OsuHitCircleJudgementResult(hitObject, judgement); - - default: - return new OsuJudgementResult(hitObject, judgement); - } + return + (int)Math.Round + (( + 700000 * ComboPortion / MaxComboPortion + + 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier); } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 4b60ee3ccb..caf0a799a2 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,23 +1,63 @@ -// 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. -#nullable disable - +using System; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Scoring { - internal partial class TaikoScoreProcessor : ScoreProcessor + public partial class TaikoScoreProcessor : ScoreProcessor { - public TaikoScoreProcessor() - : base(new TaikoRuleset()) + private const double combo_base = 4; + + protected override double ClassicScoreMultiplier => 22; + + public TaikoScoreProcessor(Ruleset ruleset) + : base(ruleset) { } - protected override double DefaultAccuracyPortion => 0.75; + protected override double ComputeTotalScore() + { + return + (int)Math.Round + (( + 250000 * ComboPortion / MaxComboPortion + + 750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier); + } - protected override double DefaultComboPortion => 0.25; + protected override void AddScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + BonusPortion += change.bonus; + ComboPortion += change.combo; + } - protected override double ClassicScoreMultiplier => 22; + protected override void RemoveScoreChange(JudgementResult result) + { + var change = computeScoreChange(result); + BonusPortion -= change.bonus; + ComboPortion -= change.combo; + } + + private (double combo, double bonus) computeScoreChange(JudgementResult result) + { + double hitValue = Judgement.ToNumericResult(result.Type); + + if (result.HitObject is StrongNestedHitObject strong) + { + double strongBonus = strong.Parent is DrumRollTick ? 3 : 7; + hitValue *= strongBonus; + } + + if (result.Type.IsBonus()) + return (0, hitValue); + + return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(400, combo_base)), 0); + } } } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index a35fdb890d..599d0dc33c 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); + public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TaikoHealthProcessor(); diff --git a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs index 1c505ea107..cb23164c00 100644 --- a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs +++ b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs @@ -157,7 +157,8 @@ namespace osu.Game.Online.Spectator Accuracy.Value = frame.Header.Accuracy; Combo.Value = frame.Header.Combo; - TotalScore.Value = scoreProcessor.ComputeScore(Mode.Value, scoreInfo); + // Todo: + // TotalScore.Value = scoreProcessor.ComputeScore(Mode.Value, scoreInfo); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 4f802a22a1..03bd0f7509 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -66,7 +66,9 @@ namespace osu.Game.Rulesets.Difficulty // calculate total score ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor(); scoreProcessor.Mods.Value = perfectPlay.Mods; - perfectPlay.TotalScore = scoreProcessor.ComputeScore(ScoringMode.Standardised, perfectPlay); + + // Todo: + // perfectPlay.TotalScore = scoreProcessor.ComputeScore(ScoringMode.Standardised, perfectPlay); // compute rank achieved // default to SS, then adjust the rank with mods diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index d4223a80c2..13b8ad5d84 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -65,7 +65,9 @@ namespace osu.Game.Rulesets.Mods scoreProcessor.PopulateScore(score); score.Statistics[result.Type]++; - return scoreProcessor.ComputeAccuracy(score); + // Todo: + return 0; + // return scoreProcessor.ComputeAccuracy(score); } } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index a77068eb14..2e7a58b96c 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -232,7 +232,7 @@ namespace osu.Game.Rulesets /// Creates a for this . /// /// The score processor. - public virtual ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); + public virtual ScoreProcessor CreateScoreProcessor() => new DefaultScoreProcessor(this); /// /// Creates a for this . @@ -381,4 +381,23 @@ namespace osu.Game.Rulesets /// public virtual RulesetSetupSection? CreateEditorSetupSection() => null; } + + public partial class DefaultScoreProcessor : ScoreProcessor + { + public DefaultScoreProcessor(Ruleset ruleset) + : base(ruleset) + { + } + + protected override double ComputeTotalScore() + { + return + (int)Math.Round + (( + 700000 * ComboPortion / MaxComboPortion + + 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier); + } + } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 96f6922224..8373ebd50c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -4,11 +4,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.Contracts; using System.Linq; using osu.Framework.Bindables; using osu.Framework.Localisation; -using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Extensions; using osu.Game.Localisation; @@ -20,8 +18,10 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring { - public partial class ScoreProcessor : JudgementProcessor + public abstract partial class ScoreProcessor : JudgementProcessor { + protected const double MAX_SCORE = 1000000; + private const double accuracy_cutoff_x = 1; private const double accuracy_cutoff_s = 0.95; private const double accuracy_cutoff_a = 0.9; @@ -29,8 +29,6 @@ namespace osu.Game.Rulesets.Scoring private const double accuracy_cutoff_c = 0.7; private const double accuracy_cutoff_d = 0; - private const double max_score = 1000000; - /// /// Invoked when this was reset from a replay frame. /// @@ -89,16 +87,6 @@ namespace osu.Game.Rulesets.Scoring /// public IReadOnlyList HitEvents => hitEvents; - /// - /// The default portion of awarded for hitting s accurately. Defaults to 30%. - /// - protected virtual double DefaultAccuracyPortion => 0.3; - - /// - /// The default portion of awarded for achieving a high combo. Default to 70%. - /// - protected virtual double DefaultComboPortion => 0.7; - /// /// An arbitrary multiplier to scale scores in the scoring mode. /// @@ -109,8 +97,45 @@ namespace osu.Game.Rulesets.Scoring /// public readonly Ruleset Ruleset; - private readonly double accuracyPortion; - private readonly double comboPortion; + /// + /// The sum of all basic judgements at the current time. + /// + private double currentBasicScore; + + /// + /// The maximum sum of basic judgements at the current time. + /// + private double currentMaxBasicScore; + + /// + /// The total count of basic judgements in the beatmap. + /// + protected int MaxBasicJudgements { get; private set; } + + /// + /// The current count of basic judgements by the player. + /// + protected int CurrentBasicJudgements { get; private set; } + + /// + /// The current combo score. + /// + protected double ComboPortion { get; set; } + + /// + /// The maximum achievable combo score. + /// + protected double MaxComboPortion { get; private set; } + + /// + /// The current bonus score. + /// + protected double BonusPortion { get; set; } + + /// + /// The total score multiplier. + /// + protected double ScoreMultiplier { get; private set; } = 1; public Dictionary MaximumStatistics { @@ -123,27 +148,6 @@ namespace osu.Game.Rulesets.Scoring } } - private ScoringValues maximumScoringValues; - - /// - /// Scoring values for the current play assuming all perfect hits. - /// - /// - /// This is only used to determine the accuracy with respect to the current point in time for an ongoing play session. - /// - private ScoringValues currentMaximumScoringValues; - - /// - /// Scoring values for the current play. - /// - private ScoringValues currentScoringValues; - - /// - /// The maximum of a basic (non-tick and non-bonus) hitobject. - /// Only populated via or . - /// - private HitResult? maxBasicResult; - private bool beatmapApplied; private readonly Dictionary scoreResultCounts = new Dictionary(); @@ -152,18 +156,10 @@ namespace osu.Game.Rulesets.Scoring private readonly List hitEvents = new List(); private HitObject? lastHitObject; - private double scoreMultiplier = 1; - - public ScoreProcessor(Ruleset ruleset) + protected ScoreProcessor(Ruleset ruleset) { Ruleset = ruleset; - accuracyPortion = DefaultAccuracyPortion; - comboPortion = DefaultComboPortion; - - if (!Precision.AlmostEquals(1.0, accuracyPortion + comboPortion)) - throw new InvalidOperationException($"{nameof(DefaultAccuracyPortion)} + {nameof(DefaultComboPortion)} must equal 1."); - Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue); Accuracy.ValueChanged += accuracy => { @@ -175,10 +171,10 @@ namespace osu.Game.Rulesets.Scoring Mode.ValueChanged += _ => updateScore(); Mods.ValueChanged += mods => { - scoreMultiplier = 1; + ScoreMultiplier = 1; foreach (var m in mods.NewValue) - scoreMultiplier *= m.ScoreMultiplier; + ScoreMultiplier *= m.ScoreMultiplier; updateScore(); }; @@ -200,10 +196,6 @@ namespace osu.Game.Rulesets.Scoring scoreResultCounts[result.Type] = scoreResultCounts.GetValueOrDefault(result.Type) + 1; - // Always update the maximum scoring values. - applyResult(result.Judgement.MaxResult, ref currentMaximumScoringValues); - currentMaximumScoringValues.MaxCombo += result.Judgement.MaxResult.IncreasesCombo() ? 1 : 0; - if (!result.Type.IsScorable()) return; @@ -212,8 +204,13 @@ namespace osu.Game.Rulesets.Scoring else if (result.Type.BreaksCombo()) Combo.Value = 0; - applyResult(result.Type, ref currentScoringValues); - currentScoringValues.MaxCombo = HighestCombo.Value; + if (result.Type.IsBasic()) + CurrentBasicJudgements++; + + currentMaxBasicScore += Judgement.ToNumericResult(result.Judgement.MaxResult); + currentBasicScore += Judgement.ToNumericResult(result.Type); + + AddScoreChange(result); hitEvents.Add(CreateHitEvent(result)); lastHitObject = result.HitObject; @@ -221,20 +218,6 @@ namespace osu.Game.Rulesets.Scoring updateScore(); } - private static void applyResult(HitResult result, ref ScoringValues scoringValues) - { - if (!result.IsScorable()) - return; - - if (result.IsBonus()) - scoringValues.BonusScore += result.IsHit() ? Judgement.ToNumericResult(result) : 0; - else - scoringValues.BaseScore += result.IsHit() ? Judgement.ToNumericResult(result) : 0; - - if (result.IsBasic()) - scoringValues.CountBasicHitObjects++; - } - /// /// Creates the that describes a . /// @@ -253,15 +236,16 @@ namespace osu.Game.Rulesets.Scoring scoreResultCounts[result.Type] = scoreResultCounts.GetValueOrDefault(result.Type) - 1; - // Always update the maximum scoring values. - revertResult(result.Judgement.MaxResult, ref currentMaximumScoringValues); - currentMaximumScoringValues.MaxCombo -= result.Judgement.MaxResult.IncreasesCombo() ? 1 : 0; - if (!result.Type.IsScorable()) return; - revertResult(result.Type, ref currentScoringValues); - currentScoringValues.MaxCombo = HighestCombo.Value; + if (result.Type.IsBasic()) + CurrentBasicJudgements--; + + currentMaxBasicScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); + currentBasicScore -= Judgement.ToNumericResult(result.Type); + + RemoveScoreChange(result); Debug.Assert(hitEvents.Count > 0); lastHitObject = hitEvents[^1].LastHitObject; @@ -270,111 +254,31 @@ namespace osu.Game.Rulesets.Scoring updateScore(); } - private static void revertResult(HitResult result, ref ScoringValues scoringValues) + protected virtual void AddScoreChange(JudgementResult result) { - if (!result.IsScorable()) - return; - - if (result.IsBonus()) - scoringValues.BonusScore -= result.IsHit() ? Judgement.ToNumericResult(result) : 0; + if (result.Type.IsBonus()) + BonusPortion += Judgement.ToNumericResult(result.Type); else - scoringValues.BaseScore -= result.IsHit() ? Judgement.ToNumericResult(result) : 0; + ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); + } - if (result.IsBasic()) - scoringValues.CountBasicHitObjects--; + protected virtual void RemoveScoreChange(JudgementResult result) + { + if (result.Type.IsBonus()) + BonusPortion -= Judgement.ToNumericResult(result.Type); + else + ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); } private void updateScore() { - Accuracy.Value = currentMaximumScoringValues.BaseScore > 0 ? (double)currentScoringValues.BaseScore / currentMaximumScoringValues.BaseScore : 1; - MinimumAccuracy.Value = maximumScoringValues.BaseScore > 0 ? (double)currentScoringValues.BaseScore / maximumScoringValues.BaseScore : 0; - MaximumAccuracy.Value = maximumScoringValues.BaseScore > 0 - ? (double)(currentScoringValues.BaseScore + (maximumScoringValues.BaseScore - currentMaximumScoringValues.BaseScore)) / maximumScoringValues.BaseScore - : 1; - TotalScore.Value = computeScore(Mode.Value, currentScoringValues, maximumScoringValues); + Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; + + // Todo: Classic/Standardised + TotalScore.Value = (long)Math.Round(ComputeTotalScore()); } - /// - /// Computes the accuracy of a given . - /// - /// The to compute the total score of. - /// The score's accuracy. - [Pure] - public double ComputeAccuracy(ScoreInfo scoreInfo) - { - if (!Ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) - throw new ArgumentException($"Unexpected score ruleset. Expected \"{Ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); - - // We only extract scoring values from the score's statistics. This is because accuracy is always relative to the point of pass or fail rather than relative to the whole beatmap. - extractScoringValues(scoreInfo.Statistics, out var current, out var maximum); - - return maximum.BaseScore > 0 ? (double)current.BaseScore / maximum.BaseScore : 1; - } - - /// - /// Computes the total score of a given . - /// - /// - /// Does not require to have been called before use. - /// - /// The to represent the score as. - /// The to compute the total score of. - /// The total score in the given . - [Pure] - public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo) - { - if (!Ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) - throw new ArgumentException($"Unexpected score ruleset. Expected \"{Ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); - - extractScoringValues(scoreInfo, out var current, out var maximum); - - return computeScore(mode, current, maximum); - } - - /// - /// Computes the total score from scoring values. - /// - /// The to represent the score as. - /// The current scoring values. - /// The maximum scoring values. - /// The total score computed from the given scoring values. - [Pure] - private long computeScore(ScoringMode mode, ScoringValues current, ScoringValues maximum) - { - double accuracyRatio = maximum.BaseScore > 0 ? (double)current.BaseScore / maximum.BaseScore : 1; - double comboRatio = maximum.MaxCombo > 0 ? (double)current.MaxCombo / maximum.MaxCombo : 1; - return ComputeScore(mode, accuracyRatio, comboRatio, current.BonusScore, maximum.CountBasicHitObjects); - } - - /// - /// Computes the total score from individual scoring components. - /// - /// The to represent the score as. - /// The accuracy percentage achieved by the player. - /// The portion of the max combo achieved by the player. - /// The total bonus score. - /// The total number of basic (non-tick and non-bonus) hitobjects in the beatmap. - /// The total score computed from the given scoring component ratios. - [Pure] - public long ComputeScore(ScoringMode mode, double accuracyRatio, double comboRatio, long bonusScore, int totalBasicHitObjects) - { - double accuracyScore = accuracyPortion * accuracyRatio; - double comboScore = comboPortion * comboRatio; - double rawScore = (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier; - - switch (mode) - { - default: - case ScoringMode.Standardised: - return (long)Math.Round(rawScore); - - case ScoringMode.Classic: - // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. - // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. - double scaledRawScore = rawScore / max_score; - return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, totalBasicHitObjects), 2) * ClassicScoreMultiplier); - } - } + protected abstract double ComputeTotalScore(); /// /// Resets this ScoreProcessor to a default state. @@ -389,7 +293,8 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { - maximumScoringValues = currentScoringValues; + MaxComboPortion = ComboPortion; + MaxBasicJudgements = CurrentBasicJudgements; maximumResultCounts.Clear(); maximumResultCounts.AddRange(scoreResultCounts); @@ -397,8 +302,11 @@ namespace osu.Game.Rulesets.Scoring scoreResultCounts.Clear(); - currentScoringValues = default; - currentMaximumScoringValues = default; + currentBasicScore = 0; + currentMaxBasicScore = 0; + CurrentBasicJudgements = 0; + ComboPortion = 0; + BonusPortion = 0; TotalScore.Value = 0; Accuracy.Value = 1; @@ -406,6 +314,9 @@ namespace osu.Game.Rulesets.Scoring Rank.Disabled = false; Rank.Value = ScoreRank.X; HighestCombo.Value = 0; + + currentBasicScore = 0; + currentMaxBasicScore = 0; } /// @@ -428,7 +339,7 @@ namespace osu.Game.Rulesets.Scoring score.MaximumStatistics[result] = maximumResultCounts.GetValueOrDefault(result); // Populate total score after everything else. - score.TotalScore = ComputeScore(ScoringMode.Standardised, score); + score.TotalScore = TotalScore.Value; } /// @@ -452,12 +363,6 @@ namespace osu.Game.Rulesets.Scoring if (frame.Header == null) return; - extractScoringValues(frame.Header.Statistics, out var current, out var maximum); - currentScoringValues.BaseScore = current.BaseScore; - currentScoringValues.MaxCombo = frame.Header.MaxCombo; - currentMaximumScoringValues.BaseScore = maximum.BaseScore; - currentMaximumScoringValues.MaxCombo = maximum.MaxCombo; - Combo.Value = frame.Header.Combo; HighestCombo.Value = frame.Header.MaxCombo; @@ -469,105 +374,6 @@ namespace osu.Game.Rulesets.Scoring OnResetFromReplayFrame?.Invoke(); } - #region ScoringValue extraction - - /// - /// Applies a best-effort extraction of hit statistics into . - /// - /// - /// This method is useful in a variety of situations, with a few drawbacks that need to be considered: - /// - /// The maximum will always be 0. - /// The current and maximum will always be the same value. - /// - /// Consumers are expected to more accurately fill in the above values through external means. - /// - /// Ensure to fill in the maximum for use in - /// . - /// - /// - /// The score to extract scoring values from. - /// The "current" scoring values, representing the hit statistics as they appear. - /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time. - [Pure] - private void extractScoringValues(ScoreInfo scoreInfo, out ScoringValues current, out ScoringValues maximum) - { - extractScoringValues(scoreInfo.Statistics, out current, out maximum); - current.MaxCombo = scoreInfo.MaxCombo; - - if (scoreInfo.MaximumStatistics.Count > 0) - extractScoringValues(scoreInfo.MaximumStatistics, out _, out maximum); - } - - /// - /// Applies a best-effort extraction of hit statistics into . - /// - /// - /// This method is useful in a variety of situations, with a few drawbacks that need to be considered: - /// - /// The current will always be 0. - /// The maximum will always be 0. - /// The current and maximum will always be the same value. - /// - /// Consumers are expected to more accurately fill in the above values (especially the current ) via external means (e.g. ). - /// - /// The hit statistics to extract scoring values from. - /// The "current" scoring values, representing the hit statistics as they appear. - /// The "maximum" scoring values, representing the hit statistics as if the maximum hit result was attained each time. - [Pure] - private void extractScoringValues(IReadOnlyDictionary statistics, out ScoringValues current, out ScoringValues maximum) - { - current = default; - maximum = default; - - foreach ((HitResult result, int count) in statistics) - { - if (!result.IsScorable()) - continue; - - if (result.IsBonus()) - current.BonusScore += count * Judgement.ToNumericResult(result); - - if (result.AffectsAccuracy()) - { - // The maximum result of this judgement if it wasn't a miss. - // E.g. For a GOOD judgement, the max result is either GREAT/PERFECT depending on which one the ruleset uses (osu!: GREAT, osu!mania: PERFECT). - HitResult maxResult; - - switch (result) - { - case HitResult.LargeTickHit: - case HitResult.LargeTickMiss: - maxResult = HitResult.LargeTickHit; - break; - - case HitResult.SmallTickHit: - case HitResult.SmallTickMiss: - maxResult = HitResult.SmallTickHit; - break; - - default: - maxResult = maxBasicResult ??= Ruleset.GetHitResults().MaxBy(kvp => Judgement.ToNumericResult(kvp.result)).result; - break; - } - - current.BaseScore += count * Judgement.ToNumericResult(result); - maximum.BaseScore += count * Judgement.ToNumericResult(maxResult); - } - - if (result.AffectsCombo()) - maximum.MaxCombo += count; - - if (result.IsBasic()) - { - current.CountBasicHitObjects += count; - maximum.CountBasicHitObjects += count; - } - } - } - - #endregion - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -629,32 +435,6 @@ namespace osu.Game.Rulesets.Scoring } #endregion - - /// - /// Stores the required scoring data that fulfils the minimum requirements for a to calculate score. - /// - private struct ScoringValues - { - /// - /// The sum of all "basic" scoring values. See: and . - /// - public long BaseScore; - - /// - /// The sum of all "bonus" scoring values. See: and . - /// - public long BonusScore; - - /// - /// The highest achieved combo. - /// - public int MaxCombo; - - /// - /// The count of "basic" s. See: . - /// - public int CountBasicHitObjects; - } } public enum ScoringMode diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 3e6d09b74a..3779156fda 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -115,7 +115,9 @@ namespace osu.Game.Scoring var scoreProcessor = ruleset.CreateScoreProcessor(); scoreProcessor.Mods.Value = score.Mods; - return scoreProcessor.ComputeScore(mode, score); + // Todo: + return 0; + // return scoreProcessor.ComputeScore(mode, score); } /// diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index 0c25a32259..7b77785c7a 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -67,7 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists { await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); - Score.ScoreInfo.TotalScore = ScoreProcessor.ComputeScore(ScoringMode.Standardised, Score.ScoreInfo); + // Todo: + // Score.ScoreInfo.TotalScore = ScoreProcessor.ComputeScore(ScoringMode.Standardised, Score.ScoreInfo); } protected override void Dispose(bool isDisposing) From a7b623f52af08fd05d89366f169fe75031fa14c3 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 9 May 2023 20:00:14 +0900 Subject: [PATCH 0807/1400] Reimplement classic scoring mode --- .../Scoring/CatchScoreProcessor.cs | 12 +++++------- .../Scoring/ManiaScoreProcessor.cs | 12 +++++------- .../Scoring/OsuScoreProcessor.cs | 12 +++++------- .../Scoring/TaikoScoreProcessor.cs | 12 +++++------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 16 ++++++++++++++-- osu.Game/Scoring/ScoreManager.cs | 8 +++----- 6 files changed, 37 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index bf5c3a91d6..9c5359ebeb 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -31,13 +31,11 @@ namespace osu.Game.Rulesets.Catch.Scoring const int tiny_droplets_portion = 400000; - return - (int)Math.Round - (( - ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion + - tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + - BonusPortion - ) * ScoreMultiplier); + return ( + ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion + + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + + BonusPortion + ) * ScoreMultiplier; } protected override void AddScoreChange(JudgementResult result) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 7d188c6786..19f8a4a639 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -20,13 +20,11 @@ namespace osu.Game.Rulesets.Mania.Scoring protected override double ComputeTotalScore() { - return - (int)Math.Round - (( - 200000 * ComboPortion / MaxComboPortion + - 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + - BonusPortion - ) * ScoreMultiplier); + return ( + 200000 * ComboPortion / MaxComboPortion + + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier; } protected override void AddScoreChange(JudgementResult result) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 5f5997b0c1..f8cbf1a641 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -17,13 +17,11 @@ namespace osu.Game.Rulesets.Osu.Scoring protected override double ComputeTotalScore() { - return - (int)Math.Round - (( - 700000 * ComboPortion / MaxComboPortion + - 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + - BonusPortion - ) * ScoreMultiplier); + return ( + 700000 * ComboPortion / MaxComboPortion + + 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier; } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index caf0a799a2..71eb0b1602 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -21,13 +21,11 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override double ComputeTotalScore() { - return - (int)Math.Round - (( - 250000 * ComboPortion / MaxComboPortion + - 750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + - BonusPortion - ) * ScoreMultiplier); + return ( + 250000 * ComboPortion / MaxComboPortion + + 750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier; } protected override void AddScoreChange(JudgementResult result) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 8373ebd50c..9172034ff6 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -274,8 +274,20 @@ namespace osu.Game.Rulesets.Scoring { Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; - // Todo: Classic/Standardised - TotalScore.Value = (long)Math.Round(ComputeTotalScore()); + double standardisedScore = ComputeTotalScore(); + + if (Mode.Value == ScoringMode.Standardised) + TotalScore.Value = (long)Math.Round(standardisedScore); + else + TotalScore.Value = ConvertToClassic(standardisedScore); + } + + public long ConvertToClassic(double standardised) + { + // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. + // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. + double scaledRawScore = standardised / MAX_SCORE; + return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, MaxBasicJudgements), 2) * ClassicScoreMultiplier); } protected abstract double ComputeTotalScore(); diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 3779156fda..0674947f30 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -107,17 +107,15 @@ namespace osu.Game.Scoring /// The total score. public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) { - // TODO: This is required for playlist aggregate scores. They should likely not be getting here in the first place. - if (string.IsNullOrEmpty(score.BeatmapInfo.MD5Hash)) + if (mode == ScoringMode.Standardised) return score.TotalScore; var ruleset = score.Ruleset.CreateInstance(); var scoreProcessor = ruleset.CreateScoreProcessor(); scoreProcessor.Mods.Value = score.Mods; - // Todo: - return 0; - // return scoreProcessor.ComputeScore(mode, score); + // Todo: This loses precision because we're dealing with pre-rounded total scores. + return scoreProcessor.ConvertToClassic(score.TotalScore); } /// From ca5e8b290f30006c93116e7d1ef47fbdb663fc00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 14:05:59 +0900 Subject: [PATCH 0808/1400] Add clamping to `SliderMultiplier` and `SliderTickRate` at parsing time --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 5e98025c9a..49594ca969 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -384,11 +384,11 @@ namespace osu.Game.Beatmaps.Formats break; case @"SliderMultiplier": - difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); + difficulty.SliderMultiplier = Math.Clamp(Parsing.ParseDouble(pair.Value), 0.4, 3.6); break; case @"SliderTickRate": - difficulty.SliderTickRate = Parsing.ParseDouble(pair.Value); + difficulty.SliderTickRate = Math.Clamp(Parsing.ParseDouble(pair.Value), 0.5, 8); break; } } From bdf8a78b4245dc008e8661820ea3cbcff42b97e8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 8 May 2023 14:14:54 +0900 Subject: [PATCH 0809/1400] Add the ability to adjust the beatmap tick rate in the editor --- osu.Game/Localisation/EditorSetupStrings.cs | 31 ++++++++++--------- .../Screens/Edit/Setup/DifficultySection.cs | 15 +++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/osu.Game/Localisation/EditorSetupStrings.cs b/osu.Game/Localisation/EditorSetupStrings.cs index caea3dd130..401411365b 100644 --- a/osu.Game/Localisation/EditorSetupStrings.cs +++ b/osu.Game/Localisation/EditorSetupStrings.cs @@ -42,8 +42,7 @@ namespace osu.Game.Localisation /// /// "If enabled, an "Are you ready? 3, 2, 1, GO!" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so." /// - public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), - @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); + public static LocalisableString CountdownDescription => new TranslatableString(getKey(@"countdown_description"), @"If enabled, an ""Are you ready? 3, 2, 1, GO!"" countdown will be inserted at the beginning of the beatmap, assuming there is enough time to do so."); /// /// "Countdown speed" @@ -53,8 +52,7 @@ namespace osu.Game.Localisation /// /// "If the countdown sounds off-time, use this to make it appear one or more beats early." /// - public static LocalisableString CountdownOffsetDescription => - new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); + public static LocalisableString CountdownOffsetDescription => new TranslatableString(getKey(@"countdown_offset_description"), @"If the countdown sounds off-time, use this to make it appear one or more beats early."); /// /// "Countdown offset" @@ -69,8 +67,7 @@ namespace osu.Game.Localisation /// /// "Allows storyboards to use the full screen space, rather than be confined to a 4:3 area." /// - public static LocalisableString WidescreenSupportDescription => - new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); + public static LocalisableString WidescreenSupportDescription => new TranslatableString(getKey(@"widescreen_support_description"), @"Allows storyboards to use the full screen space, rather than be confined to a 4:3 area."); /// /// "Epilepsy warning" @@ -80,8 +77,7 @@ namespace osu.Game.Localisation /// /// "Recommended if the storyboard or video contain scenes with rapidly flashing colours." /// - public static LocalisableString EpilepsyWarningDescription => - new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); + public static LocalisableString EpilepsyWarningDescription => new TranslatableString(getKey(@"epilepsy_warning_description"), @"Recommended if the storyboard or video contain scenes with rapidly flashing colours."); /// /// "Letterbox during breaks" @@ -91,8 +87,7 @@ namespace osu.Game.Localisation /// /// "Adds horizontal letterboxing to give a cinematic look during breaks." /// - public static LocalisableString LetterboxDuringBreaksDescription => - new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); + public static LocalisableString LetterboxDuringBreaksDescription => new TranslatableString(getKey(@"letterbox_during_breaks_description"), @"Adds horizontal letterboxing to give a cinematic look during breaks."); /// /// "Samples match playback rate" @@ -102,8 +97,7 @@ namespace osu.Game.Localisation /// /// "When enabled, all samples will speed up or slow down when rate-changing mods are enabled." /// - public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), - @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); + public static LocalisableString SamplesMatchPlaybackRateDescription => new TranslatableString(getKey(@"samples_match_playback_rate_description"), @"When enabled, all samples will speed up or slow down when rate-changing mods are enabled."); /// /// "The size of all hit objects" @@ -123,8 +117,17 @@ namespace osu.Game.Localisation /// /// "The harshness of hit windows and difficulty of special objects (ie. spinners)" /// - public static LocalisableString OverallDifficultyDescription => - new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + public static LocalisableString OverallDifficultyDescription => new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)"); + + /// + /// "Tick Rate" + /// + public static LocalisableString TickRate => new TranslatableString(getKey(@"tick_rate"), @"Tick Rate"); + + /// + /// "Determines how many "ticks" are generated within long hit objects. A tick rate of 1 will generate ticks on each beat, 2 would be twice per beat, etc." + /// + public static LocalisableString TickRateDescription => new TranslatableString(getKey(@"tick_rate_description"), @"Determines how many ""ticks"" are generated within long hit objects. A tick rate of 1 will generate ticks on each beat, 2 would be twice per beat, etc."); /// /// "Base Velocity" diff --git a/osu.Game/Screens/Edit/Setup/DifficultySection.cs b/osu.Game/Screens/Edit/Setup/DifficultySection.cs index 3a3fe7f747..4c062b0cb7 100644 --- a/osu.Game/Screens/Edit/Setup/DifficultySection.cs +++ b/osu.Game/Screens/Edit/Setup/DifficultySection.cs @@ -20,6 +20,7 @@ namespace osu.Game.Screens.Edit.Setup private LabelledSliderBar approachRateSlider = null!; private LabelledSliderBar overallDifficultySlider = null!; private LabelledSliderBar baseVelocitySlider = null!; + private LabelledSliderBar tickRateSlider = null!; public override LocalisableString Title => EditorSetupStrings.DifficultyHeader; @@ -93,6 +94,19 @@ namespace osu.Game.Screens.Edit.Setup Precision = 0.01f, } }, + tickRateSlider = new LabelledSliderBar + { + Label = EditorSetupStrings.TickRate, + FixedLabelWidth = LABEL_WIDTH, + Description = EditorSetupStrings.TickRateDescription, + Current = new BindableDouble(Beatmap.Difficulty.SliderTickRate) + { + Default = 1, + MinValue = 1, + MaxValue = 4, + Precision = 1, + } + }, }; foreach (var item in Children.OfType>()) @@ -111,6 +125,7 @@ namespace osu.Game.Screens.Edit.Setup Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value; Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value; + Beatmap.Difficulty.SliderTickRate = tickRateSlider.Current.Value; Beatmap.UpdateAllHitObjects(); Beatmap.SaveState(); From 2467813d8199473f2b37041fb005065c312dd7d2 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 9 May 2023 16:14:42 +0300 Subject: [PATCH 0810/1400] Block `deselect all` short key when using the search box --- .../TestSceneModSelectOverlay.cs | 20 +++++++++++++++++++ .../UserInterface/ShearedSearchTextBox.cs | 2 ++ .../Overlays/Mods/DeselectAllModsButton.cs | 8 +++++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 20 +++++++++++-------- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 8e4f437f44..d1cbe7d91c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -481,6 +481,26 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("all mods deselected", () => !SelectedMods.Value.Any()); } + [Test] + public void TestDeselectAllViaKey_WithSearchApplied() + { + createScreen(); + changeRuleset(0); + + AddStep("select DT + HD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden() }); + AddStep("focus on search", () => modSelectOverlay.SearchTextBox.TakeFocus()); + AddStep("apply search", () => modSelectOverlay.SearchTerm = "Easy"); + AddAssert("DT + HD selected and hidden", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.IsValid && panel.Active.Value) == 2); + + AddStep("press backspace", () => InputManager.Key(Key.BackSpace)); + AddAssert("DT + HD still selected", () => modSelectOverlay.ChildrenOfType().Count(panel => panel.Active.Value) == 2); + AddAssert("search term changed", () => modSelectOverlay.SearchTerm == "Eas"); + + AddStep("kill focus", () => modSelectOverlay.SearchTextBox.KillFocus()); + AddStep("press backspace", () => InputManager.Key(Key.BackSpace)); + AddUntilStep("all mods deselected", () => !SelectedMods.Value.Any()); + } + [Test] public void TestDeselectAllViaButton() { diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index 7bd083f9d5..a6954fafb1 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -37,6 +37,8 @@ namespace osu.Game.Graphics.UserInterface set => textBox.HoldFocus = value; } + public new bool HasFocus => textBox.HasFocus; + public void TakeFocus() => textBox.TakeFocus(); public void KillFocus() => textBox.KillFocus(); diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index 3e5a3b12d1..d4d196508f 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Mods public partial class DeselectAllModsButton : ShearedButton, IKeyBindingHandler { private readonly Bindable> selectedMods = new Bindable>(); + private readonly ShearedSearchTextBox searchTextBox; public DeselectAllModsButton(ModSelectOverlay modSelectOverlay) : base(ModSelectOverlay.BUTTON_WIDTH) @@ -25,6 +26,8 @@ namespace osu.Game.Overlays.Mods Text = CommonStrings.DeselectAll; Action = modSelectOverlay.DeselectAll; + searchTextBox = modSelectOverlay.SearchTextBox; + selectedMods.BindTo(modSelectOverlay.SelectedMods); } @@ -40,9 +43,8 @@ namespace osu.Game.Overlays.Mods Enabled.Value = selectedMods.Value.Any(); } - public bool OnPressed(KeyBindingPressEvent e) - { - if (e.Repeat || e.Action != GlobalAction.DeselectAllMods) + public bool OnPressed(KeyBindingPressEvent e) { + if (e.Repeat || e.Action != GlobalAction.DeselectAllMods || searchTextBox.HasFocus) return false; TriggerClick(); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index cb8eddca62..fdc948bcbf 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -69,16 +69,21 @@ namespace osu.Game.Overlays.Mods /// public string SearchTerm { - get => searchTextBox.Current.Value; + get => SearchTextBox.Current.Value; set { - if (searchTextBox.Current.Value == value) + if (SearchTextBox.Current.Value == value) return; - searchTextBox.Current.Value = value; + SearchTextBox.Current.Value = value; } } + /// + /// Search box applied on mod overlay + /// + public ShearedSearchTextBox SearchTextBox { get; private set; } = null!; + /// /// Whether the total score multiplier calculated from the current selected set of mods should be shown. /// @@ -124,7 +129,6 @@ namespace osu.Game.Overlays.Mods private FillFlowContainer footerButtonFlow = null!; private Container aboveColumnsContent = null!; - private ShearedSearchTextBox searchTextBox = null!; private DifficultyMultiplierDisplay? multiplierDisplay; protected ShearedButton BackButton { get; private set; } = null!; @@ -168,7 +172,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Padding = new MarginPadding { Horizontal = 100 }, - Child = searchTextBox = new ShearedSearchTextBox + Child = SearchTextBox = new ShearedSearchTextBox { HoldFocus = false, Width = 300 @@ -250,8 +254,8 @@ namespace osu.Game.Overlays.Mods { base.Hide(); - //We want to clear search for next user iteraction with mod overlay - searchTextBox.Current.Value = string.Empty; + //We want to clear search for next user interaction with mod overlay + SearchTextBox.Current.Value = string.Empty; } private ModSettingChangeTracker? modSettingChangeTracker; @@ -287,7 +291,7 @@ namespace osu.Game.Overlays.Mods customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); - searchTextBox.Current.BindValueChanged(query => + SearchTextBox.Current.BindValueChanged(query => { foreach (var column in columnFlow.Columns) column.SearchTerm = query.NewValue; From 84efddcbc7cb09db82ccb58d2a57bd80c1b9c1fd Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 9 May 2023 15:53:36 +0200 Subject: [PATCH 0811/1400] Fix default progress graph flipping with a hack --- osu.Game/Screens/Play/SquareGraph.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 57b7c84e89..8636f08b00 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -75,18 +75,28 @@ namespace osu.Game.Screens.Play private Vector2 previousDrawSize; + private Vector2 previousParentScale; + protected override void Update() { base.Update(); - if (graphNeedsUpdate || (values != null && DrawSize != previousDrawSize)) + bool hasFlipped = previousParentScale != Parent.Scale; + if (graphNeedsUpdate || (values != null && DrawSize != previousDrawSize) || hasFlipped) { - columns?.FadeOut(500, Easing.OutQuint).Expire(); - scheduledCreate?.Cancel(); - scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + + if (!hasFlipped) + { + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + } + else + { + RecreateGraph(); + } previousDrawSize = DrawSize; + previousParentScale = Parent.Scale; graphNeedsUpdate = false; } } From ad80e2ff5119322dfadaadfa57622bd6aca5afbe Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 9 May 2023 17:15:54 +0200 Subject: [PATCH 0812/1400] More robust implementation --- osu.Game/Screens/Play/SquareGraph.cs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 8636f08b00..a498917504 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -81,20 +81,31 @@ namespace osu.Game.Screens.Play { base.Update(); - bool hasFlipped = previousParentScale != Parent.Scale; - if (graphNeedsUpdate || (values != null && DrawSize != previousDrawSize) || hasFlipped) + bool extraUpdateConditions = + DrawSize != previousDrawSize || + previousParentScale != Parent.Scale; + + if (graphNeedsUpdate || (values != null && extraUpdateConditions)) { - scheduledCreate?.Cancel(); + bool hasFlipped = + previousParentScale.X == -Parent.Scale.X || + previousParentScale.Y == -Parent.Scale.Y; if (!hasFlipped) { - scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + columns?.FadeOut(500, Easing.OutQuint).Expire(); } else { - RecreateGraph(); + if (columns != null) + { + columns.Alpha = 0.0f; + } } + scheduledCreate?.Cancel(); + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + previousDrawSize = DrawSize; previousParentScale = Parent.Scale; graphNeedsUpdate = false; From 745341ca6b4b5c1ed40b362a2fece9af58a7af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 9 May 2023 21:55:53 +0200 Subject: [PATCH 0813/1400] Fix iOS build workflow failing A new version of `Microsoft.iOS.Sdk` was released on 2023-05-09T17:28:41.7300000. This version requires Xcode 14.3, which is not currently available on `macos-latest` runners (which currently alias to `macos-12`). To fix, migrate to `macos-13`, which is currently in beta, and explicitly use Xcode 14.3 (because even on the `macos-13` image, Xcode 14.3 is not yet the default). --- .github/workflows/ci.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e60e0a39ae..a8167ec4db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,12 +121,24 @@ jobs: build-only-ios: name: Build only (iOS) - runs-on: macos-latest + # `macos-13` is required, because Xcode 14.3 is required (see below). + # TODO: can be changed to `macos-latest` once `macos-13` becomes latest (currently in beta) + runs-on: macos-13 timeout-minutes: 60 steps: - name: Checkout uses: actions/checkout@v3 + # newest Microsoft.iOS.Sdk versions require Xcode 14.3. + # 14.3 is currently not the default Xcode version (https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#xcode), + # so set it manually. + # TODO: remove when 14.3 becomes the default Xcode version. + - name: Set Xcode version + shell: bash + run: | + sudo xcode-select -s "/Applications/Xcode_14.3.app" + echo "MD_APPLE_SDK_ROOT=/Applications/Xcode_14.3.app" >> $GITHUB_ENV + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v3 with: From 4aa241daeab7d12eb8a32f1bb1da78ed5749a5c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 May 2023 15:19:43 +0900 Subject: [PATCH 0814/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e9ecbaa10b..ff76e17184 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7ab9810ab5..93f22a31d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index bfa0dc63bb..c5477f765e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 3fc19553b4435211370cfd2655ed35992ae95aa7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 May 2023 15:19:46 +0900 Subject: [PATCH 0815/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 93f22a31d8..4315f44e07 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From ca688507304721a799c85a40900c1624976954c7 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 10 May 2023 19:43:58 +0300 Subject: [PATCH 0816/1400] fix formatting --- osu.Game/Overlays/Mods/DeselectAllModsButton.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index d4d196508f..bdb37e3ead 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -43,7 +43,8 @@ namespace osu.Game.Overlays.Mods Enabled.Value = selectedMods.Value.Any(); } - public bool OnPressed(KeyBindingPressEvent e) { + public bool OnPressed(KeyBindingPressEvent e) + { if (e.Repeat || e.Action != GlobalAction.DeselectAllMods || searchTextBox.HasFocus) return false; From c1a85658b728614be2f25fbca7d8dda1916865f3 Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 11 May 2023 14:58:17 +0100 Subject: [PATCH 0817/1400] feat(settings): add "import" as keywords for first run setup --- osu.Game/Overlays/Settings/Sections/GeneralSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index c5274d6223..b12541b261 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Settings.Sections new SettingsButton { Text = GeneralSettingsStrings.RunSetupWizard, - Keywords = new[] { @"first run", @"initial", @"getting started" }, + Keywords = new[] { @"first run", @"initial", @"getting started", @"import" }, TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, From 2d45d602a538532245f9fe4287700e27493e962b Mon Sep 17 00:00:00 2001 From: tsrk Date: Thu, 11 May 2023 15:03:42 +0100 Subject: [PATCH 0818/1400] feat(settings): more keyword for first run setup --- osu.Game/Overlays/Settings/Sections/GeneralSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index b12541b261..f4a79d65e6 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Settings.Sections new SettingsButton { Text = GeneralSettingsStrings.RunSetupWizard, - Keywords = new[] { @"first run", @"initial", @"getting started", @"import" }, + Keywords = new[] { @"first run", @"initial", @"getting started", @"import", @"tutorial", @"recommended beatmaps" }, TooltipText = FirstRunSetupOverlayStrings.FirstRunSetupDescription, Action = () => firstRunSetupOverlay?.Show(), }, From 4732c8a06c73c8e8e63673f6bbf21c7dd45c1b92 Mon Sep 17 00:00:00 2001 From: alix Date: Thu, 11 May 2023 13:46:07 -0400 Subject: [PATCH 0819/1400] fix angle sharpness slider value from not always scaling by 0.5 --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 307d731fd4..b8ce667398 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods { MinValue = 1, MaxValue = 10, - Precision = 0.1f + Precision = 0.5f }; private static readonly float playfield_diagonal = OsuPlayfield.BASE_SIZE.LengthFast; From 3bce7ac58931806ddaa81191b04e744ffbdef680 Mon Sep 17 00:00:00 2001 From: js1086 Date: Thu, 11 May 2023 19:07:22 +0100 Subject: [PATCH 0820/1400] Copy SliderVelocity to strict tracking sliders --- osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs index 7e4ffc7408..72031b4958 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs @@ -98,6 +98,7 @@ namespace osu.Game.Rulesets.Osu.Mods ComboOffset = original.ComboOffset; LegacyLastTickOffset = original.LegacyLastTickOffset; TickDistanceMultiplier = original.TickDistanceMultiplier; + SliderVelocity = original.SliderVelocity; } protected override void CreateNestedHitObjects(CancellationToken cancellationToken) From a4954e64acb288a3a3ca1d6213ef63f68d812a64 Mon Sep 17 00:00:00 2001 From: alix Date: Thu, 11 May 2023 23:45:41 -0400 Subject: [PATCH 0821/1400] fix precision from making mouse input also go 0.5 --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index b8ce667398..89767b29c1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -22,18 +22,27 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Mod that randomises the positions of the s /// + + public partial class AngleSharpnessSlider : SettingsSlider + { + public AngleSharpnessSlider() + { + KeyboardStep = 0.5f; + } + } + public class OsuModRandom : ModRandom, IApplicableToBeatmap { public override LocalisableString Description => "It never gets boring!"; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModTargetPractice)).ToArray(); - [SettingSource("Angle sharpness", "How sharp angles should be", SettingControlType = typeof(SettingsSlider))] + [SettingSource("Angle sharpness", "How sharp angles should be", SettingControlType = typeof(AngleSharpnessSlider))] public BindableFloat AngleSharpness { get; } = new BindableFloat(7) { MinValue = 1, MaxValue = 10, - Precision = 0.5f + Precision = 0.1f }; private static readonly float playfield_diagonal = OsuPlayfield.BASE_SIZE.LengthFast; From e50cab9e81196405011654019cd003a795018789 Mon Sep 17 00:00:00 2001 From: alix Date: Thu, 11 May 2023 23:48:31 -0400 Subject: [PATCH 0822/1400] move class to the bottom of the file --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 89767b29c1..3d19a4d6eb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -22,15 +22,6 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Mod that randomises the positions of the s /// - - public partial class AngleSharpnessSlider : SettingsSlider - { - public AngleSharpnessSlider() - { - KeyboardStep = 0.5f; - } - } - public class OsuModRandom : ModRandom, IApplicableToBeatmap { public override LocalisableString Description => "It never gets boring!"; @@ -170,5 +161,13 @@ namespace osu.Game.Rulesets.Osu.Mods return previousObjectStartedCombo && random.NextDouble() < 0.6f; } + + public partial class AngleSharpnessSlider : SettingsSlider + { + public AngleSharpnessSlider() + { + KeyboardStep = 0.5f; + } + } } } From 53ab780796fdb4a83366e84e5c00b58be3ac1cb1 Mon Sep 17 00:00:00 2001 From: alix Date: Thu, 11 May 2023 23:50:45 -0400 Subject: [PATCH 0823/1400] fix indents --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 3d19a4d6eb..61fb9189bc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -164,9 +164,9 @@ namespace osu.Game.Rulesets.Osu.Mods public partial class AngleSharpnessSlider : SettingsSlider { - public AngleSharpnessSlider() + public AngleSharpnessSlider() { - KeyboardStep = 0.5f; + KeyboardStep = 0.5f; } } } From b3a5e4d3052d4d97d4a97779f561359bf92c3217 Mon Sep 17 00:00:00 2001 From: alix Date: Fri, 12 May 2023 00:29:00 -0400 Subject: [PATCH 0824/1400] nest class outside of OsuModRandom --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 61fb9189bc..6affeb24d8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -161,13 +161,13 @@ namespace osu.Game.Rulesets.Osu.Mods return previousObjectStartedCombo && random.NextDouble() < 0.6f; } + } - public partial class AngleSharpnessSlider : SettingsSlider + public partial class AngleSharpnessSlider : SettingsSlider + { + public AngleSharpnessSlider() { - public AngleSharpnessSlider() - { - KeyboardStep = 0.5f; - } + KeyboardStep = 0.5f; } } } From c0f869e685970af218ef68640cabe755f2f93db5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 May 2023 14:57:54 +0900 Subject: [PATCH 0825/1400] Fix some tablet settings being hidden when searching using "area" keyword As discussed in https://github.com/ppy/osu/discussions/23504. --- osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs index 951cf3802f..4c9320c2a6 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/TabletSettings.cs @@ -3,6 +3,8 @@ #nullable disable +using System.Collections.Generic; +using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -23,6 +25,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input { public partial class TabletSettings : SettingsSubsection { + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "area" }); + public TabletAreaSelection AreaSelection { get; private set; } private readonly ITabletHandler tabletHandler; From f443cfb93e41c4c33e3f51bccd1583b382b5dd3a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 May 2023 16:00:40 +0900 Subject: [PATCH 0826/1400] Move blueprint validity conditions to allow more correct external usage of `EndPlacement` Until now, these were haphazardly enforce inline in blueprint implementations. The only thing stopping complete breakage is that `EndPlacement` wasn't called (too much) from outside the blueprint, leaving them responsible for their own placement. By moving this conditional out of the provided paramters to `EndPlacement`, it allows more flexible usage of that method externally. Coming in a future PR. --- .../Blueprints/BananaShowerPlacementBlueprint.cs | 4 +++- .../Blueprints/JuiceStreamPlacementBlueprint.cs | 4 +++- .../Edit/Blueprints/HoldNotePlacementBlueprint.cs | 4 +++- .../Blueprints/Sliders/SliderPlacementBlueprint.cs | 4 +++- .../Edit/Blueprints/TaikoSpanPlacementBlueprint.cs | 4 +++- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 13 +++++++++++-- 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs index 5f22ef5c12..1e63d32c41 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/BananaShowerPlacementBlueprint.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints private double placementStartTime; private double placementEndTime; + protected override bool IsValidForPlacement => HitObject.Duration > 0; + public BananaShowerPlacementBlueprint() { InternalChild = outline = new TimeSpanOutline(); @@ -49,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints case PlacementState.Active: if (e.Button != MouseButton.Right) break; - EndPlacement(HitObject.Duration > 0); + EndPlacement(true); return true; } diff --git a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs index 03ec674abb..9e50b5a80f 100644 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs @@ -24,6 +24,8 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints private InputManager inputManager = null!; + protected override bool IsValidForPlacement => HitObject.Duration > 0; + public JuiceStreamPlacementBlueprint() { InternalChildren = new Drawable[] @@ -70,7 +72,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints return true; case MouseButton.Right: - EndPlacement(HitObject.Duration > 0); + EndPlacement(true); return true; } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 21beee0769..381af8be7f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } + protected override bool IsValidForPlacement => HitObject.Duration > 0; + public HoldNotePlacementBlueprint() : base(new HoldNote()) { @@ -75,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints return; base.OnMouseUp(e); - EndPlacement(HitObject.Duration > 0); + EndPlacement(true); } private double originalStartTime; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 50514865e1..28ceb80627 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders [Resolved(CanBeNull = true)] private IDistanceSnapProvider snapProvider { get; set; } + protected override bool IsValidForPlacement => HitObject.Path.HasValidLength; + public SliderPlacementBlueprint() : base(new Slider()) { @@ -150,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void endCurve() { updateSlider(); - EndPlacement(HitObject.Path.HasValidLength); + EndPlacement(true); } protected override void Update() diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs index fcf2573d64..bc4129c982 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSpanPlacementBlueprint.cs @@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints private readonly IHasDuration spanPlacementObject; + protected override bool IsValidForPlacement => spanPlacementObject.Duration > 0; + public TaikoSpanPlacementBlueprint(HitObject hitObject) : base(hitObject) { @@ -73,7 +75,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints return; base.OnMouseUp(e); - EndPlacement(spanPlacementObject.Duration > 0); + EndPlacement(true); } public override void UpdateTimeAndPosition(SnapResult result) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index bdcb334738..253d59751d 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -47,6 +47,15 @@ namespace osu.Game.Rulesets.Edit [Resolved] private IPlacementHandler placementHandler { get; set; } + /// + /// Whether this blueprint is currently in a state that can be committed. + /// + /// + /// Override this with any preconditions that should be double-checked on committing. + /// If false is returned and a commit is attempted, the blueprint will be destroyed instead. + /// + protected virtual bool IsValidForPlacement => true; + protected PlacementBlueprint(HitObject hitObject) { HitObject = hitObject; @@ -88,7 +97,7 @@ namespace osu.Game.Rulesets.Edit /// Signals that the placement of has finished. /// This will destroy this , and add the HitObject.StartTime to the . /// - /// Whether the object should be committed. + /// Whether the object should be committed. Note that a commit may fail if is false. public void EndPlacement(bool commit) { switch (PlacementActive) @@ -102,7 +111,7 @@ namespace osu.Game.Rulesets.Edit break; } - placementHandler.EndPlacement(HitObject, commit); + placementHandler.EndPlacement(HitObject, IsValidForPlacement && commit); PlacementActive = PlacementState.Finished; } From 70e248b92790da42e5d74d4f966407af2c2e5e0e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 May 2023 15:48:53 +0900 Subject: [PATCH 0827/1400] Force placement of in-progress object when changing tools in the editor --- .../Components/ComposeBlueprintContainer.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 453e4b9130..07fb450628 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -317,12 +317,16 @@ namespace osu.Game.Screens.Edit.Compose.Components } } + private void commitIfPlacementActive() + { + CurrentPlacement?.EndPlacement(CurrentPlacement.PlacementActive == PlacementBlueprint.PlacementState.Active); + removePlacement(); + } + private void removePlacement() { - if (CurrentPlacement == null) return; - - CurrentPlacement.EndPlacement(false); - CurrentPlacement.Expire(); + CurrentPlacement?.EndPlacement(false); + CurrentPlacement?.Expire(); CurrentPlacement = null; } @@ -342,7 +346,8 @@ namespace osu.Game.Screens.Edit.Compose.Components currentTool = value; - refreshTool(); + // As per stable editor, when changing tools, we should forcefully commit any pending placement. + commitIfPlacementActive(); } } } From 0c1959ef2ff93e2e743a6a1a32b74e18c4028d5d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 May 2023 15:50:33 +0900 Subject: [PATCH 0828/1400] Allow commiting / undoing placement of blueprints using back / select bindings --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 28 +++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 253d59751d..12c0ea1807 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -9,10 +9,12 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; @@ -24,7 +26,7 @@ namespace osu.Game.Rulesets.Edit /// /// A blueprint which governs the creation of a new to actualisation. /// - public abstract partial class PlacementBlueprint : CompositeDrawable + public abstract partial class PlacementBlueprint : CompositeDrawable, IKeyBindingHandler { /// /// Whether the is currently mid-placement, but has not necessarily finished being placed. @@ -115,6 +117,30 @@ namespace osu.Game.Rulesets.Edit PlacementActive = PlacementState.Finished; } + public bool OnPressed(KeyBindingPressEvent e) + { + if (PlacementActive == PlacementState.Waiting) + return false; + + switch (e.Action) + { + case GlobalAction.Select: + EndPlacement(true); + return true; + + case GlobalAction.Back: + EndPlacement(false); + return true; + + default: + return false; + } + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + /// /// Updates the time and position of this based on the provided snap information. /// From 6180d0d620bcf6f49ec8e22168d23c5a7d7bb465 Mon Sep 17 00:00:00 2001 From: timiimit Date: Fri, 12 May 2023 15:00:46 +0200 Subject: [PATCH 0829/1400] Remove cached frame buffer --- osu.Game/Screens/Play/SquareGraph.cs | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 57b7c84e89..26283858a6 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -51,7 +51,8 @@ namespace osu.Game.Screens.Play if (value == values) return; values = value; - graphNeedsUpdate = true; + scheduledCreate?.Cancel(); + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); } } @@ -70,27 +71,6 @@ namespace osu.Game.Screens.Play } private ScheduledDelegate scheduledCreate; - - private bool graphNeedsUpdate; - - private Vector2 previousDrawSize; - - protected override void Update() - { - base.Update(); - - if (graphNeedsUpdate || (values != null && DrawSize != previousDrawSize)) - { - columns?.FadeOut(500, Easing.OutQuint).Expire(); - - scheduledCreate?.Cancel(); - scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); - - previousDrawSize = DrawSize; - graphNeedsUpdate = false; - } - } - private CancellationTokenSource cts; /// @@ -98,7 +78,7 @@ namespace osu.Game.Screens.Play /// protected virtual void RecreateGraph() { - var newColumns = new BufferedContainer(cachedFrameBuffer: true) + var newColumns = new BufferedContainer { RedrawOnScale = false, RelativeSizeAxes = Axes.Both, From 159cacf9c7299dfa72cf091bb31dc99030879d4b Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:27:28 +0200 Subject: [PATCH 0830/1400] Fix logic in recalculateValues() --- osu.Game/Screens/Play/SquareGraph.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 26283858a6..d521bb5448 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -139,18 +139,19 @@ namespace osu.Game.Screens.Play if (values == null) { for (float i = 0; i < ColumnCount; i++) + { newValues.Add(0); - - return; } - + } + else + { int max = values.Max(); - float step = values.Length / (float)ColumnCount; for (float i = 0; i < values.Length; i += step) { newValues.Add((float)values[(int)i] / max); + } } calculatedValues = newValues.ToArray(); From 21d7c62f303c2064dd99ae305d19c409f87cd4c6 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:29:11 +0200 Subject: [PATCH 0831/1400] Add optimized UpdateGraph --- osu.Game/Screens/Play/SquareGraph.cs | 122 +++++++++++++++++++-------- 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index d521bb5448..dd964b8908 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -16,6 +16,7 @@ using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Framework.Threading; +using osu.Framework.Layout; namespace osu.Game.Screens.Play { @@ -23,6 +24,8 @@ namespace osu.Game.Screens.Play { private BufferedContainer columns; + private readonly LayoutValue layout = new LayoutValue(Invalidation.DrawSize | Invalidation.DrawInfo); + public int ColumnCount => columns?.Children.Count ?? 0; private int progress; @@ -51,11 +54,13 @@ namespace osu.Game.Screens.Play if (value == values) return; values = value; - scheduledCreate?.Cancel(); - scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + haveValuesChanged = true; + layout.Invalidate(); } } + bool haveValuesChanged; + private Color4 fillColour; public Color4 FillColour @@ -70,43 +75,93 @@ namespace osu.Game.Screens.Play } } - private ScheduledDelegate scheduledCreate; - private CancellationTokenSource cts; - - /// - /// Recreates the entire graph. - /// - protected virtual void RecreateGraph() + public SquareGraph() { - var newColumns = new BufferedContainer + AddLayout(layout); + } + + [BackgroundDependencyLoader] + private void load() + { + Child = columns = new BufferedContainer(cachedFrameBuffer: true) { RedrawOnScale = false, - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.Both }; + } - for (float x = 0; x < DrawWidth; x += Column.WIDTH) + + // private Vector2 parentScale; + + protected override void Update() + { + base.Update(); + + if (!layout.IsValid) { - newColumns.Add(new Column(DrawHeight) + UpdateGraph(); + layout.Validate(); + } + } + + /// + /// Updates the graph by either adding or removing columns based on DrawWidth. + /// Does nothing if correct number of columns already exists and/or if haven't changed. + /// + protected virtual void UpdateGraph() + { + int targetColumnCount = values == null ? 0 : (int)(DrawWidth / Column.WIDTH); + + // early exit the most frequent case + if (!haveValuesChanged && targetColumnCount == ColumnCount) + { + columns.ForceRedraw(); + return; + } + + ensureColumnCount(targetColumnCount); + + // fill graph data + recalculateValues(); + redrawFilled(); + redrawProgress(); + + haveValuesChanged = false; + } + + private void ensureColumnCount(int targetColumnCount) + { + // remove excess columns + while (targetColumnCount < ColumnCount) + { + columns.Remove(columns.Children[ColumnCount - 1], true); + } + + // update height of existing columns + foreach (var column in columns) + { + column.Height = DrawHeight; + } + + // add missing columns + float x = ColumnCount * Column.WIDTH; + while (targetColumnCount > ColumnCount) + { + var column = new Column() { + Height = DrawHeight, LitColour = fillColour, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Position = new Vector2(x, 0), State = ColumnState.Dimmed, - }); + }; + + LoadComponentAsync(column); + columns.Add(column); + + x += Column.WIDTH; } - - cts?.Cancel(); - - LoadComponentAsync(newColumns, c => - { - Child = columns = c; - columns.FadeInFromZero(500, Easing.OutQuint); - - recalculateValues(); - redrawFilled(); - redrawProgress(); - }, (cts = new CancellationTokenSource()).Token); } /// @@ -141,16 +196,16 @@ namespace osu.Game.Screens.Play for (float i = 0; i < ColumnCount; i++) { newValues.Add(0); - } + } } else { - int max = values.Max(); - float step = values.Length / (float)ColumnCount; + int max = values.Max(); + float step = values.Length / (float)ColumnCount; - for (float i = 0; i < values.Length; i += step) - { - newValues.Add((float)values[(int)i] / max); + for (float i = 0; i < values.Length; i += step) + { + newValues.Add((float)values[(int)i] / max); } } @@ -203,10 +258,9 @@ namespace osu.Game.Screens.Play } } - public Column(float height) + public Column() { Width = WIDTH; - Height = height; } [BackgroundDependencyLoader] From 04f7def798e365660a8e6e721c6309ba469f6a98 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:31:12 +0200 Subject: [PATCH 0832/1400] Remove useless comment --- osu.Game/Screens/Play/SquareGraph.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index dd964b8908..7e8a8952cc 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -90,9 +90,6 @@ namespace osu.Game.Screens.Play }; } - - // private Vector2 parentScale; - protected override void Update() { base.Update(); From d39d552660d79ea2652c15e9201f2d65034e6d10 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:35:48 +0200 Subject: [PATCH 0833/1400] Update test --- .../Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs index 66671a506f..4e57a255be 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs @@ -63,10 +63,12 @@ namespace osu.Game.Tests.Visual.Gameplay { public int CreationCount { get; private set; } - protected override void RecreateGraph() + protected override void UpdateGraph() { - base.RecreateGraph(); - CreationCount++; + base.UpdateGraph(); + + if (base.ColumnCount > 0) + CreationCount++; } } } From 8cc0c5ad1ca7b27c13651a48f5ab5ebe9c673cc5 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:39:01 +0200 Subject: [PATCH 0834/1400] Fix code style --- osu.Game/Screens/Play/SquareGraph.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 7e8a8952cc..5ea17a7518 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using osu.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -15,7 +14,6 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; -using osu.Framework.Threading; using osu.Framework.Layout; namespace osu.Game.Screens.Play @@ -59,7 +57,7 @@ namespace osu.Game.Screens.Play } } - bool haveValuesChanged; + private bool haveValuesChanged; private Color4 fillColour; @@ -93,7 +91,7 @@ namespace osu.Game.Screens.Play protected override void Update() { base.Update(); - + if (!layout.IsValid) { UpdateGraph(); From 80b6e014f16747173aa4240aebb709fda1187b82 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 01:47:44 +0200 Subject: [PATCH 0835/1400] More code style --- .../Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs | 2 +- osu.Game/Screens/Play/SquareGraph.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs index 4e57a255be..8d0c26996c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs @@ -67,7 +67,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.UpdateGraph(); - if (base.ColumnCount > 0) + if (ColumnCount > 0) CreationCount++; } } diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 5ea17a7518..27c6cae2fc 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -140,9 +140,10 @@ namespace osu.Game.Screens.Play // add missing columns float x = ColumnCount * Column.WIDTH; + while (targetColumnCount > ColumnCount) { - var column = new Column() + var column = new Column { Height = DrawHeight, LitColour = fillColour, From e5884016ab7ad72fda9be0878afec14bb8363b29 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 May 2023 19:07:25 -0700 Subject: [PATCH 0836/1400] Initial commit for the snap colour mod. Implements basic functionality. --- .../Mods/OsuModSnapColour.cs | 42 +++++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + osu.Game/Rulesets/Mods/ModSnapColour.cs | 19 +++++++++ 3 files changed, 62 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs create mode 100644 osu.Game/Rulesets/Mods/ModSnapColour.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs new file mode 100644 index 0000000000..87a2598695 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +#nullable disable + +using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Screens.Edit; + +namespace osu.Game.Rulesets.Osu.Mods +{ + /// + /// Mod that colours s based on the musical division they are on + /// + public class OsuModSnapColour : ModSnapColour, IApplicableToBeatmap, IApplicableToDrawableHitObject + { + [Resolved] + private OsuColour colours { get; set; } = new OsuColour(); + + [Resolved(canBeNull: true)] + private IBeatmap currentBeatmap { get; set; } + + public void ApplyToBeatmap(IBeatmap beatmap) + { + //Store a reference to the current beatmap to look up the beat divisor when notes are drawn + if (this.currentBeatmap != beatmap) + this.currentBeatmap = beatmap; + } + + public void ApplyToDrawableHitObject(DrawableHitObject drawable) + { + if (currentBeatmap.IsNull() || drawable.IsNull()) return; + + drawable.OnUpdate += _ => + drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor(currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), colours); + } + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 922594a93a..23eea0e488 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -176,6 +176,7 @@ namespace osu.Game.Rulesets.Osu new OsuModClassic(), new OsuModRandom(), new OsuModMirror(), + new OsuModSnapColour(), new MultiMod(new OsuModAlternate(), new OsuModSingleTap()) }; diff --git a/osu.Game/Rulesets/Mods/ModSnapColour.cs b/osu.Game/Rulesets/Mods/ModSnapColour.cs new file mode 100644 index 0000000000..6f706f1cb2 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModSnapColour.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// Mod that colours hitobjects based on the musical division they are on + /// + public class ModSnapColour : Mod + { + public override string Name => "Snap Colour"; + public override string Acronym => "SC"; + public override LocalisableString Description => new LocalisableString("Colours hit objects based on the rhythm."); + public override double ScoreMultiplier => 1; + public override ModType Type => ModType.Conversion; + } +} From 24f07633f36e965532c15e2f2ca53699dbc481eb Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 May 2023 19:43:28 -0700 Subject: [PATCH 0837/1400] Formatting fixes --- osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs index 87a2598695..556af7e6b4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs @@ -1,5 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. + #nullable disable using osu.Framework.Allocation; @@ -36,7 +37,9 @@ namespace osu.Game.Rulesets.Osu.Mods if (currentBeatmap.IsNull() || drawable.IsNull()) return; drawable.OnUpdate += _ => - drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor(currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), colours); + drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor( + currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), + colours); } } } From 7a907f72070fd7248ca192c8918ed589da2bf2e6 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 12 May 2023 22:13:39 -0700 Subject: [PATCH 0838/1400] Code quality improvements (thanks to ItsShamed): Removed #nullable disable, fixed incorrect LocalisableString, removed incorrect dependency injection for OsuColour, fixed nullable dependency for IBeatmap Removed unnecessary usage of "this." caught by the CI code quality check --- osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs | 13 +++++-------- osu.Game/Rulesets/Mods/ModSnapColour.cs | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs index 556af7e6b4..69b8b1d4c3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; @@ -19,17 +17,16 @@ namespace osu.Game.Rulesets.Osu.Mods /// public class OsuModSnapColour : ModSnapColour, IApplicableToBeatmap, IApplicableToDrawableHitObject { - [Resolved] - private OsuColour colours { get; set; } = new OsuColour(); + private readonly OsuColour colours = new OsuColour(); - [Resolved(canBeNull: true)] - private IBeatmap currentBeatmap { get; set; } + [Resolved] + private IBeatmap? currentBeatmap { get; set; } public void ApplyToBeatmap(IBeatmap beatmap) { //Store a reference to the current beatmap to look up the beat divisor when notes are drawn - if (this.currentBeatmap != beatmap) - this.currentBeatmap = beatmap; + if (currentBeatmap != beatmap) + currentBeatmap = beatmap; } public void ApplyToDrawableHitObject(DrawableHitObject drawable) diff --git a/osu.Game/Rulesets/Mods/ModSnapColour.cs b/osu.Game/Rulesets/Mods/ModSnapColour.cs index 6f706f1cb2..d7e51d8cf6 100644 --- a/osu.Game/Rulesets/Mods/ModSnapColour.cs +++ b/osu.Game/Rulesets/Mods/ModSnapColour.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => "Snap Colour"; public override string Acronym => "SC"; - public override LocalisableString Description => new LocalisableString("Colours hit objects based on the rhythm."); + public override LocalisableString Description => "Colours hit objects based on the rhythm."; public override double ScoreMultiplier => 1; public override ModType Type => ModType.Conversion; } From 2cfc4eb515d50dcdd387020764bcad744c9bb9f5 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 10:12:46 +0200 Subject: [PATCH 0839/1400] Fix unconsidered height change --- osu.Game/Screens/Play/SquareGraph.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 27c6cae2fc..d5d2f1d3c2 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -110,6 +110,7 @@ namespace osu.Game.Screens.Play // early exit the most frequent case if (!haveValuesChanged && targetColumnCount == ColumnCount) { + updateColumnHeight(); columns.ForceRedraw(); return; } @@ -124,6 +125,14 @@ namespace osu.Game.Screens.Play haveValuesChanged = false; } + private void updateColumnHeight() + { + foreach (var column in columns) + { + column.Height = DrawHeight; + } + } + private void ensureColumnCount(int targetColumnCount) { // remove excess columns @@ -132,11 +141,7 @@ namespace osu.Game.Screens.Play columns.Remove(columns.Children[ColumnCount - 1], true); } - // update height of existing columns - foreach (var column in columns) - { - column.Height = DrawHeight; - } + updateColumnHeight(); // add missing columns float x = ColumnCount * Column.WIDTH; From 4b544903cb7bcd768aab655e34f40da0285785b6 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 10:13:09 +0200 Subject: [PATCH 0840/1400] Optimize recalculateValues --- osu.Game/Screens/Play/SquareGraph.cs | 33 +++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index d5d2f1d3c2..061d1f7103 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -190,27 +190,24 @@ namespace osu.Game.Screens.Play /// private void recalculateValues() { - var newValues = new List(); - - if (values == null) + int columnCount = ColumnCount; + if (values == null || values.Length == 0 || columnCount == 0) { - for (float i = 0; i < ColumnCount; i++) - { - newValues.Add(0); - } - } - else - { - int max = values.Max(); - float step = values.Length / (float)ColumnCount; - - for (float i = 0; i < values.Length; i += step) - { - newValues.Add((float)values[(int)i] / max); - } + calculatedValues = new float[0]; + return; } - calculatedValues = newValues.ToArray(); + float ratio = values.Length / (float)columnCount; + + if (calculatedValues.Length != columnCount) + calculatedValues = new float[columnCount]; + + float max = (float)values.Max(); + + for (int i = 0; i < calculatedValues.Length; i++) + { + calculatedValues[i] = values[(int)(i * ratio)] / max; + } } public partial class Column : Container, IStateful From d81cdacb0d30368cfc1ab092c0465936c5fabe56 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 11:28:05 +0200 Subject: [PATCH 0841/1400] Undo stupid changes --- .../TestSceneDefaultSongProgressGraph.cs | 8 +- osu.Game/Screens/Play/SquareGraph.cs | 126 +++++++----------- 2 files changed, 51 insertions(+), 83 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs index 8d0c26996c..66671a506f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDefaultSongProgressGraph.cs @@ -63,12 +63,10 @@ namespace osu.Game.Tests.Visual.Gameplay { public int CreationCount { get; private set; } - protected override void UpdateGraph() + protected override void RecreateGraph() { - base.UpdateGraph(); - - if (ColumnCount > 0) - CreationCount++; + base.RecreateGraph(); + CreationCount++; } } } diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 061d1f7103..037f2b5b78 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using osu.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -15,6 +16,7 @@ using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Framework.Layout; +using osu.Framework.Threading; namespace osu.Game.Screens.Play { @@ -22,8 +24,6 @@ namespace osu.Game.Screens.Play { private BufferedContainer columns; - private readonly LayoutValue layout = new LayoutValue(Invalidation.DrawSize | Invalidation.DrawInfo); - public int ColumnCount => columns?.Children.Count ?? 0; private int progress; @@ -52,13 +52,10 @@ namespace osu.Game.Screens.Play if (value == values) return; values = value; - haveValuesChanged = true; layout.Invalidate(); } } - private bool haveValuesChanged; - private Color4 fillColour; public Color4 FillColour @@ -73,96 +70,66 @@ namespace osu.Game.Screens.Play } } + private ScheduledDelegate scheduledCreate; + + private LayoutValue layout = new LayoutValue(Invalidation.DrawSize | Invalidation.DrawInfo); + public SquareGraph() { AddLayout(layout); } - [BackgroundDependencyLoader] - private void load() - { - Child = columns = new BufferedContainer(cachedFrameBuffer: true) - { - RedrawOnScale = false, - RelativeSizeAxes = Axes.Both - }; - } - protected override void Update() { base.Update(); if (!layout.IsValid) { - UpdateGraph(); + columns?.FadeOut(500, Easing.OutQuint).Expire(); + + scheduledCreate?.Cancel(); + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + layout.Validate(); } } + private CancellationTokenSource cts; + /// - /// Updates the graph by either adding or removing columns based on DrawWidth. - /// Does nothing if correct number of columns already exists and/or if haven't changed. + /// Recreates the entire graph. /// - protected virtual void UpdateGraph() + protected virtual void RecreateGraph() { - int targetColumnCount = values == null ? 0 : (int)(DrawWidth / Column.WIDTH); - - // early exit the most frequent case - if (!haveValuesChanged && targetColumnCount == ColumnCount) + var newColumns = new BufferedContainer(cachedFrameBuffer: true) { - updateColumnHeight(); - columns.ForceRedraw(); - return; - } + RedrawOnScale = false, + RelativeSizeAxes = Axes.Both, + }; - ensureColumnCount(targetColumnCount); - - // fill graph data - recalculateValues(); - redrawFilled(); - redrawProgress(); - - haveValuesChanged = false; - } - - private void updateColumnHeight() - { - foreach (var column in columns) + for (float x = 0; x < DrawWidth; x += Column.WIDTH) { - column.Height = DrawHeight; - } - } - - private void ensureColumnCount(int targetColumnCount) - { - // remove excess columns - while (targetColumnCount < ColumnCount) - { - columns.Remove(columns.Children[ColumnCount - 1], true); - } - - updateColumnHeight(); - - // add missing columns - float x = ColumnCount * Column.WIDTH; - - while (targetColumnCount > ColumnCount) - { - var column = new Column + newColumns.Add(new Column(DrawHeight) { - Height = DrawHeight, LitColour = fillColour, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Position = new Vector2(x, 0), State = ColumnState.Dimmed, - }; - - LoadComponentAsync(column); - columns.Add(column); - - x += Column.WIDTH; + }); } + + cts?.Cancel(); + + LoadComponentAsync(newColumns, c => + { + Child = columns = c; + columns.FadeInFromZero(500, Easing.OutQuint); + + recalculateValues(); + redrawFilled(); + redrawProgress(); + }, (cts = new CancellationTokenSource()).Token); } /// @@ -190,24 +157,26 @@ namespace osu.Game.Screens.Play /// private void recalculateValues() { - int columnCount = ColumnCount; - if (values == null || values.Length == 0 || columnCount == 0) + var newValues = new List(); + + if (values == null) { - calculatedValues = new float[0]; + for (float i = 0; i < ColumnCount; i++) + newValues.Add(0); + return; } - float ratio = values.Length / (float)columnCount; + int max = values.Max(); - if (calculatedValues.Length != columnCount) - calculatedValues = new float[columnCount]; + float step = values.Length / (float)ColumnCount; - float max = (float)values.Max(); - - for (int i = 0; i < calculatedValues.Length; i++) + for (float i = 0; i < values.Length; i += step) { - calculatedValues[i] = values[(int)(i * ratio)] / max; + newValues.Add((float)values[(int)i] / max); } + + calculatedValues = newValues.ToArray(); } public partial class Column : Container, IStateful @@ -256,9 +225,10 @@ namespace osu.Game.Screens.Play } } - public Column() + public Column(float height) { Width = WIDTH; + Height = height; } [BackgroundDependencyLoader] From 18efdb0e4cb3d75fba4288fc7327a10a38214a82 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sat, 13 May 2023 11:37:56 +0200 Subject: [PATCH 0842/1400] Make `layout` readonly --- osu.Game/Screens/Play/SquareGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 037f2b5b78..b53e86a41b 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.Play private ScheduledDelegate scheduledCreate; - private LayoutValue layout = new LayoutValue(Invalidation.DrawSize | Invalidation.DrawInfo); + private readonly LayoutValue layout = new LayoutValue(Invalidation.DrawSize | Invalidation.DrawInfo); public SquareGraph() { From 2e6fd4b321c6223ad1dccb3df1992c9ced5e4a0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 May 2023 20:54:22 +0900 Subject: [PATCH 0843/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index ff76e17184..c73c643d4b 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4315f44e07..3ea4a57c2c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index c5477f765e..a240dec963 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 8c542c6c51134a7357a631f15a2d5fca0bfc5edc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 May 2023 21:12:21 +0900 Subject: [PATCH 0844/1400] Fix hold-for-right-click showing during gameplay --- osu.Game/Input/OsuUserInputManager.cs | 5 +++++ osu.Game/OsuGame.cs | 7 +++++++ osu.Game/Rulesets/UI/RulesetInputManager.cs | 2 ++ 3 files changed, 14 insertions(+) diff --git a/osu.Game/Input/OsuUserInputManager.cs b/osu.Game/Input/OsuUserInputManager.cs index ab43497156..c205636ab9 100644 --- a/osu.Game/Input/OsuUserInputManager.cs +++ b/osu.Game/Input/OsuUserInputManager.cs @@ -3,6 +3,7 @@ #nullable disable +using osu.Framework.Bindables; using osu.Framework.Input; using osuTK.Input; @@ -10,6 +11,10 @@ namespace osu.Game.Input { public partial class OsuUserInputManager : UserInputManager { + protected override bool AllowRightClickFromLongTouch => !LocalUserPlaying.Value; + + public readonly BindableBool LocalUserPlaying = new BindableBool(); + internal OsuUserInputManager() { } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7c9b03bd5b..fe6e479d19 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -269,6 +269,13 @@ namespace osu.Game if (hideToolbar) Toolbar.Hide(); } + protected override UserInputManager CreateUserInputManager() + { + var userInputManager = base.CreateUserInputManager(); + (userInputManager as OsuUserInputManager)?.LocalUserPlaying.BindTo(LocalUserPlaying); + return userInputManager; + } + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 2ae54a3afe..a24e22f22b 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.UI public abstract partial class RulesetInputManager : PassThroughInputManager, ICanAttachHUDPieces, IHasReplayHandler, IHasRecordingHandler where T : struct { + protected override bool AllowRightClickFromLongTouch => false; + public readonly KeyBindingContainer KeyBindingContainer; [Resolved(CanBeNull = true)] From f1f30b94a694204b84061e9b85e5b9fc2ecdabe4 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sun, 14 May 2023 11:05:47 +0200 Subject: [PATCH 0845/1400] Add StarRating Property --- osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index c45f703b05..ef71e0ee17 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -53,6 +53,9 @@ namespace osu.Game.Online.Rooms [Key(9)] public DateTimeOffset? PlayedAt { get; set; } + [Key(10)] + public double StarRating { get; set; } + public MultiplayerPlaylistItem() { } @@ -69,6 +72,7 @@ namespace osu.Game.Online.Rooms Expired = item.Expired; PlaylistOrder = item.PlaylistOrder ?? 0; PlayedAt = item.PlayedAt; + // TODO: assign StarRating } } } From 9a327d95b883323a21c649519f7cacae30e95832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 14 May 2023 11:24:24 +0200 Subject: [PATCH 0846/1400] Add test coverage --- .../Editing/TestScenePlacementBlueprint.cs | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs new file mode 100644 index 0000000000..58eff9ade7 --- /dev/null +++ b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs @@ -0,0 +1,83 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Input.Bindings; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Compose.Components; +using osu.Game.Tests.Beatmaps; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Editing +{ + public partial class TestScenePlacementBlueprint : EditorTestScene + { + protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false); + + private GlobalActionContainer globalActionContainer => this.ChildrenOfType().Single(); + + [Test] + public void TestCommitPlacementViaGlobalAction() + { + Playfield playfield = null!; + + AddStep("select slider placement tool", () => InputManager.Key(Key.Number3)); + AddStep("move mouse to top left of playfield", () => + { + playfield = this.ChildrenOfType().Single(); + var location = (3 * playfield.ScreenSpaceDrawQuad.TopLeft + playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + AddStep("begin placement", () => InputManager.Click(MouseButton.Left)); + AddStep("move mouse to bottom right of playfield", () => + { + var location = (playfield.ScreenSpaceDrawQuad.TopLeft + 3 * playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + AddStep("confirm via global action", () => + { + globalActionContainer.TriggerPressed(GlobalAction.Select); + globalActionContainer.TriggerReleased(GlobalAction.Select); + }); + AddAssert("slider placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(1)); + } + + [Test] + public void TestAbortPlacementViaGlobalAction() + { + Playfield playfield = null!; + + AddStep("select slider placement tool", () => InputManager.Key(Key.Number3)); + AddStep("move mouse to top left of playfield", () => + { + playfield = this.ChildrenOfType().Single(); + var location = (3 * playfield.ScreenSpaceDrawQuad.TopLeft + playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + AddStep("begin placement", () => InputManager.Click(MouseButton.Left)); + AddStep("move mouse to bottom right of playfield", () => + { + var location = (playfield.ScreenSpaceDrawQuad.TopLeft + 3 * playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + AddStep("abort via global action", () => + { + globalActionContainer.TriggerPressed(GlobalAction.Back); + globalActionContainer.TriggerReleased(GlobalAction.Back); + }); + AddAssert("editor is still current", () => Editor.IsCurrentScreen()); + AddAssert("slider not placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(0)); + AddAssert("no active placement", () => this.ChildrenOfType().Single().CurrentPlacement.PlacementActive, + () => Is.EqualTo(PlacementBlueprint.PlacementState.Waiting)); + } + } +} From 5d687013214366aa6ff7fe09e998dea7f91cd79e Mon Sep 17 00:00:00 2001 From: timiimit Date: Sun, 14 May 2023 12:08:37 +0200 Subject: [PATCH 0847/1400] Copy StarRange when creating PlaylistItem --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 2 +- osu.Game/Online/Rooms/PlaylistItem.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 2be7327234..5716b7ad3b 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -783,7 +783,7 @@ namespace osu.Game.Online.Multiplayer RoomUpdated?.Invoke(); } - private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item) => new PlaylistItem(new APIBeatmap { OnlineID = item.BeatmapID }) + private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item) => new PlaylistItem(new APIBeatmap { OnlineID = item.BeatmapID, StarRating = item.StarRating }) { ID = item.ID, OwnerID = item.OwnerID, diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 2213311c67..a900d8f3d7 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -91,7 +91,7 @@ namespace osu.Game.Online.Rooms } public PlaylistItem(MultiplayerPlaylistItem item) - : this(new APIBeatmap { OnlineID = item.BeatmapID }) + : this(new APIBeatmap { OnlineID = item.BeatmapID, StarRating = item.StarRating }) { ID = item.ID; OwnerID = item.OwnerID; From fd80ffd52bd4741c82266e78d8e03f405d75b0c7 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sun, 14 May 2023 12:09:15 +0200 Subject: [PATCH 0848/1400] Fix display update condition --- .../Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 93c8faf0b0..2ee3bb30dd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -85,15 +85,15 @@ namespace osu.Game.Screens.OnlinePlay.Components StarDifficulty minDifficulty; StarDifficulty maxDifficulty; - if (DifficultyRange.Value != null) + if (DifficultyRange.Value != null && Playlist.Count == 0) { + // When Playlist is empty (in lounge) we take retrieved range minDifficulty = new StarDifficulty(DifficultyRange.Value.Min, 0); maxDifficulty = new StarDifficulty(DifficultyRange.Value.Max, 0); } else { - // In multiplayer rooms, the beatmaps of playlist items will not be populated to a point this can be correct. - // Either populating them via BeatmapLookupCache or polling the API for the room's DifficultyRange will be required. + // When Playlist is not empty (in room) we compute actual range var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray(); minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0); From 86a834fb568922ae975f014c20d410e71969ce44 Mon Sep 17 00:00:00 2001 From: timiimit Date: Sun, 14 May 2023 12:20:16 +0200 Subject: [PATCH 0849/1400] Fix TODO comment --- osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index ef71e0ee17..64f971a2e4 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -72,7 +72,7 @@ namespace osu.Game.Online.Rooms Expired = item.Expired; PlaylistOrder = item.PlaylistOrder ?? 0; PlayedAt = item.PlayedAt; - // TODO: assign StarRating + StarRating = item.Beatmap.StarRating; // generally not available, but lets at least try to use it } } } From a99bf0fc5a5befc1961e5e6d3eb175879a4973e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 14 May 2023 12:29:24 +0200 Subject: [PATCH 0850/1400] Add test coverage --- .../Editing/TestScenePlacementBlueprint.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs index 58eff9ade7..a5681bea4a 100644 --- a/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestScenePlacementBlueprint.cs @@ -79,5 +79,28 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("no active placement", () => this.ChildrenOfType().Single().CurrentPlacement.PlacementActive, () => Is.EqualTo(PlacementBlueprint.PlacementState.Waiting)); } + + [Test] + public void TestCommitPlacementViaToolChange() + { + Playfield playfield = null!; + + AddStep("select slider placement tool", () => InputManager.Key(Key.Number3)); + AddStep("move mouse to top left of playfield", () => + { + playfield = this.ChildrenOfType().Single(); + var location = (3 * playfield.ScreenSpaceDrawQuad.TopLeft + playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + AddStep("begin placement", () => InputManager.Click(MouseButton.Left)); + AddStep("move mouse to bottom right of playfield", () => + { + var location = (playfield.ScreenSpaceDrawQuad.TopLeft + 3 * playfield.ScreenSpaceDrawQuad.BottomRight) / 4; + InputManager.MoveMouseTo(location); + }); + + AddStep("change tool to circle", () => InputManager.Key(Key.Number2)); + AddAssert("slider placed", () => EditorBeatmap.HitObjects.Count, () => Is.EqualTo(1)); + } } } From 6647d95ea7e80e8430c3daa8cd0bae62c2844c42 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 14 May 2023 18:32:16 +0300 Subject: [PATCH 0851/1400] Kill search focus when clicking on `ModColumn` --- .../UserInterface/TestSceneModSelectOverlay.cs | 18 ++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 3 +++ 2 files changed, 21 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index d1cbe7d91c..ea81f9c96e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -468,6 +468,24 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).IsValid); } + [Test] + public void TestSearchFocusChange() + { + createScreen(); + + AddStep("click on search", navigateAndClick); + AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); + + AddStep("click on mod column", navigateAndClick); + AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); + + void navigateAndClick() where T : Drawable + { + InputManager.MoveMouseTo(modSelectOverlay.ChildrenOfType().FirstOrDefault()); + InputManager.Click(MouseButton.Left); + } + } + [Test] public void TestDeselectAllViaKey() { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index fdc948bcbf..ace5bf71d1 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -777,6 +777,9 @@ namespace osu.Game.Overlays.Mods if (!Active.Value) RequestScroll?.Invoke(this); + //Kill focus on SearchTextBox + Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null)); + return true; } From d503312788f5e39173a0b2c94ba1b4f3af117f22 Mon Sep 17 00:00:00 2001 From: alix Date: Sun, 14 May 2023 13:37:44 -0400 Subject: [PATCH 0852/1400] updates and add changes --- osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs index 6affeb24d8..3224ff9eaf 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRandom.cs @@ -9,7 +9,6 @@ using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Beatmaps; @@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModTargetPractice)).ToArray(); - [SettingSource("Angle sharpness", "How sharp angles should be", SettingControlType = typeof(AngleSharpnessSlider))] + [SettingSource("Angle sharpness", "How sharp angles should be")] public BindableFloat AngleSharpness { get; } = new BindableFloat(7) { MinValue = 1, @@ -162,12 +161,4 @@ namespace osu.Game.Rulesets.Osu.Mods return previousObjectStartedCombo && random.NextDouble() < 0.6f; } } - - public partial class AngleSharpnessSlider : SettingsSlider - { - public AngleSharpnessSlider() - { - KeyboardStep = 0.5f; - } - } } From cb8d5f459f40e4c0bd4f4da51867deb546d0c908 Mon Sep 17 00:00:00 2001 From: timiimit Date: Mon, 15 May 2023 07:34:27 +0200 Subject: [PATCH 0853/1400] Remove bad comment --- osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index 64f971a2e4..a102d118fe 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -72,7 +72,7 @@ namespace osu.Game.Online.Rooms Expired = item.Expired; PlaylistOrder = item.PlaylistOrder ?? 0; PlayedAt = item.PlayedAt; - StarRating = item.Beatmap.StarRating; // generally not available, but lets at least try to use it + StarRating = item.Beatmap.StarRating; } } } From 83ceb3457f8cc800d320ceb1406a04f7f9e3ae55 Mon Sep 17 00:00:00 2001 From: timiimit Date: Mon, 15 May 2023 07:35:09 +0200 Subject: [PATCH 0854/1400] Add xmldoc comment --- osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index a102d118fe..daf45c5aee 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -60,6 +60,9 @@ namespace osu.Game.Online.Rooms { } + /// + /// This constructor should only be used for test purposes. + /// public MultiplayerPlaylistItem(PlaylistItem item) { ID = item.ID; From 26ed50d8fdf13996c749bb05eeb3e1d18239fd6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 May 2023 21:42:48 +0900 Subject: [PATCH 0855/1400] Add abbreviations found in framework functions Brings total inspections down to zero when using local framework checkout (in conjuncation with https://github.com/ppy/osu-framework/pull/5793). --- osu.sln.DotSettings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index d7486273fb..b54794cd6d 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -329,6 +329,7 @@ False AABB API + ARGB BPM EF FPS @@ -336,6 +337,7 @@ GL GLSL HID + HSL HSPA HSV HTML @@ -352,6 +354,7 @@ OS PM RGB + RGBA RNG SDL SHA From 10d6f9ea5a9e64eaa92aae278b6f8466485081a5 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 09:52:26 +0200 Subject: [PATCH 0856/1400] Create common online play pill --- .../Lounge/Components/OnlinePlayPill.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs new file mode 100644 index 0000000000..45a0fd2a1b --- /dev/null +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.OnlinePlay.Lounge.Components +{ + public partial class OnlinePlayPill : OnlinePlayComposite + { + protected PillContainer pill; + protected OsuTextFlowContainer textFlow; + + public OnlinePlayPill() + { + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load() + { + InternalChild = pill = new PillContainer + { + Child = textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + } + }; + } + } +} From 04893064f06a673e60ce7e61bb23fb07571b41b7 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 09:53:11 +0200 Subject: [PATCH 0857/1400] Make used pills inherit from a common one --- .../Lounge/Components/MatchTypePill.cs | 23 +---------- .../Lounge/Components/PlaylistCountPill.cs | 33 +++------------ .../Lounge/Components/QueueModePill.cs | 27 +------------ .../Components/RoomSpecialCategoryPill.cs | 40 +++---------------- .../Lounge/Components/RoomStatusPill.cs | 32 ++------------- 5 files changed, 17 insertions(+), 138 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index f96d547747..dd5f52155c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -13,29 +13,8 @@ using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public partial class MatchTypePill : OnlinePlayComposite + public partial class MatchTypePill : OnlinePlayPill { - private OsuTextFlowContainer textFlow; - - public MatchTypePill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new PillContainer - { - Child = textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - } - }; - } - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 81ba48d135..c3118ab285 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -5,40 +5,17 @@ using System.Linq; using Humanizer; -using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { /// /// A pill that displays the playlist item count. /// - public partial class PlaylistCountPill : OnlinePlayComposite + public partial class PlaylistCountPill : OnlinePlayPill { - private OsuTextFlowContainer count; - - public PlaylistCountPill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new PillContainer - { - Child = count = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -55,10 +32,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components ? Playlist.Count(i => !i.Expired) : PlaylistItemStats.Value.CountActive; - count.Clear(); - count.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); - count.AddText(" "); - count.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None)); + textFlow.Clear(); + textFlow.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + textFlow.AddText(" "); + textFlow.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None)); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index 0175418a96..d37dede961 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -3,39 +3,14 @@ #nullable disable -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public partial class QueueModePill : OnlinePlayComposite + public partial class QueueModePill : OnlinePlayPill { - private OsuTextFlowContainer textFlow; - - public QueueModePill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = new PillContainer - { - Child = textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - } - }; - } - protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index 5d67a18d1f..a01d14ab40 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -5,54 +5,26 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public partial class RoomSpecialCategoryPill : OnlinePlayComposite + public partial class RoomSpecialCategoryPill : OnlinePlayPill { - private SpriteText text; - private PillContainer pill; - [Resolved] private OsuColour colours { get; set; } - public RoomSpecialCategoryPill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = pill = new PillContainer - { - Background = - { - Colour = colours.Pink, - Alpha = 1 - }, - Child = text = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), - Colour = Color4.Black - } - }; - } - protected override void LoadComplete() { base.LoadComplete(); + pill.Background.Colour = colours.Pink; + pill.Background.Alpha = 1; + Category.BindValueChanged(c => { - text.Text = c.NewValue.GetLocalisableDescription(); + textFlow.Clear(); + textFlow.AddText(c.NewValue.GetLocalisableDescription()); var backgroundColour = colours.ForRoomCategory(Category.Value); if (backgroundColour != null) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index 201314851e..a4fdd39236 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -6,46 +6,20 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { /// /// A pill that displays the room's current status. /// - public partial class RoomStatusPill : OnlinePlayComposite + public partial class RoomStatusPill : OnlinePlayPill { [Resolved] private OsuColour colours { get; set; } - private PillContainer pill; - private SpriteText statusText; - - public RoomStatusPill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader] - private void load() - { - InternalChild = pill = new PillContainer - { - Child = statusText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 12), - Colour = Color4.Black - } - }; - } - protected override void LoadComplete() { base.LoadComplete(); @@ -62,7 +36,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components pill.Background.Alpha = 1; pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); - statusText.Text = status.Message; + + textFlow.Clear(); + textFlow.AddText(status.Message); } private RoomStatus getDisplayStatus() From 40daa41a5272c78746f8c743ac0f72d0d0e917e4 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 10:06:48 +0200 Subject: [PATCH 0858/1400] Fix naming & namespaces --- .../OnlinePlay/Lounge/Components/MatchTypePill.cs | 8 ++------ .../OnlinePlay/Lounge/Components/OnlinePlayPill.cs | 8 ++++---- .../OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 8 ++++---- .../OnlinePlay/Lounge/Components/QueueModePill.cs | 4 ++-- .../Lounge/Components/RoomSpecialCategoryPill.cs | 10 +++++----- .../OnlinePlay/Lounge/Components/RoomStatusPill.cs | 8 ++++---- 6 files changed, 21 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index dd5f52155c..e019de0f6f 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -3,12 +3,8 @@ #nullable disable -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; -using osu.Framework.Graphics; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Lounge.Components @@ -24,8 +20,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void onMatchTypeChanged(ValueChangedEvent type) { - textFlow.Clear(); - textFlow.AddText(type.NewValue.GetLocalisableDescription()); + TextFlow.Clear(); + TextFlow.AddText(type.NewValue.GetLocalisableDescription()); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs index 45a0fd2a1b..80e82c3856 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs @@ -12,8 +12,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public partial class OnlinePlayPill : OnlinePlayComposite { - protected PillContainer pill; - protected OsuTextFlowContainer textFlow; + protected PillContainer Pill; + protected OsuTextFlowContainer TextFlow; public OnlinePlayPill() { @@ -23,9 +23,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [BackgroundDependencyLoader] private void load() { - InternalChild = pill = new PillContainer + InternalChild = Pill = new PillContainer { - Child = textFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + Child = TextFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) { AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index c3118ab285..6687f30bc0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -32,10 +32,10 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components ? Playlist.Count(i => !i.Expired) : PlaylistItemStats.Value.CountActive; - textFlow.Clear(); - textFlow.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); - textFlow.AddText(" "); - textFlow.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None)); + TextFlow.Clear(); + TextFlow.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + TextFlow.AddText(" "); + TextFlow.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None)); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index d37dede961..e402653c2f 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -20,8 +20,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void onQueueModeChanged(ValueChangedEvent mode) { - textFlow.Clear(); - textFlow.AddText(mode.NewValue.GetLocalisableDescription()); + TextFlow.Clear(); + TextFlow.AddText(mode.NewValue.GetLocalisableDescription()); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index a01d14ab40..d266104cf5 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -18,17 +18,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - pill.Background.Colour = colours.Pink; - pill.Background.Alpha = 1; + Pill.Background.Colour = colours.Pink; + Pill.Background.Alpha = 1; Category.BindValueChanged(c => { - textFlow.Clear(); - textFlow.AddText(c.NewValue.GetLocalisableDescription()); + TextFlow.Clear(); + TextFlow.AddText(c.NewValue.GetLocalisableDescription()); var backgroundColour = colours.ForRoomCategory(Category.Value); if (backgroundColour != null) - pill.Background.Colour = backgroundColour.Value; + Pill.Background.Colour = backgroundColour.Value; }, true); } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index a4fdd39236..fa5eba4b69 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -34,11 +34,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RoomStatus status = getDisplayStatus(); - pill.Background.Alpha = 1; - pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); + Pill.Background.Alpha = 1; + Pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); - textFlow.Clear(); - textFlow.AddText(status.Message); + TextFlow.Clear(); + TextFlow.AddText(status.Message); } private RoomStatus getDisplayStatus() From a9991d9dd4bce7145fde56a8c4cae6c266313ae9 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 10:14:14 +0200 Subject: [PATCH 0859/1400] Remove another unused namespace --- .../Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 6687f30bc0..d1365c02f3 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -6,7 +6,6 @@ using System.Linq; using Humanizer; using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Graphics; using osu.Game.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components From 81b7737660260a2a5b3168afaf1c171278c1f5e9 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 10:20:16 +0200 Subject: [PATCH 0860/1400] Fix text colour of RoomSpecialCategoryPill --- .../OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index d266104cf5..b869ede9bd 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Game.Graphics; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { @@ -20,6 +21,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Pill.Background.Colour = colours.Pink; Pill.Background.Alpha = 1; + TextFlow.Colour = Color4.Black; Category.BindValueChanged(c => { From 4ef74eb3f960257d2693b23a33b6358d91a7f954 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 10:22:52 +0200 Subject: [PATCH 0861/1400] Fix `RoomStatusPill` text colour --- .../Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index fa5eba4b69..4206aaf167 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; +using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { @@ -28,6 +29,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Status.BindValueChanged(_ => updateDisplay(), true); FinishTransforms(true); + + TextFlow.Colour = Colour4.Black; } private void updateDisplay() From cc6e4df93e3e1ec8ea06f14e434c1e4e0194b8d0 Mon Sep 17 00:00:00 2001 From: timiimit Date: Tue, 16 May 2023 10:27:46 +0200 Subject: [PATCH 0862/1400] Remove wrongly added back namepspace --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index 4206aaf167..f260d168a7 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { From 83dcd788262fb3cc51f94ddaa56f3fb1e202ef17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 May 2023 16:29:24 +0900 Subject: [PATCH 0863/1400] Make `HitSampleInfo.Bank` non-nullable --- .../Drawables/DrawablePippidonHitObject.cs | 3 +-- .../Drawables/DrawablePippidonHitObject.cs | 3 +-- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneSpinner.cs | 2 +- ...estSceneHitObjectSamplePointAdjustments.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 7 ++++--- .../ControlPoints/SampleControlPoint.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 14 ++++++++----- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 20 ++++++++++++++----- 10 files changed, 35 insertions(+), 22 deletions(-) diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 29203f0a20..c5ada4288d 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Audio; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osuTK; @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables public override IEnumerable GetSamples() => new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }; protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs index 554d03c79f..d198fa81cb 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Audio; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Pippidon.UI; using osu.Game.Rulesets.Scoring; @@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables public override IEnumerable GetSamples() => new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }; protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 40dc7d2403..9a78df23cf 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 100) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: 100) }) }); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 74d0fb42a3..8cfd674f88 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.Tests EndTime = Time.Current + delay + length, Samples = new List { - new HitSampleInfo("hitnormal") + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } }; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs index 7a0418cfec..230333ec35 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Editing Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2, Samples = new List { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "normal", volume: 80) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: 80) } }); diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index efa5562cb8..665ae3e1a7 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Utils; namespace osu.Game.Audio @@ -32,7 +33,7 @@ namespace osu.Game.Audio /// /// The bank to load the sample from. /// - public readonly string? Bank; + public readonly string Bank; /// /// An optional suffix to provide priority lookup. Falls back to non-suffixed . @@ -44,7 +45,7 @@ namespace osu.Game.Audio /// public int Volume { get; } - public HitSampleInfo(string name, string? bank = null, string? suffix = null, int volume = 0) + public HitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 0) { Name = name; Bank = bank; @@ -76,7 +77,7 @@ namespace osu.Game.Audio /// An optional new volume. /// The new . public virtual HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) - => new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume)); + => new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank) ?? Bank, newSuffix.GetOr(Suffix), newVolume.GetOr(Volume)); public bool Equals(HitSampleInfo? other) => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 6cd4d74a31..522a8b7892 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -69,7 +69,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// The . This will not be modified. /// The modified . This does not share a reference with . public virtual HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) - => hitSampleInfo.With(newBank: hitSampleInfo.Bank ?? SampleBank, newVolume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); + => hitSampleInfo.With(newBank: hitSampleInfo.Bank, newVolume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume); public override bool IsRedundant(ControlPoint? existing) => existing is SampleControlPoint existingSample diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 704756e3dd..23440b8a1d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -226,12 +226,16 @@ namespace osu.Game.Beatmaps.Formats public override HitSampleInfo ApplyTo(HitSampleInfo hitSampleInfo) { - var baseInfo = base.ApplyTo(hitSampleInfo); + if (hitSampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy) + { + return legacy.With( + newCustomSampleBank: legacy.CustomSampleBank > 0 ? legacy.CustomSampleBank : CustomSampleBank, + newVolume: hitSampleInfo.Volume > 0 ? hitSampleInfo.Volume : SampleVolume, + newBank: legacy.BankSpecified ? legacy.Bank : SampleBank + ); + } - if (baseInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacy && legacy.CustomSampleBank == 0) - return legacy.With(newCustomSampleBank: CustomSampleBank); - - return baseInfo; + return base.ApplyTo(hitSampleInfo); } public override bool IsRedundant(ControlPoint? existing) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 12c0ea1807..eae9f922a4 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Edit HitObject = hitObject; // adding the default hit sample should be the case regardless of the ruleset. - HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK, volume: 100)); + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: 100)); RelativeSizeAxes = Axes.Both; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index ba5de6c14b..c0f02b0b5e 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -14,6 +14,7 @@ using System.Linq; using JetBrains.Annotations; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Utils; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Legacy; using osu.Game.Skinning; using osu.Game.Utils; @@ -446,9 +447,9 @@ namespace osu.Game.Rulesets.Objects.Legacy if (string.IsNullOrEmpty(bankInfo.Filename)) { soundTypes.Add(new LegacyHitSampleInfo(HitSampleInfo.HIT_NORMAL, bankInfo.BankForNormal, bankInfo.Volume, bankInfo.CustomSampleBank, - // if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample. - // None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds - type != LegacyHitSoundType.None && !type.HasFlagFast(LegacyHitSoundType.Normal))); + // if the sound type doesn't have the Normal flag set, attach it anyway as a layered sample. + // None also counts as a normal non-layered sample: https://osu.ppy.sh/help/wiki/osu!_File_Formats/Osu_(file_format)#hitsounds + type != LegacyHitSoundType.None && !type.HasFlagFast(LegacyHitSoundType.Normal))); } else { @@ -479,12 +480,14 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The bank identifier to use for the base ("hitnormal") sample. /// Transferred to when appropriate. /// + [CanBeNull] public string BankForNormal; /// /// The bank identifier to use for additions ("hitwhistle", "hitfinish", "hitclap"). /// Transferred to when appropriate. /// + [CanBeNull] public string BankForAdditions; /// @@ -518,10 +521,17 @@ namespace osu.Game.Rulesets.Objects.Legacy /// public readonly bool IsLayered; + /// + /// Whether a bank was specified locally to the relevant hitobject. + /// If false, a bank will be retrieved from the closest control point. + /// + public bool BankSpecified; + public LegacyHitSampleInfo(string name, string? bank = null, int volume = 0, int customSampleBank = 0, bool isLayered = false) - : base(name, bank, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume) + : base(name, bank ?? SampleControlPoint.DEFAULT_BANK, customSampleBank >= 2 ? customSampleBank.ToString() : null, volume) { CustomSampleBank = customSampleBank; + BankSpecified = !string.IsNullOrEmpty(bank); IsLayered = isLayered; } @@ -531,7 +541,7 @@ namespace osu.Game.Rulesets.Objects.Legacy public virtual LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, Optional newCustomSampleBank = default, Optional newIsLayered = default) - => new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered)); + => new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank) ?? Bank, newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered)); public bool Equals(LegacyHitSampleInfo? other) // The additions to equality checks here are *required* to ensure that pooling works correctly. From d9ae8229669b0f371810b5334ea563056642a735 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 May 2023 16:34:49 +0900 Subject: [PATCH 0864/1400] Fix bank not correctly being assigned when adding sample additions in editor --- osu.Game/Rulesets/Objects/HitObject.cs | 2 +- .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 2 +- .../Screens/Edit/Compose/Components/EditorSelectionHandler.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index a4cb976d50..f5b9e9c8cd 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.Objects /// /// The name of the sample. /// A populated . - protected HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) + public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) { var hitnormalSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL); return hitnormalSample == null ? new HitSampleInfo(sampleName) : hitnormalSample.With(newName: sampleName); diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 07fb450628..73e3baf509 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Edit.Compose.Components case TernaryState.True: if (existingSample == null) - samples.Add(new HitSampleInfo(sampleName)); + samples.Add(CurrentPlacement.HitObject.GetSampleInfo(sampleName)); break; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 357cc940f2..694b24c567 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (h.Samples.Any(s => s.Name == sampleName)) return; - h.Samples.Add(new HitSampleInfo(sampleName)); + h.Samples.Add(h.GetSampleInfo(sampleName)); EditorBeatmap.Update(h); }); } From 31fff72eb6f8da11fb5f6d11d06775a1cd78f2ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 May 2023 16:35:58 +0900 Subject: [PATCH 0865/1400] Fix bank not correctly being assigned to some taiko hit cases --- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 787079bfee..d90c7016e9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Objects if (isRimType != rimSamples.Any()) { if (isRimType) - Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_CLAP)); + Samples.Add(GetSampleInfo(HitSampleInfo.HIT_CLAP)); else { foreach (var sample in rimSamples) From 8528fcaedc93bddd843be6fa6087cde82629f52e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 May 2023 18:31:10 +0900 Subject: [PATCH 0866/1400] Rename editor sample adjustment test scene to increase scope of tests --- ...intAdjustments.cs => TestSceneHitObjectSampleAdjustments.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Tests/Visual/Editing/{TestSceneHitObjectSamplePointAdjustments.cs => TestSceneHitObjectSampleAdjustments.cs} (99%) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs similarity index 99% rename from osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs rename to osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index 230333ec35..6e3f403c19 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSamplePointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -24,7 +24,7 @@ using osuTK.Input; namespace osu.Game.Tests.Visual.Editing { - public partial class TestSceneHitObjectSamplePointAdjustments : EditorTestScene + public partial class TestSceneHitObjectSampleAdjustments : EditorTestScene { protected override Ruleset CreateEditorRuleset() => new OsuRuleset(); From ebce39cd1c4ef3db38d6dbb92682252eb7c463ca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 May 2023 18:52:35 +0900 Subject: [PATCH 0867/1400] Add test coverage of failing sample bank transfer --- .../TestSceneHitObjectSampleAdjustments.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index 6e3f403c19..530bd5eb20 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -58,6 +58,26 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestAddSampleAddition() + { + AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + + AddStep("add clap addition", () => InputManager.Key(Key.R)); + + hitObjectHasSampleBank(0, "normal"); + hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP); + hitObjectHasSampleBank(1, "soft"); + hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP); + + AddStep("remove clap addition", () => InputManager.Key(Key.R)); + + hitObjectHasSampleBank(0, "normal"); + hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL); + hitObjectHasSampleBank(1, "soft"); + hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL); + } + [Test] public void TestPopoverHasFocus() { @@ -271,6 +291,12 @@ namespace osu.Game.Tests.Visual.Editing InputManager.Key(Key.Enter); }); + private void hitObjectHasSamples(int objectIndex, params string[] samples) => AddAssert($"{objectIndex.ToOrdinalWords()} has samples {string.Join(',', samples)}", () => + { + var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); + return h.Samples.Select(s => s.Name).SequenceEqual(samples); + }); + private void hitObjectHasSampleBank(int objectIndex, string bank) => AddAssert($"{objectIndex.ToOrdinalWords()} has bank {bank}", () => { var h = EditorBeatmap.HitObjects.ElementAt(objectIndex); From ddfdd712bd61b32c1f00614a840156b234c2e070 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 May 2023 00:07:06 +0800 Subject: [PATCH 0868/1400] Update InspectCode to 2022.3.3 and enable C# 11 --- .config/dotnet-tools.json | 2 +- Directory.Build.props | 2 +- osu.Game/osu.Game.csproj | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1f937e1837..d9f1e3985a 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2022.2.3", + "version": "2022.3.3", "commands": [ "jb" ] diff --git a/Directory.Build.props b/Directory.Build.props index 734374c840..fccac79a45 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  - 10.0 + 11.0 true enable diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3ea4a57c2c..bf0c1dde17 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,9 +1,8 @@ - + net6.0 Library true - 10 osu! From 84de463e2e9e11130fb8edd053796e1f722f15f6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 17 May 2023 00:13:08 +0800 Subject: [PATCH 0869/1400] Turn off inspection of MSBuild unknown property --- osu.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index b54794cd6d..5039831f76 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -234,6 +234,7 @@ WARNING WARNING HINT + DO_NOT_SHOW WARNING HINT HINT From 88ce627c8ed5428b087e5c25c16a541cd1e66b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 16 May 2023 20:40:12 +0200 Subject: [PATCH 0870/1400] Avoid bindable/event feedback when changing resolution --- .../Sections/Graphics/LayoutSettings.cs | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 2e26d15105..d82b8b1ba3 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -244,7 +244,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Scheduler.AddOnce(d => { - displayDropdown.Items = d; + if (!displayDropdown.Items.SequenceEqual(d, DisplayListComparer.DEFAULT)) + displayDropdown.Items = d; updateDisplaySettingsVisibility(); }, displays); } @@ -376,5 +377,43 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } } + + /// + /// Contrary to , this comparer disregards the value of . + /// We want to just show a list of displays, and for the purposes of settings we don't care about their bounds when it comes to the list. + /// However, fires even if only the resolution of the current display was changed + /// (because it causes the bounds of all displays to also change). + /// We're not interested in those changes, so compare only the rest that we actually care about. + /// This helps to avoid a bindable/event feedback loop, in which a resolution change + /// would trigger a display "change", which would in turn reset resolution again. + /// + private class DisplayListComparer : IEqualityComparer + { + public static readonly DisplayListComparer DEFAULT = new DisplayListComparer(); + + public bool Equals(Display? x, Display? y) + { + if (ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, null)) return false; + if (ReferenceEquals(y, null)) return false; + + return x.Index == y.Index + && x.Name == y.Name + && x.DisplayModes.SequenceEqual(y.DisplayModes); + } + + public int GetHashCode(Display obj) + { + var hashCode = new HashCode(); + + hashCode.Add(obj.Index); + hashCode.Add(obj.Name); + hashCode.Add(obj.DisplayModes.Length); + foreach (var displayMode in obj.DisplayModes) + hashCode.Add(displayMode); + + return hashCode.ToHashCode(); + } + } } } From 0dcf1b540e0ee5a652e09982eeffd5174733891d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 16 May 2023 21:14:09 +0200 Subject: [PATCH 0871/1400] Attempt to preserve old resolution when switching displays --- .../Settings/Sections/Graphics/LayoutSettings.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index d82b8b1ba3..6a4ad63799 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -193,6 +193,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics currentDisplay.BindValueChanged(display => Schedule(() => { + // there is no easy way to perform an atomic swap on the `resolutions` list, which is bound to the dropdown via `ItemSource`. + // this means, if the old resolution isn't saved, the `RemoveRange()` call below will cause `resolutionDropdown.Current` to reset value, + // therefore making it impossible to select any dropdown value other than "Default". + // to circumvent this locally, store the old value here, so that we can attempt to restore it later. + var oldResolution = resolutionDropdown.Current.Value; + resolutions.RemoveRange(1, resolutions.Count - 1); if (display.NewValue != null) @@ -204,6 +210,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics .Distinct()); } + if (resolutions.Contains(oldResolution)) + resolutionDropdown.Current.Value = oldResolution; + updateDisplaySettingsVisibility(); }), true); From 2d7fe683110c18361d18ec979473e3ccb783e88e Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 16 May 2023 21:57:31 +0200 Subject: [PATCH 0872/1400] Prevent feedback by using atomic `.ReplaceRange()` `display.NewValue` will never be null, checked on SDL + osuTK/Android. On Android it's a 0x0 display, importantly not null. --- .../Settings/Sections/Graphics/LayoutSettings.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 2e26d15105..f3ff2e87ba 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -193,16 +193,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics currentDisplay.BindValueChanged(display => Schedule(() => { - resolutions.RemoveRange(1, resolutions.Count - 1); - - if (display.NewValue != null) - { - resolutions.AddRange(display.NewValue.DisplayModes - .Where(m => m.Size.Width >= 800 && m.Size.Height >= 600) - .OrderByDescending(m => Math.Max(m.Size.Height, m.Size.Width)) - .Select(m => m.Size) - .Distinct()); - } + resolutions.ReplaceRange(1, resolutions.Count - 1, display.NewValue.DisplayModes + .Where(m => m.Size.Width >= 800 && m.Size.Height >= 600) + .OrderByDescending(m => Math.Max(m.Size.Height, m.Size.Width)) + .Select(m => m.Size) + .Distinct()); updateDisplaySettingsVisibility(); }), true); From 70426a504223eb089b1bc1af2bcdeaca6f760d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 16 May 2023 22:42:25 +0200 Subject: [PATCH 0873/1400] Add reference to youtrack issue to suppression --- osu.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 5039831f76..f9aff99267 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -234,6 +234,7 @@ WARNING WARNING HINT + DO_NOT_SHOW WARNING HINT From c97b7a077e274493fec0dfbdd3e5193669c98fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 16 May 2023 23:47:47 +0200 Subject: [PATCH 0874/1400] Use better issue reference --- osu.sln.DotSettings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index f9aff99267..9ca0fad2ab 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -234,7 +234,7 @@ WARNING WARNING HINT - + DO_NOT_SHOW WARNING HINT From e2633ae993ccd0d470a5684b3cf39ea1c850e0dd Mon Sep 17 00:00:00 2001 From: John Date: Tue, 16 May 2023 21:08:56 -0700 Subject: [PATCH 0875/1400] Removed unnecessary [Resolved] attribute (thanks bdach) Moved accent color assignment from OnUpdate to ApplyCustomUpdateState. In order to get this to work, a flag needed to be added to DrawableHitObject.cs to disable combo color updates also being applied. --- osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs | 11 +++++++---- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 ++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs index 69b8b1d4c3..7d36e73cdb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs @@ -33,10 +33,13 @@ namespace osu.Game.Rulesets.Osu.Mods { if (currentBeatmap.IsNull() || drawable.IsNull()) return; - drawable.OnUpdate += _ => - drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor( - currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), - colours); + drawable.ApplyCustomUpdateState += (drawableObject, state) => + { + int snapDivisor = currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawableObject.HitObject.StartTime); + + drawableObject.EnableComboColour = false; + drawableObject.AccentColour.Value = BindableBeatDivisor.GetColourFor(snapDivisor, colours); + }; } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 07c0d1f8a1..cbaa07bebc 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -74,6 +74,11 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool PropagateNonPositionalInputSubTree => HandleUserInput; + /// + /// Whether this object should be coloured using its combo position + /// + public bool EnableComboColour { get; set; } = true; + /// /// Invoked by this or a nested after a has been applied. /// @@ -528,6 +533,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected void UpdateComboColour() { if (!(HitObject is IHasComboInformation combo)) return; + if (!EnableComboColour) return; Color4 colour = combo.GetComboColour(CurrentSkin); From b7dc8d49bad8d28647bfae7f85a017d92b64a501 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 16 May 2023 21:14:55 -0700 Subject: [PATCH 0876/1400] Removed import for Allocation and other unnecessary [Resolved] tag missed in last commit --- osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs index 7d36e73cdb..4fda6130c0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -19,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Mods { private readonly OsuColour colours = new OsuColour(); - [Resolved] private IBeatmap? currentBeatmap { get; set; } public void ApplyToBeatmap(IBeatmap beatmap) From d6fa44240d6009e3b902765f26feac6e648a96f3 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 16 May 2023 21:51:32 -0700 Subject: [PATCH 0877/1400] Fix storyboard video-only check being inverted --- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index aa264fa719..e674e7512c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -69,7 +69,7 @@ namespace osu.Game.Storyboards.Drawables Size = new Vector2(640, 480); - bool onlyHasVideoElements = Storyboard.Layers.SelectMany(l => l.Elements).Any(e => !(e is StoryboardVideo)); + bool onlyHasVideoElements = Storyboard.Layers.SelectMany(l => l.Elements).All(e => e is StoryboardVideo); Width = Height * (storyboard.BeatmapInfo.WidescreenStoryboard || onlyHasVideoElements ? 16 / 9f : 4 / 3f); From a8bc337006918eb5579fb202c6537d0905075b17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:06:02 +0900 Subject: [PATCH 0878/1400] Change default volume when constructing a `HitSampleInfo` to non-zero --- osu.Game/Audio/HitSampleInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 665ae3e1a7..3cf8e84d56 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -45,7 +45,7 @@ namespace osu.Game.Audio /// public int Volume { get; } - public HitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 0) + public HitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 100) { Name = name; Bank = bank; From dc51d5ecf32fb23e3c45048b9aa848116f913f31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:07:48 +0900 Subject: [PATCH 0879/1400] Rename `GetSampleInfo` to better describe what method does Also add full xmldoc --- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 2 +- .../Objects/TaikoStrongableHitObject.cs | 2 +- osu.Game/Rulesets/Objects/HitObject.cs | 14 ++++++++++---- .../Components/ComposeBlueprintContainer.cs | 2 +- .../Compose/Components/EditorSelectionHandler.cs | 2 +- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 5bd4ac86f5..b05c8e5f77 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Objects { StartTime = time, BananaIndex = i, - Samples = new List { new Banana.BananaHitSampleInfo(GetSampleInfo().Volume) } + Samples = new List { new Banana.BananaHitSampleInfo(CreateHitSampleInfo().Volume) } }); time += spacing; diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index df5898fd67..ba0981e781 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Objects AddNested(i < SpinsRequired ? new SpinnerTick { StartTime = startTime, SpinnerDuration = Duration } - : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration, Samples = new[] { GetSampleInfo("spinnerbonus") } }); + : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration, Samples = new[] { CreateHitSampleInfo("spinnerbonus") } }); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index d90c7016e9..303447e672 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Objects if (isRimType != rimSamples.Any()) { if (isRimType) - Samples.Add(GetSampleInfo(HitSampleInfo.HIT_CLAP)); + Samples.Add(CreateHitSampleInfo(HitSampleInfo.HIT_CLAP)); else { foreach (var sample in rimSamples) diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs index 0043f231d2..479ad8369a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.Objects if (IsStrongBindable.Value != strongSamples.Any()) { if (IsStrongBindable.Value) - Samples.Add(GetSampleInfo(HitSampleInfo.HIT_FINISH)); + Samples.Add(CreateHitSampleInfo(HitSampleInfo.HIT_FINISH)); else { foreach (var sample in strongSamples) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index f5b9e9c8cd..ed3d3a6eb2 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -206,14 +206,20 @@ namespace osu.Game.Rulesets.Objects } /// - /// Create a SampleInfo based on the sample settings of the hit normal sample in . + /// Create a based on the sample settings of the first sample in . + /// If no sample is available, sane default settings will be used instead. /// + /// + /// In the case an existing sample exists, all settings apart from the sample name will be inherited. This includes volume, bank and suffix. + /// /// The name of the sample. /// A populated . - public HitSampleInfo GetSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) + public HitSampleInfo CreateHitSampleInfo(string sampleName = HitSampleInfo.HIT_NORMAL) { - var hitnormalSample = Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL); - return hitnormalSample == null ? new HitSampleInfo(sampleName) : hitnormalSample.With(newName: sampleName); + if (Samples.FirstOrDefault(s => s.Name == HitSampleInfo.HIT_NORMAL) is HitSampleInfo existingSample) + return existingSample.With(newName: sampleName); + + return new HitSampleInfo(sampleName); } } diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 73e3baf509..b42118b983 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -185,7 +185,7 @@ namespace osu.Game.Screens.Edit.Compose.Components case TernaryState.True: if (existingSample == null) - samples.Add(CurrentPlacement.HitObject.GetSampleInfo(sampleName)); + samples.Add(CurrentPlacement.HitObject.CreateHitSampleInfo(sampleName)); break; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 694b24c567..3b49b76e7e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -122,7 +122,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (h.Samples.Any(s => s.Name == sampleName)) return; - h.Samples.Add(h.GetSampleInfo(sampleName)); + h.Samples.Add(h.CreateHitSampleInfo(sampleName)); EditorBeatmap.Update(h); }); } From 510ebe1f234ffb9b1e8ca9c018e8ff2bb7839d3c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:11:14 +0900 Subject: [PATCH 0880/1400] Fix weird optional usage in `HitSampleInfo.With` --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game/Audio/HitSampleInfo.cs | 4 ++-- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 4c66c054e1..b80527f379 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Catch.Objects { } - public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) => new BananaHitSampleInfo(newVolume.GetOr(Volume)); public bool Equals(BananaHitSampleInfo? other) diff --git a/osu.Game/Audio/HitSampleInfo.cs b/osu.Game/Audio/HitSampleInfo.cs index 3cf8e84d56..5d1ce27c9f 100644 --- a/osu.Game/Audio/HitSampleInfo.cs +++ b/osu.Game/Audio/HitSampleInfo.cs @@ -76,8 +76,8 @@ namespace osu.Game.Audio /// An optional new lookup suffix. /// An optional new volume. /// The new . - public virtual HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) - => new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank) ?? Bank, newSuffix.GetOr(Suffix), newVolume.GetOr(Volume)); + public virtual HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + => new HitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume)); public bool Equals(HitSampleInfo? other) => other != null && Name == other.Name && Bank == other.Bank && Suffix == other.Suffix; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c0f02b0b5e..d9738ecd0a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -535,13 +535,13 @@ namespace osu.Game.Rulesets.Objects.Legacy IsLayered = isLayered; } - public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) + public sealed override HitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newSuffix = default, Optional newVolume = default) => With(newName, newBank, newVolume); - public virtual LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, + public virtual LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, Optional newCustomSampleBank = default, Optional newIsLayered = default) - => new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank) ?? Bank, newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered)); + => new LegacyHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newVolume.GetOr(Volume), newCustomSampleBank.GetOr(CustomSampleBank), newIsLayered.GetOr(IsLayered)); public bool Equals(LegacyHitSampleInfo? other) // The additions to equality checks here are *required* to ensure that pooling works correctly. @@ -573,7 +573,7 @@ namespace osu.Game.Rulesets.Objects.Legacy Path.ChangeExtension(Filename, null) }; - public sealed override LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, + public sealed override LegacyHitSampleInfo With(Optional newName = default, Optional newBank = default, Optional newVolume = default, Optional newCustomSampleBank = default, Optional newIsLayered = default) => new FileHitSampleInfo(Filename, newVolume.GetOr(Volume)); From dc421bd2af6d093f9cd1f38a7080c3acde6fae35 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:49:47 +0900 Subject: [PATCH 0881/1400] Revert "Merge pull request #23570 from huoyaoyuan/inspect-code-cs11" This reverts commit ab2bd123e7e29c098f29e92b547826f3844809bb, reversing changes made to 267e63320f5bfa1b83d15c85e9eea62106611a36. --- .config/dotnet-tools.json | 2 +- Directory.Build.props | 2 +- osu.Game/osu.Game.csproj | 3 ++- osu.sln.DotSettings | 2 -- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index d9f1e3985a..1f937e1837 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2022.3.3", + "version": "2022.2.3", "commands": [ "jb" ] diff --git a/Directory.Build.props b/Directory.Build.props index fccac79a45..734374c840 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  - 11.0 + 10.0 true enable diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bf0c1dde17..3ea4a57c2c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,8 +1,9 @@ - + net6.0 Library true + 10 osu! diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 9ca0fad2ab..b54794cd6d 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -234,8 +234,6 @@ WARNING WARNING HINT - - DO_NOT_SHOW WARNING HINT HINT From 94b184712d175e075ed805741f730fd610a3e2f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:38:58 +0900 Subject: [PATCH 0882/1400] Fix random button hover state not correctly being reset on right click --- osu.Game/Screens/Select/FooterButtonRandom.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index f413126e87..3a4bad43b3 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -119,14 +119,13 @@ namespace osu.Game.Screens.Select protected override void OnMouseUp(MouseUpEvent e) { + base.OnMouseUp(e); + if (e.Button == MouseButton.Right && IsHovered) { rewindSearch = true; TriggerClick(); - return; } - - base.OnMouseUp(e); } public override bool OnPressed(KeyBindingPressEvent e) From 764f0323f4727d412e77316a35c4d7f470158263 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 14:42:07 +0900 Subject: [PATCH 0883/1400] Show "rewind" text on random button when beginning a right mouse press --- osu.Game/Screens/Select/FooterButtonRandom.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonRandom.cs b/osu.Game/Screens/Select/FooterButtonRandom.cs index 3a4bad43b3..2d5d049133 100644 --- a/osu.Game/Screens/Select/FooterButtonRandom.cs +++ b/osu.Game/Screens/Select/FooterButtonRandom.cs @@ -93,16 +93,22 @@ namespace osu.Game.Screens.Select protected override bool OnKeyDown(KeyDownEvent e) { - updateText(e.ShiftPressed); + updateText(e); return base.OnKeyDown(e); } protected override void OnKeyUp(KeyUpEvent e) { - updateText(e.ShiftPressed); + updateText(e); base.OnKeyUp(e); } + protected override bool OnMouseDown(MouseDownEvent e) + { + updateText(e); + return base.OnMouseDown(e); + } + protected override bool OnClick(ClickEvent e) { try @@ -126,6 +132,8 @@ namespace osu.Game.Screens.Select rewindSearch = true; TriggerClick(); } + + updateText(e); } public override bool OnPressed(KeyBindingPressEvent e) @@ -150,10 +158,12 @@ namespace osu.Game.Screens.Select } } - private void updateText(bool rewind = false) + private void updateText(UIEvent e) { - randomSpriteText.Alpha = rewind ? 0 : 1; - rewindSpriteText.Alpha = rewind ? 1 : 0; + bool aboutToRewind = e.ShiftPressed || e.CurrentState.Mouse.IsPressed(MouseButton.Right); + + randomSpriteText.Alpha = aboutToRewind ? 0 : 1; + rewindSpriteText.Alpha = aboutToRewind ? 1 : 0; } } } From 9fe787acd89e04cdeb108129eb0055864343bbea Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 15:03:59 +0900 Subject: [PATCH 0884/1400] Enable NRT on `AccuracyHeatmap` --- osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 0249b6d9b1..495fccf03a 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.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. -#nullable disable - using System; using System.Diagnostics; using System.Linq; @@ -36,8 +34,8 @@ namespace osu.Game.Rulesets.Osu.Statistics private const float rotation = 45; - private BufferedContainer bufferedGrid; - private GridContainer pointGrid; + private BufferedContainer bufferedGrid = null!; + private GridContainer pointGrid = null!; private readonly ScoreInfo score; private readonly IBeatmap playableBeatmap; From 3054348c730db26c981cf5e06a36f2cc392da6ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 15:22:48 +0900 Subject: [PATCH 0885/1400] Add text hints to accuracy heat map to better describe travel direction --- .../Statistics/AccuracyHeatmap.cs | 80 ++++++++++++++----- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 495fccf03a..9d9b3fb84a 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Scoring; using osuTK; @@ -64,34 +65,36 @@ namespace osu.Game.Rulesets.Osu.Statistics FillMode = FillMode.Fit, Children = new Drawable[] { - new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(inner_portion), - Masking = true, - BorderThickness = line_thickness, - BorderColour = Color4.White, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4Extensions.FromHex("#202624") - } - }, new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { + new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(inner_portion), + Masking = true, + BorderThickness = line_thickness, + BorderColour = Color4.White, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4Extensions.FromHex("#202624") + } + }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding(1), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Rotation = rotation, Child = new Container { RelativeSizeAxes = Axes.Both, - Masking = true, Children = new Drawable[] { new Box @@ -100,9 +103,9 @@ namespace osu.Game.Rulesets.Osu.Statistics Origin = Anchor.Centre, EdgeSmoothness = new Vector2(1), RelativeSizeAxes = Axes.Y, - Height = 2, // We're rotating along a diagonal - we don't really care how big this is. - Width = line_thickness / 2, - Rotation = -rotation, + Width = line_thickness / 2, // adjust for edgesmoothness + Height = MathF.Sqrt(2), + Rotation = -rotation * 2, Alpha = 0.3f, }, new Box @@ -111,9 +114,44 @@ namespace osu.Game.Rulesets.Osu.Statistics Origin = Anchor.Centre, EdgeSmoothness = new Vector2(1), RelativeSizeAxes = Axes.Y, - Height = 2, // We're rotating along a diagonal - we don't really care how big this is. Width = line_thickness / 2, // adjust for edgesmoothness - Rotation = rotation + Height = MathF.Sqrt(2), + }, + new OsuSpriteText + { + Text = "Next", + Anchor = Anchor.Centre, + Origin = Anchor.BottomRight, + Padding = new MarginPadding(3), + RelativePositionAxes = Axes.Both, + Y = -inner_portion / 2, + }, + new OsuSpriteText + { + Text = "object", + Anchor = Anchor.Centre, + Origin = Anchor.BottomLeft, + Padding = new MarginPadding(3), + RelativePositionAxes = Axes.Both, + Y = -inner_portion / 2, + }, + new OsuSpriteText + { + Text = "Last", + Anchor = Anchor.Centre, + Origin = Anchor.TopRight, + Padding = new MarginPadding(3), + RelativePositionAxes = Axes.Both, + Y = inner_portion / 2, + }, + new OsuSpriteText + { + Text = "object", + Anchor = Anchor.Centre, + Origin = Anchor.TopLeft, + Padding = new MarginPadding(3), + RelativePositionAxes = Axes.Both, + Y = inner_portion / 2, }, } }, From 79e1d978e7581f5303fc37270f2bc02aa9c1b60e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 15:42:38 +0900 Subject: [PATCH 0886/1400] Ensure scroll-to-top button is displayed above all overlay content --- osu.Game/Overlays/OnlineOverlay.cs | 8 ++++++++ osu.Game/Overlays/OverlayScrollContainer.cs | 2 +- osu.Game/Overlays/UserProfileOverlay.cs | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index 4d2c6bc9d0..8b7a82f899 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.cs @@ -77,6 +77,14 @@ namespace osu.Game.Overlays base.Content.Add(mainContent); } + protected override void LoadComplete() + { + base.LoadComplete(); + + // Ensure the scroll-to-top button is displayed above the fixed header. + AddInternal(ScrollFlow.Button.CreateProxy()); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Overlays/OverlayScrollContainer.cs b/osu.Game/Overlays/OverlayScrollContainer.cs index 2a615f0e12..9ff0a65652 100644 --- a/osu.Game/Overlays/OverlayScrollContainer.cs +++ b/osu.Game/Overlays/OverlayScrollContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays /// private const int button_scroll_position = 200; - protected ScrollBackButton Button; + public ScrollBackButton Button { get; private set; } private readonly Bindable lastScrollTarget = new Bindable(); diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index d1fe877e55..ab4f07b982 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -249,12 +249,14 @@ namespace osu.Game.Overlays private partial class ProfileSectionsContainer : SectionsContainer { + private OverlayScrollContainer scroll = null!; + public ProfileSectionsContainer() { RelativeSizeAxes = Axes.Both; } - protected override UserTrackingScrollContainer CreateScrollContainer() => new OverlayScrollContainer(); + protected override UserTrackingScrollContainer CreateScrollContainer() => scroll = new OverlayScrollContainer(); // Reverse child ID is required so expanding beatmap panels can appear above sections below them. // This can also be done by setting Depth when adding new sections above if using ReverseChildID turns out to have any issues. @@ -267,6 +269,14 @@ namespace osu.Game.Overlays Padding = new MarginPadding { Horizontal = 10 }, Margin = new MarginPadding { Bottom = 10 }, }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + // Ensure the scroll-to-top button is displayed above the fixed header. + AddInternal(scroll.Button.CreateProxy()); + } } } } From e97d027230362277c9a12dab6581d387cc91f9a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:13:03 +0900 Subject: [PATCH 0887/1400] Make `OnlinePlayPill` class `abstract` --- .../Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs index 80e82c3856..1235e5234c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs @@ -10,12 +10,12 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { - public partial class OnlinePlayPill : OnlinePlayComposite + public abstract partial class OnlinePlayPill : OnlinePlayComposite { protected PillContainer Pill; protected OsuTextFlowContainer TextFlow; - public OnlinePlayPill() + protected OnlinePlayPill() { AutoSizeAxes = Axes.Both; } From 730bc3a9616e03d129224704373273fe93fc293f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:13:54 +0900 Subject: [PATCH 0888/1400] Apply NRT and simplify some remaining code --- .../OnlinePlay/Lounge/Components/MatchTypePill.cs | 3 +-- .../OnlinePlay/Lounge/Components/OnlinePlayPill.cs | 6 ++---- .../OnlinePlay/Lounge/Components/QueueModePill.cs | 3 +-- .../Lounge/Components/RoomSpecialCategoryPill.cs | 9 ++------- .../OnlinePlay/Lounge/Components/RoomStatusPill.cs | 6 ++---- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index e019de0f6f..35e0482f2b 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -20,8 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void onMatchTypeChanged(ValueChangedEvent type) { - TextFlow.Clear(); - TextFlow.AddText(type.NewValue.GetLocalisableDescription()); + TextFlow.Text = type.NewValue.GetLocalisableDescription(); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs index 1235e5234c..983fab8525 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; @@ -12,8 +10,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public abstract partial class OnlinePlayPill : OnlinePlayComposite { - protected PillContainer Pill; - protected OsuTextFlowContainer TextFlow; + protected PillContainer Pill { get; private set; } = null!; + protected OsuTextFlowContainer TextFlow { get; private set; } = null!; protected OnlinePlayPill() { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index e402653c2f..208c11c155 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -20,8 +20,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void onQueueModeChanged(ValueChangedEvent mode) { - TextFlow.Clear(); - TextFlow.AddText(mode.NewValue.GetLocalisableDescription()); + TextFlow.Text = mode.NewValue.GetLocalisableDescription(); } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index b869ede9bd..e88624f877 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -19,18 +19,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - Pill.Background.Colour = colours.Pink; Pill.Background.Alpha = 1; TextFlow.Colour = Color4.Black; Category.BindValueChanged(c => { - TextFlow.Clear(); - TextFlow.AddText(c.NewValue.GetLocalisableDescription()); - - var backgroundColour = colours.ForRoomCategory(Category.Value); - if (backgroundColour != null) - Pill.Background.Colour = backgroundColour.Value; + TextFlow.Text = c.NewValue.GetLocalisableDescription(); + Pill.Background.Colour = colours.ForRoomCategory(c.NewValue) ?? colours.Pink; }, true); } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index f260d168a7..ab3d293db8 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -30,17 +30,15 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components FinishTransforms(true); TextFlow.Colour = Colour4.Black; + Pill.Background.Alpha = 1; } private void updateDisplay() { RoomStatus status = getDisplayStatus(); - Pill.Background.Alpha = 1; Pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); - - TextFlow.Clear(); - TextFlow.AddText(status.Message); + TextFlow.Text = status.Message; } private RoomStatus getDisplayStatus() From ec2b9165d59a1ebdba6a2703cfa908f406ec931f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:33:58 +0900 Subject: [PATCH 0889/1400] Adjust `BeatDivisorControl` test to show control mmuch larger --- osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 56b16301be..c3d5ecac5c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -42,7 +42,8 @@ namespace osu.Game.Tests.Visual.Editing { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(90, 90) + Size = new Vector2(90, 90), + Scale = new Vector2(3), } }; }); From 87ff28b0220c40691eab57038f98f366b2601986 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:34:10 +0900 Subject: [PATCH 0890/1400] Update beat divisor control to show ticks in more visually correct locations As proposed in https://github.com/ppy/osu/discussions/23527. --- .../Edit/Compose/Components/BeatDivisorControl.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 9f422d5aa9..3bfe81e6a7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -410,6 +410,16 @@ namespace osu.Game.Screens.Edit.Compose.Components }); } + // Add a fake 1/1 at the end to give context. + AddInternal(new Tick(1) + { + Anchor = Anchor.CentreRight, + Origin = Anchor.Centre, + Depth = float.MaxValue, + Alpha = 0.05f, + Colour = BindableBeatDivisor.GetColourFor(1, colours), + }); + AddInternal(marker = new Marker()); CurrentNumber.ValueChanged += moveMarker; CurrentNumber.TriggerChange(); @@ -483,7 +493,7 @@ namespace osu.Game.Screens.Edit.Compose.Components OnUserChange(Current.Value); } - private float getMappedPosition(float divisor) => MathF.Pow((divisor - 1) / (beatDivisor.ValidDivisors.Value.Presets.Last() - 1), 0.90f); + private float getMappedPosition(float divisor) => 1 - 1 / divisor; private partial class Tick : Circle { From 7d7d402d4e06459e6834db800018d7000b2fa61b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:58:23 +0900 Subject: [PATCH 0891/1400] Apply NRT to `PlacementBlueprint` --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 12c0ea1807..5eca4f8ccd 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.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. -#nullable disable - using System.Linq; using System.Threading; using osu.Framework.Allocation; @@ -38,16 +36,16 @@ namespace osu.Game.Rulesets.Edit /// public readonly HitObject HitObject; - [Resolved(canBeNull: true)] - protected EditorClock EditorClock { get; private set; } + [Resolved] + protected EditorClock? EditorClock { get; private set; } [Resolved] - private EditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } = null!; - private Bindable startTimeBindable; + private Bindable startTimeBindable = null!; [Resolved] - private IPlacementHandler placementHandler { get; set; } + private IPlacementHandler placementHandler { get; set; } = null!; /// /// Whether this blueprint is currently in a state that can be committed. From e43f2c2c439bbc5c524606b20ee1bfb651cacb06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 16:58:43 +0900 Subject: [PATCH 0892/1400] Improve previous hitobject lookup efficient and correctness --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 5eca4f8ccd..9ef208bcb5 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -44,6 +44,8 @@ namespace osu.Game.Rulesets.Edit private Bindable startTimeBindable = null!; + private HitObject? getPreviousHitObject() => beatmap.HitObjects.TakeWhile(h => h.StartTime <= startTimeBindable.Value).LastOrDefault(); + [Resolved] private IPlacementHandler placementHandler { get; set; } = null!; @@ -84,7 +86,7 @@ namespace osu.Game.Rulesets.Edit protected void BeginPlacement(bool commitStart = false) { // Take the hitnormal sample of the last hit object - var lastHitNormal = beatmap.HitObjects.LastOrDefault(h => h.GetEndTime() < HitObject.StartTime)?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); + var lastHitNormal = getPreviousHitObject()?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); if (lastHitNormal != null) HitObject.Samples[0] = lastHitNormal; From 8d925c8a8a5f06c33bddcf28b543a784a159b71a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 17:19:07 +0900 Subject: [PATCH 0893/1400] Move combo information updating to an interface level helper method --- osu.Game/Beatmaps/BeatmapProcessor.cs | 27 +++---------------- .../Objects/Types/IHasComboInformation.cs | 23 ++++++++++++++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 8f3d0b7445..fb5313469f 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.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. -#nullable disable - using System.Linq; using osu.Game.Rulesets.Objects.Types; @@ -22,34 +20,17 @@ namespace osu.Game.Beatmaps public virtual void PreProcess() { - IHasComboInformation lastObj = null; - - bool isFirst = true; + IHasComboInformation? lastObj = null; foreach (var obj in Beatmap.HitObjects.OfType()) { - if (isFirst) + if (lastObj == null) { - obj.NewCombo = true; - // first hitobject should always be marked as a new combo for sanity. - isFirst = false; - } - - obj.ComboIndex = lastObj?.ComboIndex ?? 0; - obj.ComboIndexWithOffsets = lastObj?.ComboIndexWithOffsets ?? 0; - obj.IndexInCurrentCombo = (lastObj?.IndexInCurrentCombo + 1) ?? 0; - - if (obj.NewCombo) - { - obj.IndexInCurrentCombo = 0; - obj.ComboIndex++; - obj.ComboIndexWithOffsets += obj.ComboOffset + 1; - - if (lastObj != null) - lastObj.LastInCombo = true; + obj.NewCombo = true; } + obj.UpdateComboInformation(lastObj); lastObj = obj; } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs index b45ea989f3..d34e71021f 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Skinning; using osuTK.Graphics; @@ -65,5 +63,26 @@ namespace osu.Game.Rulesets.Objects.Types { return skin.GetConfig(new SkinComboColourLookup(comboIndex, combo))?.Value ?? Color4.White; } + + /// + /// Given the previous object in the beatmap, update relevant combo information. + /// + /// The previous hitobject, or null if this is the first object in the beatmap. + void UpdateComboInformation(IHasComboInformation? lastObj) + { + ComboIndex = lastObj?.ComboIndex ?? 0; + ComboIndexWithOffsets = lastObj?.ComboIndexWithOffsets ?? 0; + IndexInCurrentCombo = (lastObj?.IndexInCurrentCombo + 1) ?? 0; + + if (NewCombo || lastObj == null) + { + IndexInCurrentCombo = 0; + ComboIndex++; + ComboIndexWithOffsets += ComboOffset + 1; + + if (lastObj != null) + lastObj.LastInCombo = true; + } + } } } From 9563d4f73004ad5794e0031f2046fdfd1bd5dda9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 17:19:18 +0900 Subject: [PATCH 0894/1400] Fix weird purple tint on placement object in timeline --- .../Compose/Components/Timeline/TimelineBlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index f93fb0679f..30f56814ba 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -83,7 +83,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { placementBlueprint = CreateBlueprintFor(obj.NewValue).AsNonNull(); - placementBlueprint.Colour = Color4.MediumPurple; + placementBlueprint.Colour = OsuColour.Gray(0.9f); SelectionBlueprints.Add(placementBlueprint); } From 0b25818bd218d0d6388af0a5da2d7a0f0190c68d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 17:20:15 +0900 Subject: [PATCH 0895/1400] Update combo information on placement blueprint --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 9ef208bcb5..84e32d99f8 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -14,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Bindings; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose; using osuTK; @@ -148,7 +149,12 @@ namespace osu.Game.Rulesets.Edit public virtual void UpdateTimeAndPosition(SnapResult result) { if (PlacementActive == PlacementState.Waiting) + { HitObject.StartTime = result.Time ?? EditorClock?.CurrentTime ?? Time.Current; + + if (HitObject is IHasComboInformation comboInformation) + comboInformation.UpdateComboInformation(getPreviousHitObject() as IHasComboInformation); + } } /// From 214d7e07fa1ad2b4016a751b2ee6f495384b6ac5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 17:49:04 +0900 Subject: [PATCH 0896/1400] Add TODO regarding failing stack display code --- .../Compose/Components/Timeline/TimelineBlueprintContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 30f56814ba..b60e04afc1 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -85,6 +85,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline placementBlueprint.Colour = OsuColour.Gray(0.9f); + // TODO: this is out of order, causing incorrect stacking height. SelectionBlueprints.Add(placementBlueprint); } } From b58ab28765974714537a893a60e5bfff39e71f29 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 May 2023 20:54:17 +0900 Subject: [PATCH 0897/1400] Make `EditorClock` non-nullable in `PlacementBlueprint` --- .../Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs | 8 ++------ osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 73ee5df9dc..f59be0e0e9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -24,9 +21,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners private bool isPlacingEnd; - [Resolved(CanBeNull = true)] - [CanBeNull] - private IBeatSnapProvider beatSnapProvider { get; set; } + [Resolved] + private IBeatSnapProvider? beatSnapProvider { get; set; } public SpinnerPlacementBlueprint() : base(new Spinner { Position = OsuPlayfield.BASE_SIZE / 2 }) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 84e32d99f8..b10f1a2af5 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Edit public readonly HitObject HitObject; [Resolved] - protected EditorClock? EditorClock { get; private set; } + protected EditorClock EditorClock { get; private set; } = null!; [Resolved] private EditorBeatmap beatmap { get; set; } = null!; @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Edit { if (PlacementActive == PlacementState.Waiting) { - HitObject.StartTime = result.Time ?? EditorClock?.CurrentTime ?? Time.Current; + HitObject.StartTime = result.Time ?? EditorClock.CurrentTime; if (HitObject is IHasComboInformation comboInformation) comboInformation.UpdateComboInformation(getPreviousHitObject() as IHasComboInformation); From 7ac6688a0fd8c57f5d04c846ff0c04e069d61c89 Mon Sep 17 00:00:00 2001 From: Dimmitsaras Date: Wed, 17 May 2023 18:34:39 +0300 Subject: [PATCH 0898/1400] Chat message notifications always play on unfocused window --- osu.Game/Online/Chat/MessageNotifier.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index 9b2ad666b2..cb29fc4535 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -12,6 +12,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Platform; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Online.API; @@ -35,6 +36,9 @@ namespace osu.Game.Online.Chat [Resolved] private ChannelManager channelManager { get; set; } + [Resolved] + private GameHost host { get; set; } + private Bindable notifyOnUsername; private Bindable notifyOnPrivateMessage; @@ -89,8 +93,8 @@ namespace osu.Game.Online.Chat if (channel == null) return; - // Only send notifications, if ChatOverlay and the target channel aren't visible. - if (chatOverlay.IsPresent && channelManager.CurrentChannel.Value == channel) + // Only send notifications, if ChatOverlay and the target channel aren't visible, or if the window is unfocused + if (chatOverlay.IsPresent && channelManager.CurrentChannel.Value == channel && host.IsActive.Value) return; foreach (var message in messages.OrderByDescending(m => m.Id)) @@ -99,6 +103,7 @@ namespace osu.Game.Online.Chat if (message.Id <= channel.LastReadId) return; + // ignore notifications triggered by your own chat messages if (message.Sender.Id == localUser.Value.Id) continue; From caa79704acb69efd92dff2c40dc450988bf0230d Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 17 May 2023 20:23:37 -0700 Subject: [PATCH 0899/1400] Add test coverage for failing case --- .../Resources/storyboard_only_video.osu | 31 +++++++++++++++++++ .../Visual/Gameplay/TestSceneStoryboard.cs | 18 ++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Tests/Resources/storyboard_only_video.osu diff --git a/osu.Game.Tests/Resources/storyboard_only_video.osu b/osu.Game.Tests/Resources/storyboard_only_video.osu new file mode 100644 index 0000000000..25f1ff6361 --- /dev/null +++ b/osu.Game.Tests/Resources/storyboard_only_video.osu @@ -0,0 +1,31 @@ +osu file format v14 + +[Events] +//Background and Video events +0,0,"BG.jpg",0,0 +Video,0,"video.avi" +//Break Periods +//Storyboard Layer 0 (Background) +//Storyboard Layer 1 (Fail) +//Storyboard Layer 2 (Pass) +//Storyboard Layer 3 (Foreground) +//Storyboard Layer 4 (Overlay) +//Storyboard Sound Samples + +[TimingPoints] +1674,333.333333333333,4,2,1,70,1,0 +1674,-100,4,2,1,70,0,0 +3340,-100,4,2,1,70,0,0 +3507,-100,4,2,1,70,0,0 +3673,-100,4,2,1,70,0,0 + +[Colours] +Combo1 : 240,80,80 +Combo2 : 171,252,203 +Combo3 : 128,128,255 +Combo4 : 249,254,186 + +[HitObjects] +148,303,1674,5,6,3:2:0:0: +378,252,1840,1,0,0:0:0:0: +389,270,2340,5,2,0:1:0:0: diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs index dbce62cbef..a6663f3086 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStoryboard.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 System; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -8,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO; @@ -42,6 +44,18 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("Load storyboard with missing video", () => loadStoryboard("storyboard_no_video.osu")); } + [Test] + public void TestVideoSize() + { + AddStep("load storyboard with only video", () => + { + // LegacyStoryboardDecoder doesn't parse WidescreenStoryboard, so it is set manually + loadStoryboard("storyboard_only_video.osu", s => s.BeatmapInfo.WidescreenStoryboard = false); + }); + + AddAssert("storyboard is correct width", () => Precision.AlmostEquals(storyboard?.Width ?? 0f, 480 * 16 / 9f)); + } + [BackgroundDependencyLoader] private void load() { @@ -102,7 +116,7 @@ namespace osu.Game.Tests.Visual.Gameplay decoupledClock.ChangeSource(Beatmap.Value.Track); } - private void loadStoryboard(string filename) + private void loadStoryboard(string filename, Action? setUpStoryboard = null) { Storyboard loaded; @@ -113,6 +127,8 @@ namespace osu.Game.Tests.Visual.Gameplay loaded = decoder.Decode(bfr); } + setUpStoryboard?.Invoke(loaded); + loadStoryboard(loaded); } } From ee522253cb0373b8ca231557e8d56ec2d888945f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 18 May 2023 14:12:57 +0900 Subject: [PATCH 0900/1400] Remove a couple of unnecessary `volume` declarations --- osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs | 2 +- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 9a78df23cf..f21825668f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Tests NewCombo = i % 8 == 0, Samples = new List(new[] { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: 100) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }) }); } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index eae9f922a4..919a3cdfdf 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Edit HitObject = hitObject; // adding the default hit sample should be the case regardless of the ruleset. - HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL, volume: 100)); + HitObject.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_NORMAL)); RelativeSizeAxes = Axes.Both; From f2483a1cf8c4f91fd8c9374b803e2bd553fe68f4 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 17:27:47 +0900 Subject: [PATCH 0901/1400] Add some helper methods, fix precision differences Introduces some error at all times, but if we're to store scores everywhere as `long`, then the same precision should be applied to the "during gameplay" path as well. --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 40 ++++++++++++++++----- osu.Game/Scoring/IScoreInfo.cs | 3 ++ osu.Game/Scoring/ScoreManager.cs | 10 +++--- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 9172034ff6..cbcf0dceaf 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -274,20 +274,44 @@ namespace osu.Game.Rulesets.Scoring { Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; - double standardisedScore = ComputeTotalScore(); + long standardisedScore = (long)Math.Round(ComputeTotalScore()); - if (Mode.Value == ScoringMode.Standardised) - TotalScore.Value = (long)Math.Round(standardisedScore); - else - TotalScore.Value = ConvertToClassic(standardisedScore); + TotalScore.Value = Mode.Value == ScoringMode.Standardised + ? standardisedScore + : convertToClassic(standardisedScore, MaxBasicJudgements, ClassicScoreMultiplier); } - public long ConvertToClassic(double standardised) + /// + /// Retrieves the total score from a in the given scoring mode. + /// + /// The mode to return the total score in. + /// The score to get the total score of. + /// The total score. + public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo) + { + int maxBasicJudgements = scoreInfo.MaximumStatistics.Where(k => k.Key.IsBasic()) + .Select(k => k.Value) + .DefaultIfEmpty(0) + .Sum(); + + return mode == ScoringMode.Standardised + ? scoreInfo.TotalScore + : convertToClassic(scoreInfo.TotalScore, maxBasicJudgements, ClassicScoreMultiplier); + } + + /// + /// Converts a standardised total score to the classic score. + /// + /// The standardised score. + /// The maximum possible number of basic judgements. + /// The classic multiplier. + /// The classic score. + private static long convertToClassic(long score, int maxBasicJudgements, double classicMultiplier) { // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. - double scaledRawScore = standardised / MAX_SCORE; - return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, MaxBasicJudgements), 2) * ClassicScoreMultiplier); + double scaledRawScore = score / MAX_SCORE; + return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * classicMultiplier); } protected abstract double ComputeTotalScore(); diff --git a/osu.Game/Scoring/IScoreInfo.cs b/osu.Game/Scoring/IScoreInfo.cs index 289679a724..ffc30384d2 100644 --- a/osu.Game/Scoring/IScoreInfo.cs +++ b/osu.Game/Scoring/IScoreInfo.cs @@ -15,6 +15,9 @@ namespace osu.Game.Scoring { IUser User { get; } + /// + /// The standardised total score. + /// long TotalScore { get; } int MaxCombo { get; } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 0674947f30..f616c6db6d 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -107,15 +107,13 @@ namespace osu.Game.Scoring /// The total score. public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) { + // Shortcut to avoid potentially creating many ruleset objects in the default scoring mode. if (mode == ScoringMode.Standardised) return score.TotalScore; - var ruleset = score.Ruleset.CreateInstance(); - var scoreProcessor = ruleset.CreateScoreProcessor(); - scoreProcessor.Mods.Value = score.Mods; - - // Todo: This loses precision because we're dealing with pre-rounded total scores. - return scoreProcessor.ConvertToClassic(score.TotalScore); + return score.Ruleset.CreateInstance() + .CreateScoreProcessor() + .ComputeScore(mode, score); } /// From 829e47d30b279ca949b9b2f02d57724a9048e27e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 17:47:25 +0900 Subject: [PATCH 0902/1400] Add MaxTotalScore for performance breakdown calculator --- .../Rulesets/Difficulty/PerformanceBreakdownCalculator.cs | 6 +++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 03bd0f7509..3dd7f934a8 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -62,13 +62,13 @@ namespace osu.Game.Rulesets.Difficulty .GroupBy(hr => hr, (hr, list) => (hitResult: hr, count: list.Count())) .ToDictionary(pair => pair.hitResult, pair => pair.count); perfectPlay.Statistics = statistics; + perfectPlay.MaximumStatistics = statistics; // calculate total score ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor(); scoreProcessor.Mods.Value = perfectPlay.Mods; - - // Todo: - // perfectPlay.TotalScore = scoreProcessor.ComputeScore(ScoringMode.Standardised, perfectPlay); + scoreProcessor.ApplyBeatmap(playableBeatmap); + perfectPlay.TotalScore = scoreProcessor.MaxTotalScore; // compute rank achieved // default to SS, then adjust the rank with mods diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index cbcf0dceaf..ebecc39aa7 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -97,6 +97,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly Ruleset Ruleset; + /// + /// The maximum achievable total score. + /// + public long MaxTotalScore { get; private set; } + /// /// The sum of all basic judgements at the current time. /// @@ -334,6 +339,8 @@ namespace osu.Game.Rulesets.Scoring maximumResultCounts.Clear(); maximumResultCounts.AddRange(scoreResultCounts); + + MaxTotalScore = TotalScore.Value; } scoreResultCounts.Clear(); From 510b8e4c7887df92574ec0963154082a9ebb8347 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 18:53:43 +0900 Subject: [PATCH 0903/1400] Remove ScoreManager.Mode, handle per-use --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 48 +------------------ .../Scoring/Legacy/ScoreInfoExtensions.cs | 45 +++++++++++++++++ osu.Game/Scoring/ScoreManager.cs | 12 +---- .../Play/HUD/GameplayLeaderboardScore.cs | 18 ++++++- .../Screens/Play/HUD/GameplayScoreCounter.cs | 5 +- .../Screens/Play/HUD/ILeaderboardScore.cs | 4 ++ .../Play/HUD/SoloGameplayLeaderboard.cs | 18 ++----- osu.Game/Screens/Play/Player.cs | 3 -- 8 files changed, 77 insertions(+), 76 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ebecc39aa7..bda2d7140d 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Scoring { public abstract partial class ScoreProcessor : JudgementProcessor { - protected const double MAX_SCORE = 1000000; + public const double MAX_SCORE = 1000000; private const double accuracy_cutoff_x = 1; private const double accuracy_cutoff_s = 0.95; @@ -76,11 +76,6 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableInt HighestCombo = new BindableInt(); - /// - /// The used to calculate scores. - /// - public readonly Bindable Mode = new Bindable(); - /// /// The s collected during gameplay thus far. /// Intended for use with various statistics displays. @@ -173,7 +168,6 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue); }; - Mode.ValueChanged += _ => updateScore(); Mods.ValueChanged += mods => { ScoreMultiplier = 1; @@ -278,45 +272,7 @@ namespace osu.Game.Rulesets.Scoring private void updateScore() { Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; - - long standardisedScore = (long)Math.Round(ComputeTotalScore()); - - TotalScore.Value = Mode.Value == ScoringMode.Standardised - ? standardisedScore - : convertToClassic(standardisedScore, MaxBasicJudgements, ClassicScoreMultiplier); - } - - /// - /// Retrieves the total score from a in the given scoring mode. - /// - /// The mode to return the total score in. - /// The score to get the total score of. - /// The total score. - public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo) - { - int maxBasicJudgements = scoreInfo.MaximumStatistics.Where(k => k.Key.IsBasic()) - .Select(k => k.Value) - .DefaultIfEmpty(0) - .Sum(); - - return mode == ScoringMode.Standardised - ? scoreInfo.TotalScore - : convertToClassic(scoreInfo.TotalScore, maxBasicJudgements, ClassicScoreMultiplier); - } - - /// - /// Converts a standardised total score to the classic score. - /// - /// The standardised score. - /// The maximum possible number of basic judgements. - /// The classic multiplier. - /// The classic score. - private static long convertToClassic(long score, int maxBasicJudgements, double classicMultiplier) - { - // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. - // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. - double scaledRawScore = score / MAX_SCORE; - return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * classicMultiplier); + TotalScore.Value = (long)Math.Round(ComputeTotalScore()); } protected abstract double ComputeTotalScore(); diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index e42f6caf26..af991c7ea3 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -3,13 +3,58 @@ #nullable disable +using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring.Legacy { public static class ScoreInfoExtensions { + public static long GetDisplayScore(this ScoreProcessor scoreProcessor, ScoringMode mode) + => getDisplayScore(scoreProcessor.Ruleset.RulesetInfo.OnlineID, scoreProcessor.TotalScore.Value, mode, scoreProcessor.MaximumStatistics); + + public static long GetDisplayScore(this ScoreInfo scoreInfo, ScoringMode mode) + => getDisplayScore(scoreInfo.Ruleset.OnlineID, scoreInfo.TotalScore, mode, scoreInfo.MaximumStatistics); + + private static long getDisplayScore(int rulesetId, long score, ScoringMode mode, IReadOnlyDictionary maximumStatistics) + { + if (mode == ScoringMode.Standardised) + return score; + + double multiplier; + + switch (rulesetId) + { + case 0: + multiplier = 36; + break; + + case 1: + multiplier = 22; + break; + + case 2: + multiplier = 28; + break; + + case 3: + multiplier = 16; + break; + + default: + return score; + } + + int maxBasicJudgements = maximumStatistics.Where(k => k.Key.IsBasic()).Select(k => k.Value).DefaultIfEmpty(0).Sum(); + + // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. + // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. + double scaledRawScore = score / ScoreProcessor.MAX_SCORE; + return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * multiplier); + } + public static int? GetCountGeki(this ScoreInfo scoreInfo) { switch (scoreInfo.Ruleset.OnlineID) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index f616c6db6d..fa5a9fc7c1 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -20,6 +20,7 @@ using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Online.API; +using osu.Game.Scoring.Legacy; namespace osu.Game.Scoring { @@ -105,16 +106,7 @@ namespace osu.Game.Scoring /// The to calculate the total score of. /// The to return the total score as. /// The total score. - public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) - { - // Shortcut to avoid potentially creating many ruleset objects in the default scoring mode. - if (mode == ScoringMode.Standardised) - return score.TotalScore; - - return score.Ruleset.CreateInstance() - .CreateScoreProcessor() - .ComputeScore(mode, score); - } + public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) => score.GetDisplayScore(mode); /// /// Retrieves the maximum achievable combo for the provided score. diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 07b80feb3e..74a3925435 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -11,8 +11,10 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Scoring; using osu.Game.Users; using osu.Game.Users.Drawables; using osu.Game.Utils; @@ -55,6 +57,7 @@ namespace osu.Game.Screens.Play.HUD public BindableInt Combo { get; } = new BindableInt(); public BindableBool HasQuit { get; } = new BindableBool(); public Bindable DisplayOrder { get; } = new Bindable(); + public Func GetDisplayScore { get; set; } public Color4? BackgroundColour { get; set; } @@ -100,6 +103,8 @@ namespace osu.Game.Screens.Play.HUD private Container scoreComponents; + private IBindable scoreDisplayMode; + /// /// Creates a new . /// @@ -112,10 +117,12 @@ namespace osu.Game.Screens.Play.HUD AutoSizeAxes = Axes.X; Height = PANEL_HEIGHT; + + GetDisplayScore = _ => TotalScore.Value; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, OsuConfigManager osuConfigManager) { Container avatarContainer; @@ -286,7 +293,9 @@ namespace osu.Game.Screens.Play.HUD LoadComponentAsync(new DrawableAvatar(User), avatarContainer.Add); - TotalScore.BindValueChanged(v => scoreText.Text = v.NewValue.ToString("N0"), true); + scoreDisplayMode = osuConfigManager.GetBindable(OsuSetting.ScoreDisplayMode); + scoreDisplayMode.BindValueChanged(_ => updateScore()); + TotalScore.BindValueChanged(_ => updateScore(), true); Accuracy.BindValueChanged(v => { @@ -303,6 +312,11 @@ namespace osu.Game.Screens.Play.HUD HasQuit.BindValueChanged(_ => updateState()); } + private void updateScore() + { + scoreText.Text = GetDisplayScore(scoreDisplayMode.Value).ToString("N0"); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs index a11cccd97c..a696d2cad7 100644 --- a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs @@ -9,12 +9,14 @@ using osu.Framework.Bindables; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring.Legacy; namespace osu.Game.Screens.Play.HUD { public abstract partial class GameplayScoreCounter : ScoreCounter { private Bindable scoreDisplayMode; + private Bindable totalScoreBindable; protected GameplayScoreCounter() : base(6) @@ -42,7 +44,8 @@ namespace osu.Game.Screens.Play.HUD } }, true); - Current.BindTo(scoreProcessor.TotalScore); + totalScoreBindable = scoreProcessor.TotalScore.GetBoundCopy(); + totalScoreBindable.BindValueChanged(_ => Current.Value = scoreProcessor.GetDisplayScore(scoreDisplayMode.Value), true); } } } diff --git a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs index 428390f90c..cc1d83e0c7 100644 --- a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs @@ -3,7 +3,9 @@ #nullable disable +using System; using osu.Framework.Bindables; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Play.HUD { @@ -20,5 +22,7 @@ namespace osu.Game.Screens.Play.HUD /// Lower numbers will appear higher in cases of ties. /// Bindable DisplayOrder { get; } + + Func GetDisplayScore { get; set; } } } diff --git a/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs index 9f92880919..e9bb1d2101 100644 --- a/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/SoloGameplayLeaderboard.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -10,6 +9,7 @@ using osu.Game.Configuration; using osu.Game.Online.API.Requests; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; using osu.Game.Screens.Select; using osu.Game.Users; @@ -27,15 +27,9 @@ namespace osu.Game.Screens.Play.HUD public readonly IBindableList Scores = new BindableList(); - // hold references to ensure bindables are updated. - private readonly List> scoreBindables = new List>(); - [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; - [Resolved] - private ScoreManager scoreManager { get; set; } = null!; - /// /// Whether the leaderboard should be visible regardless of the configuration value. /// This is true by default, but can be changed. @@ -70,7 +64,6 @@ namespace osu.Game.Screens.Play.HUD private void showScores() { Clear(); - scoreBindables.Clear(); if (!Scores.Any()) return; @@ -79,12 +72,8 @@ namespace osu.Game.Screens.Play.HUD { var score = Add(s.User, false); - var bindableTotal = scoreManager.GetBindableTotalScore(s); - - // Direct binding not possible due to differing types (see https://github.com/ppy/osu/issues/20298). - bindableTotal.BindValueChanged(total => score.TotalScore.Value = total.NewValue, true); - scoreBindables.Add(bindableTotal); - + score.GetDisplayScore = s.GetDisplayScore; + score.TotalScore.Value = s.TotalScore; score.Accuracy.Value = s.Accuracy; score.Combo.Value = s.MaxCombo; score.DisplayOrder.Value = s.OnlineID > 0 ? s.OnlineID : s.Date.ToUnixTimeSeconds(); @@ -92,6 +81,7 @@ namespace osu.Game.Screens.Play.HUD ILeaderboardScore local = Add(trackingUser, true); + local.GetDisplayScore = scoreProcessor.GetDisplayScore; local.TotalScore.BindTarget = scoreProcessor.TotalScore; local.Accuracy.BindTarget = scoreProcessor.Accuracy; local.Combo.BindTarget = scoreProcessor.HighestCombo; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5174adfc06..18ea9d0acb 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -237,9 +237,6 @@ namespace osu.Game.Screens.Play dependencies.CacheAs(HealthProcessor); - if (!ScoreProcessor.Mode.Disabled) - config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); From f3591f83a2d831a737f094afed372c365c3a40a5 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 18:55:10 +0900 Subject: [PATCH 0904/1400] Remove ScoreManager.GetTotalScore() --- osu.Game/Scoring/ScoreManager.cs | 17 ++++------------- osu.Game/Screens/Ranking/ScorePanelList.cs | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index fa5a9fc7c1..d5509538fd 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -75,7 +75,7 @@ namespace osu.Game.Scoring /// The array of s to reorder. /// The given ordered by decreasing total score. public IEnumerable OrderByTotalScore(IEnumerable scores) - => scores.OrderByDescending(s => GetTotalScore(s)) + => scores.OrderByDescending(s => s.TotalScore) .ThenBy(s => s.OnlineID) // Local scores may not have an online ID. Fall back to date in these cases. .ThenBy(s => s.Date); @@ -88,7 +88,7 @@ namespace osu.Game.Scoring /// /// The to retrieve the bindable for. /// The bindable containing the total score. - public Bindable GetBindableTotalScore([NotNull] ScoreInfo score) => new TotalScoreBindable(score, this, configManager); + public Bindable GetBindableTotalScore([NotNull] ScoreInfo score) => new TotalScoreBindable(score, configManager); /// /// Retrieves a bindable that represents the formatted total score string of a . @@ -100,14 +100,6 @@ namespace osu.Game.Scoring /// The bindable containing the formatted total score string. public Bindable GetBindableTotalScoreString([NotNull] ScoreInfo score) => new TotalScoreStringBindable(GetBindableTotalScore(score)); - /// - /// Retrieves the total score of a in the given . - /// - /// The to calculate the total score of. - /// The to return the total score as. - /// The total score. - public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) => score.GetDisplayScore(mode); - /// /// Retrieves the maximum achievable combo for the provided score. /// @@ -126,12 +118,11 @@ namespace osu.Game.Scoring /// Creates a new . /// /// The to provide the total score of. - /// The . /// The config. - public TotalScoreBindable(ScoreInfo score, ScoreManager scoreManager, OsuConfigManager configManager) + public TotalScoreBindable(ScoreInfo score, OsuConfigManager configManager) { configManager?.BindWith(OsuSetting.ScoreDisplayMode, scoringMode); - scoringMode.BindValueChanged(mode => Value = scoreManager.GetTotalScore(score, mode.NewValue), true); + scoringMode.BindValueChanged(mode => Value = score.GetDisplayScore(mode.NewValue), true); } } diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs index 29dec42083..1f93389e94 100644 --- a/osu.Game/Screens/Ranking/ScorePanelList.cs +++ b/osu.Game/Screens/Ranking/ScorePanelList.cs @@ -149,7 +149,7 @@ namespace osu.Game.Screens.Ranking var score = trackingContainer.Panel.Score; - flow.SetLayoutPosition(trackingContainer, scoreManager.GetTotalScore(score)); + flow.SetLayoutPosition(trackingContainer, score.TotalScore); trackingContainer.Show(); From 808818768bf46710191b7071f67f512078cddd2e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 19:02:49 +0900 Subject: [PATCH 0905/1400] Add TotalScore to replay frame headers --- osu.Game/Online/Spectator/FrameHeader.cs | 10 +++++++++- osu.Game/Online/Spectator/SpectatorScoreProcessor.cs | 4 +--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index b6dcd8aaa5..4d1ff23530 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -44,6 +44,12 @@ namespace osu.Game.Online.Spectator [Key(4)] public DateTimeOffset ReceivedTime { get; set; } + /// + /// The total score. + /// + [Key(5)] + public long TotalScore { get; set; } + /// /// Construct header summary information from a point-in-time reference to a score which is actively being played. /// @@ -53,6 +59,7 @@ namespace osu.Game.Online.Spectator Combo = score.Combo; MaxCombo = score.MaxCombo; Accuracy = score.Accuracy; + TotalScore = score.TotalScore; // copy for safety Statistics = new Dictionary(score.Statistics); @@ -60,13 +67,14 @@ namespace osu.Game.Online.Spectator [JsonConstructor] [SerializationConstructor] - public FrameHeader(double accuracy, int combo, int maxCombo, Dictionary statistics, DateTimeOffset receivedTime) + public FrameHeader(double accuracy, int combo, int maxCombo, Dictionary statistics, DateTimeOffset receivedTime, long totalScore) { Combo = combo; MaxCombo = maxCombo; Accuracy = accuracy; Statistics = statistics; ReceivedTime = receivedTime; + TotalScore = totalScore; } } } diff --git a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs index cb23164c00..90b584a89f 100644 --- a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs +++ b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs @@ -153,12 +153,10 @@ namespace osu.Game.Online.Spectator scoreInfo.MaxCombo = frame.Header.MaxCombo; scoreInfo.Statistics = frame.Header.Statistics; scoreInfo.MaximumStatistics = spectatorState.MaximumStatistics; + scoreInfo.TotalScore = frame.Header.TotalScore; Accuracy.Value = frame.Header.Accuracy; Combo.Value = frame.Header.Combo; - - // Todo: - // TotalScore.Value = scoreProcessor.ComputeScore(Mode.Value, scoreInfo); } protected override void Dispose(bool isDisposing) From c33e4fe75ea22c129bfbae9a5df268d8036a1ddb Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 20:10:28 +0900 Subject: [PATCH 0906/1400] Remove unnecessary override --- .../Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index 7b77785c7a..b0e4585986 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -6,14 +6,12 @@ using System; using System.Diagnostics; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Extensions; using osu.Game.Online.Rooms; using osu.Game.Rulesets; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; @@ -63,14 +61,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists return new PlaylistsResultsScreen(score, Room.RoomID.Value.Value, PlaylistItem, true); } - protected override async Task PrepareScoreForResultsAsync(Score score) - { - await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); - - // Todo: - // Score.ScoreInfo.TotalScore = ScoreProcessor.ComputeScore(ScoringMode.Standardised, Score.ScoreInfo); - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From ef86be6d21c56a3350bc0969705a91074d7b112d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 20:29:26 +0900 Subject: [PATCH 0907/1400] Fix base score added for non-accuracy-affecting objects --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 44 ++++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index bda2d7140d..1162b6ac04 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -98,14 +98,20 @@ namespace osu.Game.Rulesets.Scoring public long MaxTotalScore { get; private set; } /// - /// The sum of all basic judgements at the current time. + /// The sum of all accuracy-affecting judgements at the current time. /// - private double currentBasicScore; + /// + /// Used to compute accuracy. + /// + private double currentBaseScore; /// - /// The maximum sum of basic judgements at the current time. + /// The maximum sum of accuracy-affecting judgements at the current time. /// - private double currentMaxBasicScore; + /// + /// Used to compute accuracy. + /// + private double currentMaxBaseScore; /// /// The total count of basic judgements in the beatmap. @@ -206,8 +212,11 @@ namespace osu.Game.Rulesets.Scoring if (result.Type.IsBasic()) CurrentBasicJudgements++; - currentMaxBasicScore += Judgement.ToNumericResult(result.Judgement.MaxResult); - currentBasicScore += Judgement.ToNumericResult(result.Type); + if (result.Type.AffectsAccuracy()) + { + currentMaxBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); + currentBaseScore += Judgement.ToNumericResult(result.Type); + } AddScoreChange(result); @@ -241,8 +250,11 @@ namespace osu.Game.Rulesets.Scoring if (result.Type.IsBasic()) CurrentBasicJudgements--; - currentMaxBasicScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); - currentBasicScore -= Judgement.ToNumericResult(result.Type); + if (result.Type.AffectsAccuracy()) + { + currentMaxBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); + currentBaseScore -= Judgement.ToNumericResult(result.Type); + } RemoveScoreChange(result); @@ -257,7 +269,8 @@ namespace osu.Game.Rulesets.Scoring { if (result.Type.IsBonus()) BonusPortion += Judgement.ToNumericResult(result.Type); - else + + if (result.Type.AffectsCombo()) ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); } @@ -265,13 +278,14 @@ namespace osu.Game.Rulesets.Scoring { if (result.Type.IsBonus()) BonusPortion -= Judgement.ToNumericResult(result.Type); - else + + if (result.Type.AffectsCombo()) ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); } private void updateScore() { - Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; + Accuracy.Value = currentMaxBaseScore > 0 ? currentBaseScore / currentMaxBaseScore : 1; TotalScore.Value = (long)Math.Round(ComputeTotalScore()); } @@ -301,8 +315,8 @@ namespace osu.Game.Rulesets.Scoring scoreResultCounts.Clear(); - currentBasicScore = 0; - currentMaxBasicScore = 0; + currentBaseScore = 0; + currentMaxBaseScore = 0; CurrentBasicJudgements = 0; ComboPortion = 0; BonusPortion = 0; @@ -314,8 +328,8 @@ namespace osu.Game.Rulesets.Scoring Rank.Value = ScoreRank.X; HighestCombo.Value = 0; - currentBasicScore = 0; - currentMaxBasicScore = 0; + currentBaseScore = 0; + currentMaxBaseScore = 0; } /// From 00e0411369a14e724705fcc35f2088832aa91bcb Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 20:37:13 +0900 Subject: [PATCH 0908/1400] Fix/rework ModAccuracyChallenge calculation --- .../Rulesets/Mods/ModAccuracyChallenge.cs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 13b8ad5d84..57284b7eaa 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -42,9 +42,29 @@ namespace osu.Game.Rulesets.Mods Value = 0.9, }; - private ScoreProcessor scoreProcessor = null!; + private int baseScore; + private int maxBaseScore; - public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) => this.scoreProcessor = scoreProcessor; + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) + { + scoreProcessor.NewJudgement += j => + { + if (!j.Type.AffectsAccuracy()) + return; + + baseScore += Judgement.ToNumericResult(j.Type); + maxBaseScore += Judgement.ToNumericResult(j.Judgement.MaxResult); + }; + + scoreProcessor.JudgementReverted += j => + { + if (!j.Type.AffectsAccuracy()) + return; + + baseScore -= Judgement.ToNumericResult(j.Type); + maxBaseScore -= Judgement.ToNumericResult(j.Judgement.MaxResult); + }; + } public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; @@ -58,16 +78,11 @@ namespace osu.Game.Rulesets.Mods private double getAccuracyWithImminentResultAdded(JudgementResult result) { - var score = new ScoreInfo { Ruleset = scoreProcessor.Ruleset.RulesetInfo }; + // baseScore and maxBaseScore are always exactly one judgement behind because the health processor is processed first (see: Player). + int imminentBaseScore = baseScore + Judgement.ToNumericResult(result.Type); + int imminentMaxBaseScore = maxBaseScore + Judgement.ToNumericResult(result.Judgement.MaxResult); - // This is super ugly, but if we don't do it this way we will not have the most recent result added to the accuracy value. - // Hopefully we can improve this in the future. - scoreProcessor.PopulateScore(score); - score.Statistics[result.Type]++; - - // Todo: - return 0; - // return scoreProcessor.ComputeAccuracy(score); + return imminentMaxBaseScore > 0 ? imminentBaseScore / (double)imminentMaxBaseScore : 1; } } } From 8b56a3f87d568dfd2c9fdf63b8bd534181b18d2f Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 18 May 2023 20:52:40 +0900 Subject: [PATCH 0909/1400] Remove ClassicScoreMultiplier and DefaultScoreProcessor --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Scoring/CatchScoreProcessor.cs | 8 +++---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 +- .../Scoring/ManiaScoreProcessor.cs | 8 +++---- osu.Game.Rulesets.Osu/OsuRuleset.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 8 +++---- .../Scoring/TaikoScoreProcessor.cs | 8 +++---- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Rulesets/Ruleset.cs | 21 +------------------ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 20 +++++++++++------- 10 files changed, 29 insertions(+), 52 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index e2255fa6f7..8a0b8250d5 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableCatchRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 9c5359ebeb..435b39150b 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -13,15 +13,13 @@ namespace osu.Game.Rulesets.Catch.Scoring private const int combo_cap = 200; private const double combo_base = 4; - protected override double ClassicScoreMultiplier => 28; - private double tinyDropletScale; private int maximumTinyDroplets; private int hitTinyDroplets; - public CatchScoreProcessor(Ruleset ruleset) - : base(ruleset) + public CatchScoreProcessor() + : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c6065c9b96..d324682989 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableManiaRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new ManiaHealthProcessor(drainStartTime); diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 19f8a4a639..1c55f9ffce 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -11,10 +11,8 @@ namespace osu.Game.Rulesets.Mania.Scoring { private const double combo_base = 4; - protected override double ClassicScoreMultiplier => 16; - - public ManiaScoreProcessor(Ruleset ruleset) - : base(ruleset) + public ManiaScoreProcessor() + : base(new ManiaRuleset()) { } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 497d405436..922594a93a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableOsuRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap, this); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index f8cbf1a641..d4677d92c1 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -8,10 +8,8 @@ namespace osu.Game.Rulesets.Osu.Scoring { public partial class OsuScoreProcessor : ScoreProcessor { - protected override double ClassicScoreMultiplier => 36; - - public OsuScoreProcessor(Ruleset ruleset) - : base(ruleset) + public OsuScoreProcessor() + : base(new OsuRuleset()) { } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 71eb0b1602..e2b442739b 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -12,10 +12,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring { private const double combo_base = 4; - protected override double ClassicScoreMultiplier => 22; - - public TaikoScoreProcessor(Ruleset ruleset) - : base(ruleset) + public TaikoScoreProcessor() + : base(new TaikoRuleset()) { } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 599d0dc33c..a35fdb890d 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Taiko { public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList? mods = null) => new DrawableTaikoRuleset(this, beatmap, mods); - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); + public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); public override HealthProcessor CreateHealthProcessor(double drainStartTime) => new TaikoHealthProcessor(); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 2e7a58b96c..a77068eb14 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -232,7 +232,7 @@ namespace osu.Game.Rulesets /// Creates a for this . /// /// The score processor. - public virtual ScoreProcessor CreateScoreProcessor() => new DefaultScoreProcessor(this); + public virtual ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); /// /// Creates a for this . @@ -381,23 +381,4 @@ namespace osu.Game.Rulesets /// public virtual RulesetSetupSection? CreateEditorSetupSection() => null; } - - public partial class DefaultScoreProcessor : ScoreProcessor - { - public DefaultScoreProcessor(Ruleset ruleset) - : base(ruleset) - { - } - - protected override double ComputeTotalScore() - { - return - (int)Math.Round - (( - 700000 * ComboPortion / MaxComboPortion + - 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + - BonusPortion - ) * ScoreMultiplier); - } - } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 1162b6ac04..4ded3d5d91 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -18,7 +18,7 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Scoring { - public abstract partial class ScoreProcessor : JudgementProcessor + public partial class ScoreProcessor : JudgementProcessor { public const double MAX_SCORE = 1000000; @@ -82,11 +82,6 @@ namespace osu.Game.Rulesets.Scoring /// public IReadOnlyList HitEvents => hitEvents; - /// - /// An arbitrary multiplier to scale scores in the scoring mode. - /// - protected virtual double ClassicScoreMultiplier => 36; - /// /// The ruleset this score processor is valid for. /// @@ -162,7 +157,7 @@ namespace osu.Game.Rulesets.Scoring private readonly List hitEvents = new List(); private HitObject? lastHitObject; - protected ScoreProcessor(Ruleset ruleset) + public ScoreProcessor(Ruleset ruleset) { Ruleset = ruleset; @@ -289,7 +284,16 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = (long)Math.Round(ComputeTotalScore()); } - protected abstract double ComputeTotalScore(); + protected virtual double ComputeTotalScore() + { + return + (int)Math.Round + (( + 700000 * ComboPortion / MaxComboPortion + + 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + BonusPortion + ) * ScoreMultiplier); + } /// /// Resets this ScoreProcessor to a default state. From 035d0d5c9ce27d79d84ffee0b24b89064699b538 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 13:16:57 +0900 Subject: [PATCH 0910/1400] Fix multiplayer leaderboard not working --- .../Spectator/SpectatorScoreProcessor.cs | 25 ++++++++++--------- .../HUD/MultiplayerGameplayLeaderboard.cs | 1 + 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs index 90b584a89f..3242e21994 100644 --- a/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs +++ b/osu.Game/Online/Spectator/SpectatorScoreProcessor.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; namespace osu.Game.Online.Spectator { @@ -46,7 +47,9 @@ namespace osu.Game.Online.Spectator /// /// The applied s. /// - public IReadOnlyList Mods => scoreProcessor?.Mods.Value ?? Array.Empty(); + public IReadOnlyList Mods => scoreInfo?.Mods ?? Array.Empty(); + + public Func GetDisplayScore => mode => scoreInfo?.GetDisplayScore(mode) ?? 0; private IClock? referenceClock; @@ -70,7 +73,6 @@ namespace osu.Game.Online.Spectator private readonly int userId; private SpectatorState? spectatorState; - private ScoreProcessor? scoreProcessor; private ScoreInfo? scoreInfo; public SpectatorScoreProcessor(int userId) @@ -94,19 +96,15 @@ namespace osu.Game.Online.Spectator { if (!spectatorStates.TryGetValue(userId, out var userState) || userState.BeatmapID == null || userState.RulesetID == null) { - scoreProcessor?.RemoveAndDisposeImmediately(); - scoreProcessor = null; scoreInfo = null; spectatorState = null; replayFrames.Clear(); return; } - if (scoreProcessor != null) + if (scoreInfo != null) return; - Debug.Assert(scoreInfo == null); - RulesetInfo? rulesetInfo = rulesetStore.GetRuleset(userState.RulesetID.Value); if (rulesetInfo == null) return; @@ -114,9 +112,11 @@ namespace osu.Game.Online.Spectator Ruleset ruleset = rulesetInfo.CreateInstance(); spectatorState = userState; - scoreInfo = new ScoreInfo { Ruleset = rulesetInfo }; - scoreProcessor = ruleset.CreateScoreProcessor(); - scoreProcessor.Mods.Value = userState.Mods.Select(m => m.ToMod(ruleset)).ToArray(); + scoreInfo = new ScoreInfo + { + Ruleset = rulesetInfo, + Mods = userState.Mods.Select(m => m.ToMod(ruleset)).ToArray() + }; } private void onNewFrames(int incomingUserId, FrameDataBundle bundle) @@ -126,7 +126,7 @@ namespace osu.Game.Online.Spectator Schedule(() => { - if (scoreProcessor == null) + if (scoreInfo == null) return; replayFrames.Add(new TimedFrame(bundle.Frames.First().Time, bundle.Header)); @@ -140,7 +140,6 @@ namespace osu.Game.Online.Spectator return; Debug.Assert(spectatorState != null); - Debug.Assert(scoreProcessor != null); int frameIndex = replayFrames.BinarySearch(new TimedFrame(ReferenceClock.CurrentTime)); if (frameIndex < 0) @@ -150,6 +149,7 @@ namespace osu.Game.Online.Spectator TimedFrame frame = replayFrames[frameIndex]; Debug.Assert(frame.Header != null); + scoreInfo.Accuracy = frame.Header.Accuracy; scoreInfo.MaxCombo = frame.Header.MaxCombo; scoreInfo.Statistics = frame.Header.Statistics; scoreInfo.MaximumStatistics = spectatorState.MaximumStatistics; @@ -157,6 +157,7 @@ namespace osu.Game.Online.Spectator Accuracy.Value = frame.Header.Accuracy; Combo.Value = frame.Header.Combo; + TotalScore.Value = frame.Header.TotalScore; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 620f3718c2..922def6174 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -98,6 +98,7 @@ namespace osu.Game.Screens.Play.HUD var trackedUser = UserScores[user.Id]; var leaderboardScore = Add(user, user.Id == api.LocalUser.Value.Id); + leaderboardScore.GetDisplayScore = trackedUser.ScoreProcessor.GetDisplayScore; leaderboardScore.Accuracy.BindTo(trackedUser.ScoreProcessor.Accuracy); leaderboardScore.TotalScore.BindTo(trackedUser.ScoreProcessor.TotalScore); leaderboardScore.Combo.BindTo(trackedUser.ScoreProcessor.Combo); From 4d14467d95cf3b0a1cab08b70a5408d587f056f7 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 13:23:04 +0900 Subject: [PATCH 0911/1400] Invert order of operations --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index e2b442739b..f86a6669ca 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -29,15 +29,15 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override void AddScoreChange(JudgementResult result) { var change = computeScoreChange(result); - BonusPortion += change.bonus; ComboPortion += change.combo; + BonusPortion += change.bonus; } protected override void RemoveScoreChange(JudgementResult result) { var change = computeScoreChange(result); - BonusPortion -= change.bonus; ComboPortion -= change.combo; + BonusPortion -= change.bonus; } private (double combo, double bonus) computeScoreChange(JudgementResult result) From 73544231de1c75263e0dc116890b5119350abc7a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 14:06:46 +0900 Subject: [PATCH 0912/1400] Fix TestSceneTopLocalRank --- osu.Game.Tests/Resources/TestResources.cs | 2 +- .../Visual/SongSelect/TestSceneTopLocalRank.cs | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index a2d81c0a75..a77dc8d49b 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -179,7 +179,7 @@ namespace osu.Game.Tests.Resources BeatmapHash = beatmap.Hash, Ruleset = beatmap.Ruleset, Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() }, - TotalScore = 2845370, + TotalScore = 284537, Accuracy = 0.95, MaxCombo = 999, Position = 1, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs index cf0de14541..79baae53e8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneTopLocalRank.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -12,7 +11,6 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Select.Carousel; using osu.Game.Tests.Resources; @@ -143,25 +141,20 @@ namespace osu.Game.Tests.Visual.SongSelect testScoreInfo.User = API.LocalUser.Value; testScoreInfo.Rank = ScoreRank.B; - testScoreInfo.TotalScore = scoreManager.GetTotalScore(testScoreInfo, ScoringMode.Classic); scoreManager.Import(testScoreInfo); }); AddUntilStep("B rank displayed", () => topLocalRank.DisplayedRank == ScoreRank.B); - AddStep("Add higher score for current user", () => + AddStep("Add higher-graded score for current user", () => { var testScoreInfo2 = TestResources.CreateTestScoreInfo(importedBeatmap); testScoreInfo2.User = API.LocalUser.Value; testScoreInfo2.Rank = ScoreRank.X; testScoreInfo2.Statistics = testScoreInfo2.MaximumStatistics; - testScoreInfo2.TotalScore = scoreManager.GetTotalScore(testScoreInfo2); - - // ensure second score has a total score (standardised) less than first one (classic) - // despite having better statistics, otherwise this test is pointless. - Debug.Assert(testScoreInfo2.TotalScore < testScoreInfo.TotalScore); + testScoreInfo2.TotalScore = testScoreInfo.TotalScore + 1; scoreManager.Import(testScoreInfo2); }); From 9a1d749020e365fe0519e5ca06a6b551370c4aa6 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 14:06:53 +0900 Subject: [PATCH 0913/1400] Fix TestSceneDrawableTaikoMascot --- .../Skinning/TestSceneDrawableTaikoMascot.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index e4e68c7207..dd8748f6e3 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -91,8 +91,9 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning { prepareDrawableRulesetAndBeatmap(false); - assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle); - assertStateAfterResult(new JudgementResult(new Hit.StrongNestedHit(), new TaikoStrongJudgement()) { Type = HitResult.IgnoreMiss }, TaikoMascotAnimationState.Idle); + var hit = new Hit(); + assertStateAfterResult(new JudgementResult(hit, new TaikoJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle); + assertStateAfterResult(new JudgementResult(new Hit.StrongNestedHit(hit), new TaikoStrongJudgement()) { Type = HitResult.IgnoreMiss }, TaikoMascotAnimationState.Idle); } [Test] From 7cbf48ffcff775dcfa77a5787fa72d0f89df7d8e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 14:09:19 +0900 Subject: [PATCH 0914/1400] Fix TestSceneScoring and incorrect combo calculations --- .../Scoring/CatchScoreProcessor.cs | 2 +- .../Scoring/ManiaScoreProcessor.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs | 11 ++++++----- osu.Game/Rulesets/Judgements/JudgementResult.cs | 5 +++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 ++++-- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 435b39150b..ae3966ccc5 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.Scoring if (result.Type.IsBonus()) return (0, Judgement.ToNumericResult(result.Type), 0); - return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0); + return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0); } protected override void Reset(bool storeResults) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 1c55f9ffce..4c8f8ef65e 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.Scoring if (result.Type.IsBonus()) return (0, Judgement.ToNumericResult(result.Type)); - return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(400, combo_base)), 0); + return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0); } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index f86a6669ca..2ecd962d72 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring if (result.Type.IsBonus()) return (0, hitValue); - return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAtJudgement, combo_base)), Math.Log(400, combo_base)), 0); + return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs index 8fff07e6d8..2b378c8013 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoring.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring.Legacy; using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -124,8 +125,8 @@ namespace osu.Game.Tests.Visual.Gameplay graphs.Clear(); legend.Clear(); - runForProcessor("lazer-standardised", Color4.YellowGreen, new ScoreProcessor(new OsuRuleset()) { Mode = { Value = ScoringMode.Standardised } }); - runForProcessor("lazer-classic", Color4.MediumPurple, new ScoreProcessor(new OsuRuleset()) { Mode = { Value = ScoringMode.Classic } }); + runForProcessor("lazer-standardised", Color4.YellowGreen, new ScoreProcessor(new OsuRuleset()), ScoringMode.Standardised); + runForProcessor("lazer-classic", Color4.MediumPurple, new ScoreProcessor(new OsuRuleset()), ScoringMode.Classic); runScoreV1(); runScoreV2(); @@ -218,7 +219,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); } - private void runForProcessor(string name, Color4 colour, ScoreProcessor processor) + private void runForProcessor(string name, Color4 colour, ScoreProcessor processor, ScoringMode mode) { int maxCombo = sliderMaxCombo.Current.Value; @@ -232,10 +233,10 @@ namespace osu.Game.Tests.Visual.Gameplay () => processor.ApplyResult(new OsuJudgementResult(new HitCircle(), new OsuJudgement()) { Type = HitResult.Great }), () => processor.ApplyResult(new OsuJudgementResult(new HitCircle(), new OsuJudgement()) { Type = HitResult.Ok }), () => processor.ApplyResult(new OsuJudgementResult(new HitCircle(), new OsuJudgement()) { Type = HitResult.Miss }), - () => (int)processor.TotalScore.Value); + () => processor.GetDisplayScore(mode)); } - private void runForAlgorithm(string name, Color4 colour, Action applyHit, Action applyNonPerfect, Action applyMiss, Func getTotalScore) + private void runForAlgorithm(string name, Color4 colour, Action applyHit, Action applyNonPerfect, Action applyMiss, Func getTotalScore) { int maxCombo = sliderMaxCombo.Current.Value; diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index bf29919e34..34d1f1f6e9 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -64,6 +64,11 @@ namespace osu.Game.Rulesets.Judgements /// public int ComboAtJudgement { get; internal set; } + /// + /// The combo after this occurred. + /// + public int ComboAfterJudgement { get; internal set; } + /// /// The highest combo achieved prior to this occurring. /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4ded3d5d91..b014b12297 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -204,6 +204,8 @@ namespace osu.Game.Rulesets.Scoring else if (result.Type.BreaksCombo()) Combo.Value = 0; + result.ComboAfterJudgement = Combo.Value; + if (result.Type.IsBasic()) CurrentBasicJudgements++; @@ -266,7 +268,7 @@ namespace osu.Game.Rulesets.Scoring BonusPortion += Judgement.ToNumericResult(result.Type); if (result.Type.AffectsCombo()) - ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); + ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d); } protected virtual void RemoveScoreChange(JudgementResult result) @@ -275,7 +277,7 @@ namespace osu.Game.Rulesets.Scoring BonusPortion -= Judgement.ToNumericResult(result.Type); if (result.Type.AffectsCombo()) - ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAtJudgement / 10d); + ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d); } private void updateScore() From 2ae34530f787e9420bdaefda85583bc165984075 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 14:14:34 +0900 Subject: [PATCH 0915/1400] Avoid NaN values during ApplyBeatmap processing() --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 3 ++- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 7 +++++-- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 7 +++++-- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 7 +++++-- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 +++++-- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index ae3966ccc5..dc6d5b28ee 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -25,12 +25,13 @@ namespace osu.Game.Rulesets.Catch.Scoring protected override double ComputeTotalScore() { + double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; const int tiny_droplets_portion = 400000; return ( - ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion + + ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + BonusPortion ) * ScoreMultiplier; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 4c8f8ef65e..544b9add32 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -18,9 +18,12 @@ namespace osu.Game.Rulesets.Mania.Scoring protected override double ComputeTotalScore() { + double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; + double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + return ( - 200000 * ComboPortion / MaxComboPortion + - 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + 200000 * comboRatio + + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio + BonusPortion ) * ScoreMultiplier; } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index d4677d92c1..edd0880271 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -15,9 +15,12 @@ namespace osu.Game.Rulesets.Osu.Scoring protected override double ComputeTotalScore() { + double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; + double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + return ( - 700000 * ComboPortion / MaxComboPortion + - 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + 700000 * comboRatio + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + BonusPortion ) * ScoreMultiplier; } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 2ecd962d72..32f4421ed2 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -19,9 +19,12 @@ namespace osu.Game.Rulesets.Taiko.Scoring protected override double ComputeTotalScore() { + double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; + double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + return ( - 250000 * ComboPortion / MaxComboPortion + - 750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + 250000 * comboRatio + + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio + BonusPortion ) * ScoreMultiplier; } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b014b12297..0ec9c884c3 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -288,11 +288,14 @@ namespace osu.Game.Rulesets.Scoring protected virtual double ComputeTotalScore() { + double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; + double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + return (int)Math.Round (( - 700000 * ComboPortion / MaxComboPortion + - 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + + 700000 * comboRatio + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + BonusPortion ) * ScoreMultiplier); } From d74bf2a096575a0f55f74f417724ad4d3593f8cf Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 14:37:26 +0900 Subject: [PATCH 0916/1400] Refactor for safety --- .../Scoring/CatchScoreProcessor.cs | 51 ++++---- .../Scoring/ManiaScoreProcessor.cs | 36 +----- .../Scoring/OsuScoreProcessor.cs | 13 +- .../Scoring/TaikoScoreProcessor.cs | 44 ++----- .../PerformanceBreakdownCalculator.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 117 ++++++++++-------- 6 files changed, 111 insertions(+), 152 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index dc6d5b28ee..c74d4b84e4 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -17,51 +17,48 @@ namespace osu.Game.Rulesets.Catch.Scoring private int maximumTinyDroplets; private int hitTinyDroplets; + private int maximumBasicJudgements; + private int currentBasicJudgements; public CatchScoreProcessor() : base(new CatchRuleset()) { } - protected override double ComputeTotalScore() + protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) { - double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; const int tiny_droplets_portion = 400000; - return ( - ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio + - tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + - BonusPortion - ) * ScoreMultiplier; + return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio + + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + + bonusPortion; } - protected override void AddScoreChange(JudgementResult result) + protected override double GetComboScoreChange(JudgementResult result) + => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)); + + protected override void ApplyScoreChange(JudgementResult result) { - var change = computeScoreChange(result); - ComboPortion += change.combo; - BonusPortion += change.bonus; - hitTinyDroplets += change.tinyDropletHits; + base.ApplyScoreChange(result); + + if (result.HitObject is TinyDroplet) + hitTinyDroplets++; + + if (result.Type.IsBasic()) + currentBasicJudgements++; } protected override void RemoveScoreChange(JudgementResult result) { - var change = computeScoreChange(result); - ComboPortion -= change.combo; - BonusPortion -= change.bonus; - hitTinyDroplets -= change.tinyDropletHits; - } + base.RemoveScoreChange(result); - private (double combo, double bonus, int tinyDropletHits) computeScoreChange(JudgementResult result) - { if (result.HitObject is TinyDroplet) - return (0, 0, 1); + hitTinyDroplets--; - if (result.Type.IsBonus()) - return (0, Judgement.ToNumericResult(result.Type), 0); - - return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0); + if (result.Type.IsBasic()) + currentBasicJudgements--; } protected override void Reset(bool storeResults) @@ -71,14 +68,16 @@ namespace osu.Game.Rulesets.Catch.Scoring if (storeResults) { maximumTinyDroplets = hitTinyDroplets; + maximumBasicJudgements = currentBasicJudgements; - if (maximumTinyDroplets + MaxBasicJudgements == 0) + if (maximumTinyDroplets + maximumBasicJudgements == 0) tinyDropletScale = 0; else - tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + MaxBasicJudgements); + tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + maximumBasicJudgements); } hitTinyDroplets = 0; + currentBasicJudgements = 0; } } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 544b9add32..214aded2d7 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -16,38 +16,14 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - protected override double ComputeTotalScore() + protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) { - double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; - double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; - - return ( - 200000 * comboRatio + - 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio + - BonusPortion - ) * ScoreMultiplier; + return 200000 * comboRatio + + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio + + bonusPortion; } - protected override void AddScoreChange(JudgementResult result) - { - var change = computeScoreChange(result); - ComboPortion += change.combo; - BonusPortion += change.bonus; - } - - protected override void RemoveScoreChange(JudgementResult result) - { - var change = computeScoreChange(result); - ComboPortion -= change.combo; - BonusPortion -= change.bonus; - } - - private (double combo, double bonus) computeScoreChange(JudgementResult result) - { - if (result.Type.IsBonus()) - return (0, Judgement.ToNumericResult(result.Type)); - - return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0); - } + protected override double GetComboScoreChange(JudgementResult result) + => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index edd0880271..5028d5b8d6 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -13,16 +13,11 @@ namespace osu.Game.Rulesets.Osu.Scoring { } - protected override double ComputeTotalScore() + protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) { - double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; - double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; - - return ( - 700000 * comboRatio + - 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + - BonusPortion - ) * ScoreMultiplier; + return 700000 * comboRatio + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + + bonusPortion; } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 32f4421ed2..e0f83505cf 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -17,46 +17,28 @@ namespace osu.Game.Rulesets.Taiko.Scoring { } - protected override double ComputeTotalScore() + protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) { - double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; - double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; - - return ( - 250000 * comboRatio + - 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio + - BonusPortion - ) * ScoreMultiplier; + return 250000 * comboRatio + + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio + + bonusPortion; } - protected override void AddScoreChange(JudgementResult result) + protected override double GetBonusScoreChange(JudgementResult result) => base.GetBonusScoreChange(result) * strongScaleValue(result); + + protected override double GetComboScoreChange(JudgementResult result) { - var change = computeScoreChange(result); - ComboPortion += change.combo; - BonusPortion += change.bonus; + return Judgement.ToNumericResult(result.Type) + * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)) + * strongScaleValue(result); } - protected override void RemoveScoreChange(JudgementResult result) + private double strongScaleValue(JudgementResult result) { - var change = computeScoreChange(result); - ComboPortion -= change.combo; - BonusPortion -= change.bonus; - } - - private (double combo, double bonus) computeScoreChange(JudgementResult result) - { - double hitValue = Judgement.ToNumericResult(result.Type); - if (result.HitObject is StrongNestedHitObject strong) - { - double strongBonus = strong.Parent is DrumRollTick ? 3 : 7; - hitValue *= strongBonus; - } + return strong.Parent is DrumRollTick ? 3 : 7; - if (result.Type.IsBonus()) - return (0, hitValue); - - return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0); + return 1; } } } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 3dd7f934a8..64a04f896f 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Difficulty ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor(); scoreProcessor.Mods.Value = perfectPlay.Mods; scoreProcessor.ApplyBeatmap(playableBeatmap); - perfectPlay.TotalScore = scoreProcessor.MaxTotalScore; + perfectPlay.TotalScore = scoreProcessor.MaximumTotalScore; // compute rank achieved // default to SS, then adjust the rank with mods diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0ec9c884c3..a94ee9c181 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -90,10 +90,18 @@ namespace osu.Game.Rulesets.Scoring /// /// The maximum achievable total score. /// - public long MaxTotalScore { get; private set; } + public long MaximumTotalScore { get; private set; } /// - /// The sum of all accuracy-affecting judgements at the current time. + /// The maximum sum of accuracy-affecting judgements at the current point in time. + /// + /// + /// Used to compute accuracy. + /// + private double currentMaximumBaseScore; + + /// + /// The sum of all accuracy-affecting judgements at the current point in time. /// /// /// Used to compute accuracy. @@ -101,42 +109,34 @@ namespace osu.Game.Rulesets.Scoring private double currentBaseScore; /// - /// The maximum sum of accuracy-affecting judgements at the current time. + /// The count of all basic judgements in the beatmap. /// - /// - /// Used to compute accuracy. - /// - private double currentMaxBaseScore; + private int maximumCountBasicJudgements; /// - /// The total count of basic judgements in the beatmap. + /// The count of basic judgements at the current point in time. /// - protected int MaxBasicJudgements { get; private set; } + private int currentCountBasicJudgements; /// - /// The current count of basic judgements by the player. + /// The maximum combo score in the beatmap. /// - protected int CurrentBasicJudgements { get; private set; } + private double maximumComboPortion; /// - /// The current combo score. + /// The combo score at the current point in time. /// - protected double ComboPortion { get; set; } + private double currentComboPortion; /// - /// The maximum achievable combo score. + /// The bonus score at the current point in time. /// - protected double MaxComboPortion { get; private set; } - - /// - /// The current bonus score. - /// - protected double BonusPortion { get; set; } + private double currentBonusPortion; /// /// The total score multiplier. /// - protected double ScoreMultiplier { get; private set; } = 1; + private double scoreMultiplier = 1; public Dictionary MaximumStatistics { @@ -171,10 +171,10 @@ namespace osu.Game.Rulesets.Scoring Mods.ValueChanged += mods => { - ScoreMultiplier = 1; + scoreMultiplier = 1; foreach (var m in mods.NewValue) - ScoreMultiplier *= m.ScoreMultiplier; + scoreMultiplier *= m.ScoreMultiplier; updateScore(); }; @@ -207,15 +207,21 @@ namespace osu.Game.Rulesets.Scoring result.ComboAfterJudgement = Combo.Value; if (result.Type.IsBasic()) - CurrentBasicJudgements++; + currentCountBasicJudgements++; if (result.Type.AffectsAccuracy()) { - currentMaxBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); + currentMaximumBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore += Judgement.ToNumericResult(result.Type); } - AddScoreChange(result); + if (result.Type.IsBonus()) + currentBonusPortion += GetBonusScoreChange(result); + + if (result.Type.AffectsCombo()) + currentComboPortion += GetComboScoreChange(result); + + ApplyScoreChange(result); hitEvents.Add(CreateHitEvent(result)); lastHitObject = result.HitObject; @@ -245,14 +251,20 @@ namespace osu.Game.Rulesets.Scoring return; if (result.Type.IsBasic()) - CurrentBasicJudgements--; + currentCountBasicJudgements--; if (result.Type.AffectsAccuracy()) { - currentMaxBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); + currentMaximumBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore -= Judgement.ToNumericResult(result.Type); } + if (result.Type.IsBonus()) + currentBonusPortion -= GetBonusScoreChange(result); + + if (result.Type.AffectsCombo()) + currentComboPortion -= GetComboScoreChange(result); + RemoveScoreChange(result); Debug.Assert(hitEvents.Count > 0); @@ -262,42 +274,37 @@ namespace osu.Game.Rulesets.Scoring updateScore(); } - protected virtual void AddScoreChange(JudgementResult result) - { - if (result.Type.IsBonus()) - BonusPortion += Judgement.ToNumericResult(result.Type); + protected virtual double GetBonusScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type); - if (result.Type.AffectsCombo()) - ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d); + protected virtual double GetComboScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d); + + protected virtual void ApplyScoreChange(JudgementResult result) + { } protected virtual void RemoveScoreChange(JudgementResult result) { - if (result.Type.IsBonus()) - BonusPortion -= Judgement.ToNumericResult(result.Type); - - if (result.Type.AffectsCombo()) - ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d); } private void updateScore() { - Accuracy.Value = currentMaxBaseScore > 0 ? currentBaseScore / currentMaxBaseScore : 1; - TotalScore.Value = (long)Math.Round(ComputeTotalScore()); + Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1; + + double comboRatio = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; + double accuracyRatio = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1; + + TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboRatio, accuracyRatio, currentBonusPortion) * scoreMultiplier); } - protected virtual double ComputeTotalScore() + protected virtual double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) { - double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; - double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; - return (int)Math.Round (( 700000 * comboRatio + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + - BonusPortion - ) * ScoreMultiplier); + bonusPortion + ) * scoreMultiplier); } /// @@ -313,22 +320,22 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { - MaxComboPortion = ComboPortion; - MaxBasicJudgements = CurrentBasicJudgements; + maximumComboPortion = currentComboPortion; + maximumCountBasicJudgements = currentCountBasicJudgements; maximumResultCounts.Clear(); maximumResultCounts.AddRange(scoreResultCounts); - MaxTotalScore = TotalScore.Value; + MaximumTotalScore = TotalScore.Value; } scoreResultCounts.Clear(); currentBaseScore = 0; - currentMaxBaseScore = 0; - CurrentBasicJudgements = 0; - ComboPortion = 0; - BonusPortion = 0; + currentMaximumBaseScore = 0; + currentCountBasicJudgements = 0; + currentComboPortion = 0; + currentBonusPortion = 0; TotalScore.Value = 0; Accuracy.Value = 1; @@ -338,7 +345,7 @@ namespace osu.Game.Rulesets.Scoring HighestCombo.Value = 0; currentBaseScore = 0; - currentMaxBaseScore = 0; + currentMaximumBaseScore = 0; } /// From 6c6f8621c1ae5b7ea26116b3883c9ae9683b8bde Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 16:25:52 +0900 Subject: [PATCH 0917/1400] Add score processor statistics to replay header --- .../Scoring/CatchScoreProcessor.cs | 17 +++++++ osu.Game/Online/Spectator/FrameDataBundle.cs | 5 ++- osu.Game/Online/Spectator/FrameHeader.cs | 45 ++++++++++++------- osu.Game/Online/Spectator/SpectatorClient.cs | 6 ++- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 27 +++++++++-- .../Visual/Spectator/TestSpectatorClient.cs | 7 ++- 6 files changed, 83 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index c74d4b84e4..63937600bb 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -79,5 +80,21 @@ namespace osu.Game.Rulesets.Catch.Scoring hitTinyDroplets = 0; currentBasicJudgements = 0; } + + public override void WriteScoreProcessorStatistics(IDictionary statistics) + { + base.WriteScoreProcessorStatistics(statistics); + + statistics.Add(nameof(hitTinyDroplets), hitTinyDroplets); + statistics.Add(nameof(currentBasicJudgements), currentBasicJudgements); + } + + public override void ReadScoreProcessorStatistics(IReadOnlyDictionary statistics) + { + base.ReadScoreProcessorStatistics(statistics); + + hitTinyDroplets = (int)statistics.GetValueOrDefault(nameof(hitTinyDroplets), 0); + currentBasicJudgements = (int)statistics.GetValueOrDefault(nameof(currentBasicJudgements), 0); + } } } diff --git a/osu.Game/Online/Spectator/FrameDataBundle.cs b/osu.Game/Online/Spectator/FrameDataBundle.cs index 97ae468875..b936847434 100644 --- a/osu.Game/Online/Spectator/FrameDataBundle.cs +++ b/osu.Game/Online/Spectator/FrameDataBundle.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using MessagePack; using Newtonsoft.Json; using osu.Game.Replays.Legacy; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Online.Spectator @@ -20,10 +21,10 @@ namespace osu.Game.Online.Spectator [Key(1)] public IList Frames { get; set; } - public FrameDataBundle(ScoreInfo score, IList frames) + public FrameDataBundle(ScoreInfo score, ScoreProcessor scoreProcessor, IList frames) { Frames = frames; - Header = new FrameHeader(score); + Header = new FrameHeader(score, scoreProcessor); } [JsonConstructor] diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index 4d1ff23530..baebb28e4f 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -15,66 +15,77 @@ namespace osu.Game.Online.Spectator public class FrameHeader { /// - /// The current accuracy of the score. + /// The total score. /// [Key(0)] + public long TotalScore { get; set; } + + /// + /// The current accuracy of the score. + /// + [Key(1)] public double Accuracy { get; set; } /// /// The current combo of the score. /// - [Key(1)] + [Key(2)] public int Combo { get; set; } /// /// The maximum combo achieved up to the current point in time. /// - [Key(2)] + [Key(3)] public int MaxCombo { get; set; } /// /// Cumulative hit statistics. /// - [Key(3)] + [Key(4)] public Dictionary Statistics { get; set; } + /// + /// Additional statistics that guides the score processor to calculate the correct score for this frame. + /// + [Key(5)] + public Dictionary ScoreProcessorStatistics { get; set; } + /// /// The time at which this frame was received by the server. /// - [Key(4)] + [Key(6)] public DateTimeOffset ReceivedTime { get; set; } - /// - /// The total score. - /// - [Key(5)] - public long TotalScore { get; set; } - /// /// Construct header summary information from a point-in-time reference to a score which is actively being played. /// /// The score for reference. - public FrameHeader(ScoreInfo score) + /// The score processor for reference. + public FrameHeader(ScoreInfo score, ScoreProcessor scoreProcessor) { + TotalScore = score.TotalScore; + Accuracy = score.Accuracy; Combo = score.Combo; MaxCombo = score.MaxCombo; - Accuracy = score.Accuracy; - TotalScore = score.TotalScore; // copy for safety Statistics = new Dictionary(score.Statistics); + + ScoreProcessorStatistics = new Dictionary(); + scoreProcessor.WriteScoreProcessorStatistics(ScoreProcessorStatistics); } [JsonConstructor] [SerializationConstructor] - public FrameHeader(double accuracy, int combo, int maxCombo, Dictionary statistics, DateTimeOffset receivedTime, long totalScore) + public FrameHeader(long totalScore, double accuracy, int combo, int maxCombo, Dictionary statistics, Dictionary scoreProcessorStatistics, DateTimeOffset receivedTime) { + TotalScore = totalScore; + Accuracy = accuracy; Combo = combo; MaxCombo = maxCombo; - Accuracy = accuracy; Statistics = statistics; + ScoreProcessorStatistics = scoreProcessorStatistics; ReceivedTime = receivedTime; - TotalScore = totalScore; } } } diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 55ec75f4ce..89da8b9d32 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -16,6 +16,7 @@ using osu.Game.Online.API; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play; @@ -82,6 +83,7 @@ namespace osu.Game.Online.Spectator private IBeatmap? currentBeatmap; private Score? currentScore; private long? currentScoreToken; + private ScoreProcessor? currentScoreProcessor; private readonly Queue pendingFrameBundles = new Queue(); @@ -192,6 +194,7 @@ namespace osu.Game.Online.Spectator currentBeatmap = state.Beatmap; currentScore = score; currentScoreToken = scoreToken; + currentScoreProcessor = state.ScoreProcessor; BeginPlayingInternal(currentScoreToken, currentState); }); @@ -302,9 +305,10 @@ namespace osu.Game.Online.Spectator return; Debug.Assert(currentScore != null); + Debug.Assert(currentScoreProcessor != null); var frames = pendingFrames.ToArray(); - var bundle = new FrameDataBundle(currentScore.ScoreInfo, frames); + var bundle = new FrameDataBundle(currentScore.ScoreInfo, currentScoreProcessor, frames); pendingFrames.Clear(); lastPurgeTime = Time.Current; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a94ee9c181..0244e7f5e3 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -394,19 +394,34 @@ namespace osu.Game.Rulesets.Scoring Combo.Value = frame.Header.Combo; HighestCombo.Value = frame.Header.MaxCombo; + TotalScore.Value = frame.Header.TotalScore; scoreResultCounts.Clear(); scoreResultCounts.AddRange(frame.Header.Statistics); + ReadScoreProcessorStatistics(frame.Header.ScoreProcessorStatistics); + updateScore(); OnResetFromReplayFrame?.Invoke(); } - protected override void Dispose(bool isDisposing) + public virtual void WriteScoreProcessorStatistics(IDictionary statistics) { - base.Dispose(isDisposing); - hitEvents.Clear(); + statistics.Add(nameof(currentMaximumBaseScore), currentMaximumBaseScore); + statistics.Add(nameof(currentBaseScore), currentBaseScore); + statistics.Add(nameof(currentCountBasicJudgements), currentCountBasicJudgements); + statistics.Add(nameof(currentComboPortion), currentComboPortion); + statistics.Add(nameof(currentBonusPortion), currentBonusPortion); + } + + public virtual void ReadScoreProcessorStatistics(IReadOnlyDictionary statistics) + { + currentMaximumBaseScore = (double)statistics.GetValueOrDefault(nameof(currentMaximumBaseScore), 0); + currentBaseScore = (double)statistics.GetValueOrDefault(nameof(currentBaseScore), 0); + currentCountBasicJudgements = (int)statistics.GetValueOrDefault(nameof(currentCountBasicJudgements), 0); + currentComboPortion = (double)statistics.GetValueOrDefault(nameof(currentComboPortion), 0); + currentBonusPortion = (double)statistics.GetValueOrDefault(nameof(currentBonusPortion), 0); } #region Static helper methods @@ -464,6 +479,12 @@ namespace osu.Game.Rulesets.Scoring } #endregion + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + hitEvents.Clear(); + } } public enum ScoringMode diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index 1db35b3aaa..305a615102 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -12,7 +12,9 @@ using osu.Framework.Utils; using osu.Game.Online.API; using osu.Game.Online.Spectator; using osu.Game.Replays.Legacy; +using osu.Game.Rulesets; using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; namespace osu.Game.Tests.Visual.Spectator @@ -44,6 +46,9 @@ namespace osu.Game.Tests.Visual.Spectator [Resolved] private IAPIProvider api { get; set; } = null!; + [Resolved] + private RulesetStore rulesetStore { get; set; } = null!; + public TestSpectatorClient() { OnNewFrames += (i, bundle) => lastReceivedUserFrames[i] = bundle.Frames[^1]; @@ -119,7 +124,7 @@ namespace osu.Game.Tests.Visual.Spectator if (frames.Count == 0) return; - var bundle = new FrameDataBundle(new ScoreInfo { Combo = currentFrameIndex }, frames.ToArray()); + var bundle = new FrameDataBundle(new ScoreInfo { Combo = currentFrameIndex }, new ScoreProcessor(rulesetStore.GetRuleset(0)!.CreateInstance()), frames.ToArray()); ((ISpectatorClient)this).UserSentFrames(userId, bundle); frames.Clear(); From 30a296bd094604d5f2c7a2c3ddc1e9d03c60fa80 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 19 May 2023 17:27:02 +0900 Subject: [PATCH 0918/1400] Rename parameters --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 4 ++-- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 6 +++--- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 6 +++--- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 6 +++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 63937600bb..9d5fc553de 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -26,13 +26,13 @@ namespace osu.Game.Rulesets.Catch.Scoring { } - protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; const int tiny_droplets_portion = 400000; - return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio + return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboProgress + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + bonusPortion; } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 214aded2d7..3341f834dd 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -16,10 +16,10 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - return 200000 * comboRatio - + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio + return 200000 * comboProgress + + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyProgress + bonusPortion; } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 5028d5b8d6..ab07ac3e9d 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -13,10 +13,10 @@ namespace osu.Game.Rulesets.Osu.Scoring { } - protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - return 700000 * comboRatio - + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + return 700000 * comboProgress + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyProgress + bonusPortion; } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index e0f83505cf..a77e6db6f3 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -17,10 +17,10 @@ namespace osu.Game.Rulesets.Taiko.Scoring { } - protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - return 250000 * comboRatio - + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio + return 250000 * comboProgress + + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyProgress + bonusPortion; } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0244e7f5e3..d0bbe863fb 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -296,13 +296,13 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboRatio, accuracyRatio, currentBonusPortion) * scoreMultiplier); } - protected virtual double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion) + protected virtual double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { return (int)Math.Round (( - 700000 * comboRatio + - 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + + 700000 * comboProgress + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyProgress + bonusPortion ) * scoreMultiplier); } From e8cb19e40aead0744621afe052944f57fa81ea02 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 19 May 2023 17:49:26 +0900 Subject: [PATCH 0919/1400] Pin builds to .NET 6 As more things move to having the 7 SDK installed, let's pin for now. This helps with mobile build scenarios, which fall over on the new SDKs and require further attention. --- global.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 global.json diff --git a/global.json b/global.json new file mode 100644 index 0000000000..5dcd5f425a --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "6.0.100", + "rollForward": "latestFeature" + } +} + From 25d72d370e95c8e0722bbccb96b0cc01a78e61f9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 20 May 2023 00:24:43 +0900 Subject: [PATCH 0920/1400] Always add non-bonus change to combo portion --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index d0bbe863fb..f2b1607f5e 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -217,8 +217,7 @@ namespace osu.Game.Rulesets.Scoring if (result.Type.IsBonus()) currentBonusPortion += GetBonusScoreChange(result); - - if (result.Type.AffectsCombo()) + else currentComboPortion += GetComboScoreChange(result); ApplyScoreChange(result); @@ -261,8 +260,7 @@ namespace osu.Game.Rulesets.Scoring if (result.Type.IsBonus()) currentBonusPortion -= GetBonusScoreChange(result); - - if (result.Type.AffectsCombo()) + else currentComboPortion -= GetComboScoreChange(result); RemoveScoreChange(result); From 8e0a97ca4965a5d058fc16abb03ec9bc91ad0067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 20 May 2023 18:02:12 +0200 Subject: [PATCH 0921/1400] Remove usage of `HasSubmenu` Property has been removed in the appropriate framework-side PR and instead folded into `IsActionable`. See: https://github.com/ppy/osu-framework/pull/5658#discussion_r1114834647 --- osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs index 0adff11342..eb046932e6 100644 --- a/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableOsuMenuItem.cs @@ -77,12 +77,10 @@ namespace osu.Game.Graphics.UserInterface private void updateState() { - bool enabledState = IsActionable || HasSubmenu; + hoverClickSounds.Enabled.Value = IsActionable; + Alpha = IsActionable ? 1 : 0.2f; - hoverClickSounds.Enabled.Value = enabledState; - Alpha = enabledState ? 1 : 0.2f; - - if (IsHovered && enabledState) + if (IsHovered && IsActionable) { text.BoldText.FadeIn(transition_length, Easing.OutQuint); text.NormalText.FadeOut(transition_length, Easing.OutQuint); From a677d87d39b49e1ba9f471f720d61c292d9c3547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 20 May 2023 19:29:59 +0200 Subject: [PATCH 0922/1400] Touch up inline comments --- osu.Game/Online/Chat/MessageNotifier.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs index cb29fc4535..52bdd36169 100644 --- a/osu.Game/Online/Chat/MessageNotifier.cs +++ b/osu.Game/Online/Chat/MessageNotifier.cs @@ -93,7 +93,7 @@ namespace osu.Game.Online.Chat if (channel == null) return; - // Only send notifications, if ChatOverlay and the target channel aren't visible, or if the window is unfocused + // Only send notifications if ChatOverlay or the target channel aren't visible, or if the window is unfocused if (chatOverlay.IsPresent && channelManager.CurrentChannel.Value == channel && host.IsActive.Value) return; @@ -103,7 +103,7 @@ namespace osu.Game.Online.Chat if (message.Id <= channel.LastReadId) return; - // ignore notifications triggered by your own chat messages + // ignore notifications triggered by local user's own chat messages if (message.Sender.Id == localUser.Value.Id) continue; From ec5f0bbf421828ee8d3ab42ddcec3ab2679baf1c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 20 May 2023 16:29:49 -0700 Subject: [PATCH 0923/1400] Fix clicking area of news sidebar post links Side effect is that the hover color is yellow and pressing it opens an external dialog, but those are temporary (pending implementation of link underline to make `Light1` hover more readable and set at a higher level and news pages). --- .../Overlays/News/Sidebar/MonthSection.cs | 29 +++---------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index 30d29048ba..4dccc07eff 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -20,7 +20,7 @@ using System.Diagnostics; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Platform; +using osu.Game.Online.Chat; namespace osu.Game.Overlays.News.Sidebar { @@ -123,35 +123,14 @@ namespace osu.Game.Overlays.News.Sidebar } } - private partial class PostButton : OsuHoverContainer + private partial class PostButton : LinkFlowContainer { - protected override IEnumerable EffectTargets => new[] { text }; - - private readonly TextFlowContainer text; - private readonly APINewsPost post; - public PostButton(APINewsPost post) + : base(t => t.Font = OsuFont.GetFont(size: 12)) { - this.post = post; - RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Child = text = new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 12)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Text = post.Title - }; - } - - [BackgroundDependencyLoader] - private void load(OverlayColourProvider overlayColours, GameHost host) - { - IdleColour = overlayColours.Light2; - HoverColour = overlayColours.Light1; - - TooltipText = "view in browser"; - Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug); + AddLink(post.Title, LinkAction.External, "https://osu.ppy.sh/home/news/" + post.Slug, "view in browser"); } } From 8aefb62532aebf3430f19aae09bbcedce8fce7c7 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 20 May 2023 16:38:56 -0700 Subject: [PATCH 0924/1400] Rename `PostButton` to `PostLink` --- osu.Game/Overlays/News/Sidebar/MonthSection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index 4dccc07eff..b586d156ad 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.News.Sidebar new PostsContainer { Expanded = { BindTarget = Expanded }, - Children = posts.Select(p => new PostButton(p)).ToArray() + Children = posts.Select(p => new PostLink(p)).ToArray() } } }; @@ -123,9 +123,9 @@ namespace osu.Game.Overlays.News.Sidebar } } - private partial class PostButton : LinkFlowContainer + private partial class PostLink : LinkFlowContainer { - public PostButton(APINewsPost post) + public PostLink(APINewsPost post) : base(t => t.Font = OsuFont.GetFont(size: 12)) { RelativeSizeAxes = Axes.X; From 67bf1b4dfe5117cbf1e7a30b1a98caf271f8d637 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 21 May 2023 11:05:01 +0300 Subject: [PATCH 0925/1400] Select/deselect first visible mod when `GlobalAction.Select` is triggered --- .../UserInterface/TestSceneModSelectOverlay.cs | 18 ++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 18 ++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index ea81f9c96e..499a30f0dc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -468,6 +468,24 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).IsValid); } + [Test] + public void TestFirstModSelectDeselect() + { + createScreen(); + + AddStep("apply search", () => modSelectOverlay.SearchTerm = "HD"); + + AddStep("press enter", () => InputManager.Key(Key.Enter)); + AddAssert("hidden selected", () => getPanelForMod(typeof(OsuModHidden)).Active.Value); + + AddStep("press enter again", () => InputManager.Key(Key.Enter)); + AddAssert("hidden deselected", () => !getPanelForMod(typeof(OsuModHidden)).Active.Value); + + AddStep("clear search", () => modSelectOverlay.SearchTerm = string.Empty); + AddStep("press enter", () => InputManager.Key(Key.Enter)); + AddAssert("mod select hidden", () => modSelectOverlay.State.Value == Visibility.Hidden); + } + [Test] public void TestSearchFocusChange() { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ace5bf71d1..eb0e797eac 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -612,10 +612,24 @@ namespace osu.Game.Overlays.Mods // This is handled locally here because this overlay is being registered at the game level // and therefore takes away keyboard focus from the screen stack. case GlobalAction.ToggleModSelection: + // Pressing toggle should completely hide the overlay in one shot. + hideOverlay(true); + return true; + case GlobalAction.Select: { - // Pressing toggle or select should completely hide the overlay in one shot. - hideOverlay(true); + // Pressing select should select first filtered mod or completely hide the overlay in one shot if search term is empty. + if (string.IsNullOrEmpty(SearchTerm)) + { + hideOverlay(true); + return true; + } + + ModState? firstMod = columnFlow.Columns.OfType().FirstOrDefault(m => m.IsPresent)?.AvailableMods.FirstOrDefault(x => x.IsValid); + + if (firstMod is not null) + firstMod.Active.Value = !firstMod.Active.Value; + return true; } } From 5229cf7343ea6d562598fbbdf67a6c2e19bb51b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 16:47:16 +0200 Subject: [PATCH 0926/1400] Add failing test cases for drum roll/swell sample playback --- .../TestSceneDrumSampleTriggerSource.cs | 273 ++++++++++++++++++ .../UI/GameplaySampleTriggerSource.cs | 2 +- 2 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs new file mode 100644 index 0000000000..0c8f18badd --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -0,0 +1,273 @@ +// 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 System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public partial class TestSceneDrumSampleTriggerSource : OsuTestScene + { + private readonly ManualClock manualClock = new ManualClock(); + + [Cached(typeof(IScrollingInfo))] + private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo + { + Direction = { Value = ScrollingDirection.Left }, + TimeRange = { Value = 200 }, + }; + + private ScrollingHitObjectContainer hitObjectContainer = null!; + private TestDrumSampleTriggerSource triggerSource = null!; + + [SetUp] + public void SetUp() => Schedule(() => + { + hitObjectContainer = new ScrollingHitObjectContainer(); + manualClock.CurrentTime = 0; + + Child = new Container + { + Clock = new FramedClock(manualClock), + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + hitObjectContainer, + triggerSource = new TestDrumSampleTriggerSource(hitObjectContainer) + } + }; + }); + + [Test] + public void TestNormalHit() + { + AddStep("add hit with normal samples", () => + { + var hit = new Hit + { + StartTime = 100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) + } + }; + hit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableHit = new DrawableHit(hit); + hitObjectContainer.Add(drawableHit); + }); + + AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + + AddStep("seek past hit", () => manualClock.CurrentTime = 200); + AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + } + + [Test] + public void TestSoftHit() + { + AddStep("add hit with soft samples", () => + { + var hit = new Hit + { + StartTime = 100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft") + } + }; + hit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableHit = new DrawableHit(hit); + hitObjectContainer.Add(drawableHit); + }); + + AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + + AddStep("seek past hit", () => manualClock.CurrentTime = 200); + AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + } + + [Test] + public void TestNormalDrumRoll() + { + AddStep("add drum roll with normal samples", () => + { + var drumRoll = new DrumRoll + { + StartTime = 100, + EndTime = 1100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) + } + }; + drumRoll.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableDrumRoll = new DrawableDrumRoll(drumRoll); + hitObjectContainer.Add(drawableDrumRoll); + }); + + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + + AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + + AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + } + + [Test] + public void TestSoftDrumRoll() + { + AddStep("add drum roll with soft samples", () => + { + var drumRoll = new DrumRoll + { + StartTime = 100, + EndTime = 1100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft") + } + }; + drumRoll.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableDrumRoll = new DrawableDrumRoll(drumRoll); + hitObjectContainer.Add(drawableDrumRoll); + }); + + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + + AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + + AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + } + + [Test] + public void TestNormalSwell() + { + AddStep("add swell with normal samples", () => + { + var swell = new Swell + { + StartTime = 100, + EndTime = 1100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) + } + }; + swell.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableSwell = new DrawableSwell(swell); + hitObjectContainer.Add(drawableSwell); + }); + + AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + + AddStep("seek to middle of swell", () => manualClock.CurrentTime = 600); + AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + + AddStep("seek past swell", () => manualClock.CurrentTime = 1200); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); + } + + [Test] + public void TestDrumSwell() + { + AddStep("add swell with drum samples", () => + { + var swell = new Swell() + { + StartTime = 100, + EndTime = 1100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "drum") + } + }; + swell.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableSwell = new DrawableSwell(swell); + hitObjectContainer.Add(drawableSwell); + }); + + AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + + AddStep("seek to middle of swell", () => manualClock.CurrentTime = 600); + AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + + AddStep("seek past swell", () => manualClock.CurrentTime = 1200); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + } + + private void checkSound(HitType hitType, string expectedName, string expectedBank) + { + AddStep($"hit {hitType}", () => triggerSource.Play(hitType)); + AddAssert($"last played sample is {expectedName}", () => triggerSource.LastPlayedSamples!.OfType().Single().Name, () => Is.EqualTo(expectedName)); + AddAssert($"last played sample has {expectedBank} bank", () => triggerSource.LastPlayedSamples!.OfType().Single().Bank, () => Is.EqualTo(expectedBank)); + } + + private partial class TestDrumSampleTriggerSource : DrumSampleTriggerSource + { + public ISampleInfo[]? LastPlayedSamples { get; private set; } + + public TestDrumSampleTriggerSource(HitObjectContainer hitObjectContainer) + : base(hitObjectContainer) + { + } + + protected override void PlaySamples(ISampleInfo[] samples) + { + base.PlaySamples(samples); + LastPlayedSamples = samples; + } + + public new HitObject GetMostValidObject() => base.GetMostValidObject(); + } + } +} diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index d4510a4519..fbb7a20a5d 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.UI PlaySamples(samples); } - protected void PlaySamples(ISampleInfo[] samples) => Schedule(() => + protected virtual void PlaySamples(ISampleInfo[] samples) => Schedule(() => { var hitSound = getNextSample(); hitSound.Samples = samples; From 6d325651dcca275091d51bbfbad3e59fa4ce4dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 16:49:17 +0200 Subject: [PATCH 0927/1400] Propagate samples to drum roll/swell ticks for correct playback In d97daee96be2c10f90709cc30beceb1f369ae225, `DrumSampleTriggerSource` was changed such that in order to play sounds for the user's inputs, the bank of the normal sound would always be used. The problem is that in the case of taiko objects which have nested objects (swells and drum rolls), the samples were not propagated fully (drum rolls, where only the finish sample was kept, for the purposes of determining strongability), or not propagated at all (swells) to ticks. As ticks of both objects are valid return values of `GetMostValidHitObject()`, this would lead to the drum making no sounds if the next object was a drum roll or swell, until that drum roll or swell was completed. To fix, propagate the full set of samples, so that `DrumSampleTriggerSource` can retrieve the normal sound to copy the bank from. Note that this may not necessarily reproduce prior behaviour. This is because it is not guaranteed that all realised samples for a given hitobject have the same bank - some may have been overriden locally on a given hitobject. Previously, the bank would have been retrieved from the sample control point, wherein there is only one possible bank to use; however, when deciding the sound to play on the basis of a constructed hitobject, it is possible that there are cases wherein the hitnormal sample was overridden on that given hitobject, and in such cases, this PR would make samples _play_, but not necessarily the _same_ samples as prior to #23308. If that turns out to be the case, this will have to be revisited. --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 +--- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index b4a12fd314..ba68967fbe 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -3,11 +3,9 @@ #nullable disable -using System.Linq; using osu.Game.Rulesets.Objects.Types; using System.Threading; using osu.Framework.Bindables; -using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; @@ -98,7 +96,7 @@ namespace osu.Game.Rulesets.Taiko.Objects TickSpacing = tickSpacing, StartTime = t, IsStrong = IsStrong, - Samples = Samples.Where(s => s.Name == HitSampleInfo.HIT_FINISH).ToList() + Samples = Samples }); first = false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index cb91c46b4d..9ad783ba7e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -33,7 +33,10 @@ namespace osu.Game.Rulesets.Taiko.Objects for (int i = 0; i < RequiredHits; i++) { cancellationToken.ThrowIfCancellationRequested(); - AddNested(new SwellTick()); + AddNested(new SwellTick + { + Samples = Samples + }); } } From 812df9d652e73c55565a0667f09f8e0e480fcb29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 17:14:24 +0200 Subject: [PATCH 0928/1400] Add failing test cases for strong object sample playback --- .../TestSceneDrumSampleTriggerSource.cs | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index 0c8f18badd..74da69e3eb 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -109,6 +109,35 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); } + [Test] + public void TestDrumStrongHit() + { + AddStep("add strong hit with drum samples", () => + { + var hit = new Hit + { + StartTime = 100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "drum"), + new HitSampleInfo(HitSampleInfo.HIT_FINISH, "drum") // implies strong + } + }; + hit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableHit = new DrawableHit(hit); + hitObjectContainer.Add(drawableHit); + }); + + AddAssert("most valid object is strong nested hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + + AddStep("seek past hit", () => manualClock.CurrentTime = 200); + AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + } + [Test] public void TestNormalDrumRoll() { @@ -177,6 +206,41 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); } + [Test] + public void TestDrumStrongDrumRoll() + { + AddStep("add strong drum roll with drum samples", () => + { + var drumRoll = new DrumRoll + { + StartTime = 100, + EndTime = 1100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "drum"), + new HitSampleInfo(HitSampleInfo.HIT_FINISH, "drum") // implies strong + } + }; + drumRoll.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableDrumRoll = new DrawableDrumRoll(drumRoll); + hitObjectContainer.Add(drawableDrumRoll); + }); + + AddAssert("most valid object is drum roll tick's nested strong hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + + AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); + AddAssert("most valid object is drum roll tick's nested strong hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + + AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); + } + [Test] public void TestNormalSwell() { @@ -216,7 +280,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { AddStep("add swell with drum samples", () => { - var swell = new Swell() + var swell = new Swell { StartTime = 100, EndTime = 1100, From 4a7b011a53773d547b60401f609d7e394482a3ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 18:28:30 +0200 Subject: [PATCH 0929/1400] Propagate samples to strong nested hits too The rationale is the same as in 6d325651dcca275091d51bbfbad3e59fa4ce4dc8. Due to the recursive nature of `GameplaySampleTriggerSource.GetMostValidObject()`, in the case of nested hits, drum rolls and drum roll ticks, the nested strong hits would become the most valid object, and so without propagating the samples down to that level too, nothing would play. --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 6 +++++- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 6 +++++- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index ba68967fbe..aa5da6d710 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -107,7 +107,11 @@ namespace osu.Game.Rulesets.Taiko.Objects protected override HitWindows CreateHitWindows() => HitWindows.Empty; - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit + { + StartTime = startTime, + Samples = Samples + }; public class StrongNestedHit : StrongNestedHitObject { diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 6bcb8674e6..f8203d793d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -33,7 +33,11 @@ namespace osu.Game.Rulesets.Taiko.Objects public override double MaximumJudgementOffset => HitWindow; - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit + { + StartTime = startTime, + Samples = Samples + }; public class StrongNestedHit : StrongNestedHitObject { diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 303447e672..8935878f0e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -72,7 +72,11 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime }; + protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit + { + StartTime = startTime, + Samples = Samples + }; public class StrongNestedHit : StrongNestedHitObject { From 9915fac2c825a5b06555bf440f61748b10cccd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 18:31:26 +0200 Subject: [PATCH 0930/1400] Fix sample silence being one level too low 4a7b011a53773d547b60401f609d7e394482a3ab inadvertently unearthed that nested strong hits could play samples of their own accord, rather than delegating to `DrumSampleTriggerSource` as they were supposed to. This was an unfortunate omission due to how the inheritance structure of `TaikoHitObject` looks like (some irrelevant classes omitted for brevity): DrawableTaikoHitObject DrawableTaikoHitObject <-- `GetSamples()` was overridden to empty here DrawableTaikoStrongableHitObject DrawableHit DrawableDrumRoll DrawableDrumRollTick DrawableSwell DrawableSwellTick DrawableStrongNestedHit <-- all strong nested hits are here => didn't receive `GetSamples()` override DrawableHit.StrongNestedHit DrawableDrumRoll.StrongNestedHit DrawableDrumRollTick.StrongNestedHit To fix, move the `GetSamples()` override one level higher, to the non-generic `DrawableTaikoHitObject`, to suppress the spurious sample playbacks. The stale reference in the comment was also updated to match current code. --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index f695c505a4..1b5d641612 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -118,6 +118,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override bool RemoveWhenNotAlive => false; } + + // Most osu!taiko hitsounds are managed by the drum (see DrumSampleTriggerSource). + public override IEnumerable GetSamples() => Enumerable.Empty(); } public abstract partial class DrawableTaikoHitObject : DrawableTaikoHitObject @@ -157,9 +160,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Content.Add(MainPiece = CreateMainPiece()); } - // Most osu!taiko hitsounds are managed by the drum (see DrumSampleMapping). - public override IEnumerable GetSamples() => Enumerable.Empty(); - protected abstract SkinnableDrawable CreateMainPiece(); } } From 88c112612f05c71cb75b5364753cc38bb310848f Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 May 2023 10:35:22 -0700 Subject: [PATCH 0931/1400] Remove hardcoded website url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Overlays/News/Sidebar/MonthSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/News/Sidebar/MonthSection.cs b/osu.Game/Overlays/News/Sidebar/MonthSection.cs index b586d156ad..9a748b2001 100644 --- a/osu.Game/Overlays/News/Sidebar/MonthSection.cs +++ b/osu.Game/Overlays/News/Sidebar/MonthSection.cs @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.News.Sidebar { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - AddLink(post.Title, LinkAction.External, "https://osu.ppy.sh/home/news/" + post.Slug, "view in browser"); + AddLink(post.Title, LinkAction.External, @"/home/news/" + post.Slug, "view in browser"); } } From 19816ae0137d49709b53753dc55d137224be89a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 21 May 2023 20:38:27 +0200 Subject: [PATCH 0932/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 4 ++-- osu.iOS.props | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c73c643d4b..6aebae665d 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3ea4a57c2c..0fd2b0c2c5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -30,13 +30,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index a240dec963..e4a169f8e5 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From b3527b92b60670dd2f5a6d18af135987e0e08d60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 May 2023 09:25:17 +0900 Subject: [PATCH 0933/1400] Handle case in tests where current display becomes null --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index b76b9a40f9..a3290bc81c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -193,6 +193,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics currentDisplay.BindValueChanged(display => Schedule(() => { + if (display.NewValue == null) + { + resolutions.Clear(); + return; + } + resolutions.ReplaceRange(1, resolutions.Count - 1, display.NewValue.DisplayModes .Where(m => m.Size.Width >= 800 && m.Size.Height >= 600) .OrderByDescending(m => Math.Max(m.Size.Height, m.Size.Width)) From 2279aad360a6f733068aa355855f17f383822782 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 May 2023 19:27:20 -0700 Subject: [PATCH 0934/1400] Apply NRT to `NewsCard` --- osu.Game/Overlays/News/NewsCard.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/News/NewsCard.cs b/osu.Game/Overlays/News/NewsCard.cs index e0be5cc4a9..18ca46a995 100644 --- a/osu.Game/Overlays/News/NewsCard.cs +++ b/osu.Game/Overlays/News/NewsCard.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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Allocation; @@ -27,8 +25,8 @@ namespace osu.Game.Overlays.News private readonly APINewsPost post; - private Box background; - private TextFlowContainer main; + private Box background = null!; + private TextFlowContainer main = null!; public NewsCard(APINewsPost post) { From 7392109bcef1ff00170d26539cf13e29460790c4 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 21 May 2023 19:28:12 -0700 Subject: [PATCH 0935/1400] Apply same behavioral changes to `NewsCard` --- osu.Game/Overlays/News/NewsCard.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/News/NewsCard.cs b/osu.Game/Overlays/News/NewsCard.cs index 18ca46a995..b12aa4509e 100644 --- a/osu.Game/Overlays/News/NewsCard.cs +++ b/osu.Game/Overlays/News/NewsCard.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; -using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -39,12 +38,12 @@ namespace osu.Game.Overlays.News } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider, GameHost host) + private void load(OverlayColourProvider colourProvider, OsuGame? game) { if (post.Slug != null) { TooltipText = "view in browser"; - Action = () => host.OpenUrlExternally("https://osu.ppy.sh/home/news/" + post.Slug); + Action = () => game?.OpenUrlExternally(@"/home/news/" + post.Slug); } AddRange(new Drawable[] From 843d2903d237a12c92781ced262576f7a65c9ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 22 May 2023 21:17:21 +0200 Subject: [PATCH 0936/1400] Add failing test case for slider velocity undo --- ...TestSceneHitObjectDifficultyPointAdjustments.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index 3b998b4219..c874b39028 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -92,6 +92,20 @@ namespace osu.Game.Tests.Visual.Editing hitObjectHasVelocity(1, 5); } + [Test] + public void TestUndo() + { + clickDifficultyPiece(1); + velocityPopoverHasSingleValue(2); + + setVelocityViaPopover(5); + hitObjectHasVelocity(1, 5); + dismissPopover(); + + AddStep("undo", () => Editor.Undo()); + hitObjectHasVelocity(1, 2); + } + [Test] public void TestMultipleSelectionWithSameSliderVelocity() { From f253d17a7f0af2d21985fbf92ca8835a510e9ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 22 May 2023 22:19:10 +0200 Subject: [PATCH 0937/1400] Fix slider velocity changes not being applied in patcher --- .../Screens/Edit/LegacyEditorBeatmapPatcher.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index b4647c2b64..33f8cd5c78 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -15,7 +15,9 @@ using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; +using osu.Game.Beatmaps.Legacy; using osu.Game.IO; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using Decoder = osu.Game.Beatmaps.Formats.Decoder; @@ -42,6 +44,7 @@ namespace osu.Game.Screens.Edit editorBeatmap.BeginChange(); processHitObjects(result, () => newBeatmap ??= readBeatmap(newState)); processTimingPoints(() => newBeatmap ??= readBeatmap(newState)); + processSliderVelocity(() => newBeatmap ??= readBeatmap(newState)); editorBeatmap.EndChange(); } @@ -71,6 +74,17 @@ namespace osu.Game.Screens.Edit } } + private void processSliderVelocity(Func getNewBeatmap) + { + var legacyControlPoints = (LegacyControlPointInfo)getNewBeatmap().ControlPointInfo; + + foreach (var hitObject in editorBeatmap.HitObjects.Where(ho => ho is IHasSliderVelocity)) + { + var difficultyPoint = legacyControlPoints.DifficultyPointAt(hitObject.StartTime); + ((IHasSliderVelocity)hitObject).SliderVelocity = difficultyPoint.SliderVelocity; + } + } + private void processHitObjects(DiffResult result, Func getNewBeatmap) { findChangedIndices(result, LegacyDecoder.Section.HitObjects, out var removedIndices, out var addedIndices); From 2ce150ba2bbff1763a4be142ec802a5d942c96fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 22 May 2023 22:23:05 +0200 Subject: [PATCH 0938/1400] Add failing test case for sample undo --- .../TestSceneHitObjectSampleAdjustments.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index 530bd5eb20..d812aed0f6 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -109,6 +109,21 @@ namespace osu.Game.Tests.Visual.Editing hitObjectHasSampleBank(1, "drum"); } + [Test] + public void TestUndo() + { + clickSamplePiece(1); + samplePopoverHasSingleBank("soft"); + samplePopoverHasSingleVolume(60); + + setVolumeViaPopover(90); + hitObjectHasSampleVolume(1, 90); + dismissPopover(); + + AddStep("undo", () => Editor.Undo()); + hitObjectHasSampleVolume(1, 60); + } + [Test] public void TestMultipleSelectionWithSameSampleVolume() { From e0b7539c2a1338f079b8052bff0cf1eeb5e1de37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 22 May 2023 22:33:41 +0200 Subject: [PATCH 0939/1400] Fix sample changes not being applied in patcher --- .../Edit/LegacyEditorBeatmapPatcher.cs | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index 33f8cd5c78..ae7105ee34 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -15,7 +16,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.Legacy; +using osu.Game.Extensions; using osu.Game.IO; using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; @@ -44,7 +45,7 @@ namespace osu.Game.Screens.Edit editorBeatmap.BeginChange(); processHitObjects(result, () => newBeatmap ??= readBeatmap(newState)); processTimingPoints(() => newBeatmap ??= readBeatmap(newState)); - processSliderVelocity(() => newBeatmap ??= readBeatmap(newState)); + processHitObjectLocalData(() => newBeatmap ??= readBeatmap(newState)); editorBeatmap.EndChange(); } @@ -74,17 +75,6 @@ namespace osu.Game.Screens.Edit } } - private void processSliderVelocity(Func getNewBeatmap) - { - var legacyControlPoints = (LegacyControlPointInfo)getNewBeatmap().ControlPointInfo; - - foreach (var hitObject in editorBeatmap.HitObjects.Where(ho => ho is IHasSliderVelocity)) - { - var difficultyPoint = legacyControlPoints.DifficultyPointAt(hitObject.StartTime); - ((IHasSliderVelocity)hitObject).SliderVelocity = difficultyPoint.SliderVelocity; - } - } - private void processHitObjects(DiffResult result, Func getNewBeatmap) { findChangedIndices(result, LegacyDecoder.Section.HitObjects, out var removedIndices, out var addedIndices); @@ -101,6 +91,36 @@ namespace osu.Game.Screens.Edit } } + private void processHitObjectLocalData(Func getNewBeatmap) + { + // This method handles data that are stored in control points in the legacy format, + // but were moved to the hitobjects themselves in lazer. + // Specifically, the data being referred to here consists of: slider velocity and sample information. + + // For simplicity, this implementation relies on the editor beatmap already having the same hitobjects in sequence as the new beatmap. + // To guarantee that, `processHitObjects()` must be ran prior to this method for correct operation. + // This is done to avoid the necessity of reimplementing/reusing parts of LegacyBeatmapDecoder that already treat this data correctly. + + var oldObjects = editorBeatmap.HitObjects; + var newObjects = getNewBeatmap().HitObjects; + + Debug.Assert(oldObjects.Count == newObjects.Count); + + foreach (var (oldObject, newObject) in oldObjects.Zip(newObjects)) + { + if (oldObject is IHasSliderVelocity oldWithVelocity && newObject is IHasSliderVelocity newWithVelocity) + oldWithVelocity.SliderVelocity = newWithVelocity.SliderVelocity; + + oldObject.Samples = newObject.Samples; + + if (oldObject is IHasRepeats oldWithRepeats && newObject is IHasRepeats newWithRepeats) + { + oldWithRepeats.NodeSamples.Clear(); + oldWithRepeats.NodeSamples.AddRange(newWithRepeats.NodeSamples); + } + } + } + private void findChangedIndices(DiffResult result, LegacyDecoder.Section section, out List removedIndices, out List addedIndices) { removedIndices = new List(); From 38b4bd8aefd738af26e26c1bf2309995f7253aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 22 May 2023 22:45:39 +0200 Subject: [PATCH 0940/1400] Fix undo not behaving as expected sometimes --- osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index ae7105ee34..2cf823ca0c 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -108,6 +108,11 @@ namespace osu.Game.Screens.Edit foreach (var (oldObject, newObject) in oldObjects.Zip(newObjects)) { + // if `oldObject` and `newObject` are the same, it means that `oldObject` was inserted into `editorBeatmap` by `processHitObjects()`. + // in that case, there is nothing to do (and some of the subsequent changes may even prove destructive). + if (ReferenceEquals(oldObject, newObject)) + continue; + if (oldObject is IHasSliderVelocity oldWithVelocity && newObject is IHasSliderVelocity newWithVelocity) oldWithVelocity.SliderVelocity = newWithVelocity.SliderVelocity; From c291d6fc829d02103230f4cb0881fe2bdeca1985 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 22 May 2023 12:02:44 +0900 Subject: [PATCH 0941/1400] Remove catch tiny droplet portion --- .../Scoring/CatchScoreProcessor.cs | 74 +------------------ 1 file changed, 2 insertions(+), 72 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 9d5fc553de..9323296b7f 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -14,13 +12,6 @@ namespace osu.Game.Rulesets.Catch.Scoring private const int combo_cap = 200; private const double combo_base = 4; - private double tinyDropletScale; - - private int maximumTinyDroplets; - private int hitTinyDroplets; - private int maximumBasicJudgements; - private int currentBasicJudgements; - public CatchScoreProcessor() : base(new CatchRuleset()) { @@ -28,73 +19,12 @@ namespace osu.Game.Rulesets.Catch.Scoring protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; - - const int tiny_droplets_portion = 400000; - - return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboProgress - + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + return 600000 * comboProgress + + 400000 * Accuracy.Value * accuracyProgress + bonusPortion; } protected override double GetComboScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)); - - protected override void ApplyScoreChange(JudgementResult result) - { - base.ApplyScoreChange(result); - - if (result.HitObject is TinyDroplet) - hitTinyDroplets++; - - if (result.Type.IsBasic()) - currentBasicJudgements++; - } - - protected override void RemoveScoreChange(JudgementResult result) - { - base.RemoveScoreChange(result); - - if (result.HitObject is TinyDroplet) - hitTinyDroplets--; - - if (result.Type.IsBasic()) - currentBasicJudgements--; - } - - protected override void Reset(bool storeResults) - { - base.Reset(storeResults); - - if (storeResults) - { - maximumTinyDroplets = hitTinyDroplets; - maximumBasicJudgements = currentBasicJudgements; - - if (maximumTinyDroplets + maximumBasicJudgements == 0) - tinyDropletScale = 0; - else - tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + maximumBasicJudgements); - } - - hitTinyDroplets = 0; - currentBasicJudgements = 0; - } - - public override void WriteScoreProcessorStatistics(IDictionary statistics) - { - base.WriteScoreProcessorStatistics(statistics); - - statistics.Add(nameof(hitTinyDroplets), hitTinyDroplets); - statistics.Add(nameof(currentBasicJudgements), currentBasicJudgements); - } - - public override void ReadScoreProcessorStatistics(IReadOnlyDictionary statistics) - { - base.ReadScoreProcessorStatistics(statistics); - - hitTinyDroplets = (int)statistics.GetValueOrDefault(nameof(hitTinyDroplets), 0); - currentBasicJudgements = (int)statistics.GetValueOrDefault(nameof(currentBasicJudgements), 0); - } } } From e1feeded127aeb95b6a5f34c95c93ee0cd484b78 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 22 May 2023 12:49:41 +0900 Subject: [PATCH 0942/1400] Change statistics type, remove overridability --- osu.Game/Online/Spectator/FrameHeader.cs | 7 ++- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 49 +++++++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index baebb28e4f..4d1c2c2cff 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -48,7 +48,7 @@ namespace osu.Game.Online.Spectator /// Additional statistics that guides the score processor to calculate the correct score for this frame. /// [Key(5)] - public Dictionary ScoreProcessorStatistics { get; set; } + public ScoreProcessorStatistics ScoreProcessorStatistics { get; set; } /// /// The time at which this frame was received by the server. @@ -71,13 +71,12 @@ namespace osu.Game.Online.Spectator // copy for safety Statistics = new Dictionary(score.Statistics); - ScoreProcessorStatistics = new Dictionary(); - scoreProcessor.WriteScoreProcessorStatistics(ScoreProcessorStatistics); + ScoreProcessorStatistics = scoreProcessor.GetScoreProcessorStatistics(); } [JsonConstructor] [SerializationConstructor] - public FrameHeader(long totalScore, double accuracy, int combo, int maxCombo, Dictionary statistics, Dictionary scoreProcessorStatistics, DateTimeOffset receivedTime) + public FrameHeader(long totalScore, double accuracy, int combo, int maxCombo, Dictionary statistics, ScoreProcessorStatistics scoreProcessorStatistics, DateTimeOffset receivedTime) { TotalScore = totalScore; Accuracy = accuracy; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index f2b1607f5e..013dd4b8e7 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using MessagePack; using osu.Framework.Bindables; using osu.Framework.Localisation; using osu.Game.Beatmaps; @@ -397,29 +398,29 @@ namespace osu.Game.Rulesets.Scoring scoreResultCounts.Clear(); scoreResultCounts.AddRange(frame.Header.Statistics); - ReadScoreProcessorStatistics(frame.Header.ScoreProcessorStatistics); + SetScoreProcessorStatistics(frame.Header.ScoreProcessorStatistics); updateScore(); OnResetFromReplayFrame?.Invoke(); } - public virtual void WriteScoreProcessorStatistics(IDictionary statistics) + public ScoreProcessorStatistics GetScoreProcessorStatistics() => new ScoreProcessorStatistics { - statistics.Add(nameof(currentMaximumBaseScore), currentMaximumBaseScore); - statistics.Add(nameof(currentBaseScore), currentBaseScore); - statistics.Add(nameof(currentCountBasicJudgements), currentCountBasicJudgements); - statistics.Add(nameof(currentComboPortion), currentComboPortion); - statistics.Add(nameof(currentBonusPortion), currentBonusPortion); - } + MaximumBaseScore = currentMaximumBaseScore, + BaseScore = currentBaseScore, + CountBasicJudgements = currentCountBasicJudgements, + ComboPortion = currentComboPortion, + BonusPortion = currentBonusPortion + }; - public virtual void ReadScoreProcessorStatistics(IReadOnlyDictionary statistics) + public void SetScoreProcessorStatistics(ScoreProcessorStatistics statistics) { - currentMaximumBaseScore = (double)statistics.GetValueOrDefault(nameof(currentMaximumBaseScore), 0); - currentBaseScore = (double)statistics.GetValueOrDefault(nameof(currentBaseScore), 0); - currentCountBasicJudgements = (int)statistics.GetValueOrDefault(nameof(currentCountBasicJudgements), 0); - currentComboPortion = (double)statistics.GetValueOrDefault(nameof(currentComboPortion), 0); - currentBonusPortion = (double)statistics.GetValueOrDefault(nameof(currentBonusPortion), 0); + currentMaximumBaseScore = statistics.MaximumBaseScore; + currentBaseScore = statistics.BaseScore; + currentCountBasicJudgements = statistics.CountBasicJudgements; + currentComboPortion = statistics.ComboPortion; + currentBonusPortion = statistics.BonusPortion; } #region Static helper methods @@ -493,4 +494,24 @@ namespace osu.Game.Rulesets.Scoring [LocalisableDescription(typeof(GameplaySettingsStrings), nameof(GameplaySettingsStrings.ClassicScoreDisplay))] Classic } + + [Serializable] + [MessagePackObject] + public class ScoreProcessorStatistics + { + [Key(0)] + public double MaximumBaseScore { get; set; } + + [Key(1)] + public double BaseScore { get; set; } + + [Key(2)] + public int CountBasicJudgements { get; set; } + + [Key(3)] + public double ComboPortion { get; set; } + + [Key(4)] + public double BonusPortion { get; set; } + } } From 62d504af921f7de8ac6c7933425aec975f6c3206 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 15:59:24 +0900 Subject: [PATCH 0943/1400] Fix base implementation of ComputeTotalScore --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 013dd4b8e7..2108e99def 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -297,13 +297,9 @@ namespace osu.Game.Rulesets.Scoring protected virtual double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - return - (int)Math.Round - (( - 700000 * comboProgress + - 300000 * Math.Pow(Accuracy.Value, 10) * accuracyProgress + - bonusPortion - ) * scoreMultiplier); + return 700000 * comboProgress + + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyProgress + + bonusPortion; } /// From c8303d55cd72c2e152ad40393325f5ec887ff4f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 May 2023 16:21:56 +0900 Subject: [PATCH 0944/1400] Adjust text and alignment --- .../Statistics/AccuracyHeatmap.cs | 72 ++++++++----------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs index 9d9b3fb84a..5d2f6a14c7 100644 --- a/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs +++ b/osu.Game.Rulesets.Osu/Statistics/AccuracyHeatmap.cs @@ -57,6 +57,8 @@ namespace osu.Game.Rulesets.Osu.Statistics [BackgroundDependencyLoader] private void load() { + const float line_extension = 0.2f; + InternalChild = new Container { Anchor = Anchor.Centre, @@ -97,81 +99,67 @@ namespace osu.Game.Rulesets.Osu.Statistics RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - EdgeSmoothness = new Vector2(1), RelativeSizeAxes = Axes.Y, - Width = line_thickness / 2, // adjust for edgesmoothness - Height = MathF.Sqrt(2), + Width = line_thickness, + Height = inner_portion + line_extension, Rotation = -rotation * 2, - Alpha = 0.3f, + Alpha = 0.6f, }, - new Box + new Circle { Anchor = Anchor.Centre, Origin = Anchor.Centre, - EdgeSmoothness = new Vector2(1), RelativeSizeAxes = Axes.Y, - Width = line_thickness / 2, // adjust for edgesmoothness - Height = MathF.Sqrt(2), + Width = line_thickness, + Height = inner_portion + line_extension, }, new OsuSpriteText { - Text = "Next", + Text = "Overshoot", Anchor = Anchor.Centre, - Origin = Anchor.BottomRight, + Origin = Anchor.BottomCentre, Padding = new MarginPadding(3), RelativePositionAxes = Axes.Both, - Y = -inner_portion / 2, + Y = -(inner_portion + line_extension) / 2, }, new OsuSpriteText { - Text = "object", + Text = "Undershoot", Anchor = Anchor.Centre, - Origin = Anchor.BottomLeft, + Origin = Anchor.TopCentre, Padding = new MarginPadding(3), RelativePositionAxes = Axes.Both, - Y = -inner_portion / 2, + Y = (inner_portion + line_extension) / 2, }, - new OsuSpriteText + new Circle { - Text = "Last", Anchor = Anchor.Centre, - Origin = Anchor.TopRight, - Padding = new MarginPadding(3), + Origin = Anchor.TopCentre, RelativePositionAxes = Axes.Both, - Y = inner_portion / 2, + Y = -(inner_portion + line_extension) / 2, + Margin = new MarginPadding(-line_thickness / 2), + Width = line_thickness, + Height = 10, + Rotation = 45, }, - new OsuSpriteText + new Circle { - Text = "object", Anchor = Anchor.Centre, - Origin = Anchor.TopLeft, - Padding = new MarginPadding(3), + Origin = Anchor.TopCentre, RelativePositionAxes = Axes.Both, - Y = inner_portion / 2, - }, + Y = -(inner_portion + line_extension) / 2, + Margin = new MarginPadding(-line_thickness / 2), + Width = line_thickness, + Height = 10, + Rotation = -45, + } } }, }, - new Box - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Width = 10, - EdgeSmoothness = new Vector2(1), - Height = line_thickness / 2, // adjust for edgesmoothness - }, - new Box - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - EdgeSmoothness = new Vector2(1), - Width = line_thickness / 2, // adjust for edgesmoothness - Height = 10, - } } }, bufferedGrid = new BufferedContainer(cachedFrameBuffer: true) From f8101fbbc7b3606d6e8510846eb186f221bef85e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 17:44:17 +0900 Subject: [PATCH 0945/1400] Rename variables --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2108e99def..c539820f13 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -289,10 +289,10 @@ namespace osu.Game.Rulesets.Scoring { Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1; - double comboRatio = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; - double accuracyRatio = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1; + double comboProgress = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; + double accuracyProcess = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1; - TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboRatio, accuracyRatio, currentBonusPortion) * scoreMultiplier); + TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboProgress, accuracyProcess, currentBonusPortion) * scoreMultiplier); } protected virtual double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) From 8570f825ed20a32733f104a2778df0685d92261e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 17:47:35 +0900 Subject: [PATCH 0946/1400] Consider all accuracy judgements in accuracy progress --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 28 +++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index c539820f13..8c3cd27012 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -110,14 +110,14 @@ namespace osu.Game.Rulesets.Scoring private double currentBaseScore; /// - /// The count of all basic judgements in the beatmap. + /// The count of all accuracy-affecting judgements in the beatmap. /// - private int maximumCountBasicJudgements; + private int maximumCountAccuracyJudgements; /// - /// The count of basic judgements at the current point in time. + /// The count of accuracy-affecting judgements at the current point in time. /// - private int currentCountBasicJudgements; + private int currentCountAccuracyJudgements; /// /// The maximum combo score in the beatmap. @@ -207,13 +207,11 @@ namespace osu.Game.Rulesets.Scoring result.ComboAfterJudgement = Combo.Value; - if (result.Type.IsBasic()) - currentCountBasicJudgements++; - if (result.Type.AffectsAccuracy()) { currentMaximumBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore += Judgement.ToNumericResult(result.Type); + currentCountAccuracyJudgements++; } if (result.Type.IsBonus()) @@ -250,13 +248,11 @@ namespace osu.Game.Rulesets.Scoring if (!result.Type.IsScorable()) return; - if (result.Type.IsBasic()) - currentCountBasicJudgements--; - if (result.Type.AffectsAccuracy()) { currentMaximumBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore -= Judgement.ToNumericResult(result.Type); + currentCountAccuracyJudgements--; } if (result.Type.IsBonus()) @@ -290,7 +286,7 @@ namespace osu.Game.Rulesets.Scoring Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1; double comboProgress = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; - double accuracyProcess = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1; + double accuracyProcess = maximumCountAccuracyJudgements > 0 ? (double)currentCountAccuracyJudgements / maximumCountAccuracyJudgements : 1; TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboProgress, accuracyProcess, currentBonusPortion) * scoreMultiplier); } @@ -316,7 +312,7 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { maximumComboPortion = currentComboPortion; - maximumCountBasicJudgements = currentCountBasicJudgements; + maximumCountAccuracyJudgements = currentCountAccuracyJudgements; maximumResultCounts.Clear(); maximumResultCounts.AddRange(scoreResultCounts); @@ -328,7 +324,7 @@ namespace osu.Game.Rulesets.Scoring currentBaseScore = 0; currentMaximumBaseScore = 0; - currentCountBasicJudgements = 0; + currentCountAccuracyJudgements = 0; currentComboPortion = 0; currentBonusPortion = 0; @@ -405,7 +401,7 @@ namespace osu.Game.Rulesets.Scoring { MaximumBaseScore = currentMaximumBaseScore, BaseScore = currentBaseScore, - CountBasicJudgements = currentCountBasicJudgements, + CountAccuracyJudgements = currentCountAccuracyJudgements, ComboPortion = currentComboPortion, BonusPortion = currentBonusPortion }; @@ -414,7 +410,7 @@ namespace osu.Game.Rulesets.Scoring { currentMaximumBaseScore = statistics.MaximumBaseScore; currentBaseScore = statistics.BaseScore; - currentCountBasicJudgements = statistics.CountBasicJudgements; + currentCountAccuracyJudgements = statistics.CountAccuracyJudgements; currentComboPortion = statistics.ComboPortion; currentBonusPortion = statistics.BonusPortion; } @@ -502,7 +498,7 @@ namespace osu.Game.Rulesets.Scoring public double BaseScore { get; set; } [Key(2)] - public int CountBasicJudgements { get; set; } + public int CountAccuracyJudgements { get; set; } [Key(3)] public double ComboPortion { get; set; } From adf9a596b5fd4cb5e71519e79c990b371dbb7132 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 May 2023 17:58:10 +0900 Subject: [PATCH 0947/1400] Fix weird state when attempting to enter gameplay skin editor scene from multiplayer Closes https://github.com/ppy/osu/issues/23626. --- osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs b/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs index 61195d7175..9b021632cf 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorSceneLibrary.cs @@ -113,7 +113,7 @@ namespace osu.Game.Overlays.SkinEditor if (replayGeneratingMod != null) screen.Push(new PlayerLoader(() => new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)))); - }, new[] { typeof(Player), typeof(SongSelect) }) + }, new[] { typeof(Player), typeof(PlaySongSelect) }) }, } }, From 3598ca91251ed4991d716c32878d751e8de13e60 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 18:05:10 +0900 Subject: [PATCH 0948/1400] Adjust xmldoc --- osu.Game/Rulesets/Scoring/HitResult.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 83ed98768c..0013a9f20d 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Scoring => AffectsCombo(result) && !IsHit(result); /// - /// Whether a increases/breaks the combo, and affects the combo portion of the score. + /// Whether a increases or breaks the combo. /// public static bool AffectsCombo(this HitResult result) { From 7cf50b1e18a74b74fc34396a1c4ddaf444d6dc6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 May 2023 18:06:04 +0900 Subject: [PATCH 0949/1400] Disallow game to check for updates while gameplay is active --- osu.Desktop/Updater/SquirrelUpdateManager.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 3d4db88471..941ab335e8 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -9,6 +9,7 @@ using osu.Framework.Logging; using osu.Game; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using osu.Game.Screens.Play; using Squirrel; using Squirrel.SimpleSplat; using LogLevel = Squirrel.SimpleSplat.LogLevel; @@ -36,6 +37,9 @@ namespace osu.Desktop.Updater [Resolved] private OsuGameBase game { get; set; } = null!; + [Resolved] + private ILocalUserPlayInfo? localUserInfo { get; set; } + [BackgroundDependencyLoader] private void load(INotificationOverlay notifications) { @@ -55,6 +59,10 @@ namespace osu.Desktop.Updater try { + // Avoid any kind of update checking while gameplay is running. + if (localUserInfo?.IsPlaying.Value == true) + return false; + updateManager ??= new GithubUpdateManager(@"https://github.com/ppy/osu", false, github_token, @"osulazer"); var info = await updateManager.CheckForUpdate(!useDeltaPatching).ConfigureAwait(false); From d45b54399b376289531a37f5635f03dfa64cc8c2 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 18:15:32 +0900 Subject: [PATCH 0950/1400] Add back minimum/maximum accuracy --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 8c3cd27012..b470c09859 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -109,6 +109,11 @@ namespace osu.Game.Rulesets.Scoring /// private double currentBaseScore; + /// + /// The maximum sum of all accuracy-affecting judgements in the beatmap. + /// + private double maximumBaseScore; + /// /// The count of all accuracy-affecting judgements in the beatmap. /// @@ -284,6 +289,8 @@ namespace osu.Game.Rulesets.Scoring private void updateScore() { Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1; + MinimumAccuracy.Value = maximumBaseScore > 0 ? currentBaseScore / maximumBaseScore : 0; + MaximumAccuracy.Value = maximumBaseScore > 0 ? (currentBaseScore + (maximumBaseScore - currentMaximumBaseScore)) / maximumBaseScore : 1; double comboProgress = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; double accuracyProcess = maximumCountAccuracyJudgements > 0 ? (double)currentCountAccuracyJudgements / maximumCountAccuracyJudgements : 1; @@ -311,6 +318,8 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { + maximumBaseScore = currentBaseScore; + maximumComboPortion = currentComboPortion; maximumCountAccuracyJudgements = currentCountAccuracyJudgements; @@ -334,9 +343,6 @@ namespace osu.Game.Rulesets.Scoring Rank.Disabled = false; Rank.Value = ScoreRank.X; HighestCombo.Value = 0; - - currentBaseScore = 0; - currentMaximumBaseScore = 0; } /// From 844c023fb71fc6b87386650e820c621b6ca5b2bd Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 18:18:27 +0900 Subject: [PATCH 0951/1400] Fix tests --- .../Gameplay/TestSceneScoreProcessor.cs | 20 +- .../Rulesets/Scoring/ScoreProcessorTest.cs | 189 +++++------------- ...MultiplayerGameplayLeaderboardTestScene.cs | 14 +- 3 files changed, 75 insertions(+), 148 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index 90c7688443..fbe4dba8ed 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -76,22 +76,38 @@ namespace osu.Game.Tests.Gameplay // Reset with a miss instead. scoreProcessor.ResetFromReplayFrame(new OsuReplayFrame { - Header = new FrameHeader(0, 0, 0, new Dictionary { { HitResult.Miss, 1 } }, DateTimeOffset.Now) + Header = new FrameHeader(0, 0, 0, 0, new Dictionary { { HitResult.Miss, 1 } }, new ScoreProcessorStatistics + { + MaximumBaseScore = 300, + BaseScore = 0, + CountAccuracyJudgements = 1, + ComboPortion = 0, + BonusPortion = 0 + }, DateTimeOffset.Now) }); Assert.That(scoreProcessor.TotalScore.Value, Is.Zero); Assert.That(scoreProcessor.JudgedHits, Is.EqualTo(1)); Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(0)); + Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo(0)); // Reset with no judged hit. scoreProcessor.ResetFromReplayFrame(new OsuReplayFrame { - Header = new FrameHeader(0, 0, 0, new Dictionary(), DateTimeOffset.Now) + Header = new FrameHeader(0, 0, 0, 0, new Dictionary(), new ScoreProcessorStatistics + { + MaximumBaseScore = 0, + BaseScore = 0, + CountAccuracyJudgements = 0, + ComboPortion = 0, + BonusPortion = 0 + }, DateTimeOffset.Now) }); Assert.That(scoreProcessor.TotalScore.Value, Is.Zero); Assert.That(scoreProcessor.JudgedHits, Is.Zero); Assert.That(scoreProcessor.Combo.Value, Is.EqualTo(0)); + Assert.That(scoreProcessor.Accuracy.Value, Is.EqualTo(1)); } [Test] diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index 826c610f56..f51a4ad52b 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -14,11 +14,12 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; using osu.Game.Tests.Beatmaps; namespace osu.Game.Tests.Rulesets.Scoring @@ -31,7 +32,7 @@ namespace osu.Game.Tests.Rulesets.Scoring [SetUp] public void SetUp() { - scoreProcessor = new ScoreProcessor(new TestRuleset()); + scoreProcessor = new ScoreProcessor(new OsuRuleset()); beatmap = new TestBeatmap(new RulesetInfo()) { HitObjects = new List @@ -41,15 +42,14 @@ namespace osu.Game.Tests.Rulesets.Scoring }; } - [TestCase(ScoringMode.Standardised, HitResult.Meh, 750_000)] - [TestCase(ScoringMode.Standardised, HitResult.Ok, 800_000)] + [TestCase(ScoringMode.Standardised, HitResult.Meh, 116_667)] + [TestCase(ScoringMode.Standardised, HitResult.Ok, 233_338)] [TestCase(ScoringMode.Standardised, HitResult.Great, 1_000_000)] - [TestCase(ScoringMode.Classic, HitResult.Meh, 20)] - [TestCase(ScoringMode.Classic, HitResult.Ok, 23)] + [TestCase(ScoringMode.Classic, HitResult.Meh, 0)] + [TestCase(ScoringMode.Classic, HitResult.Ok, 2)] [TestCase(ScoringMode.Classic, HitResult.Great, 36)] public void TestSingleOsuHit(ScoringMode scoringMode, HitResult hitResult, int expectedScore) { - scoreProcessor.Mode.Value = scoringMode; scoreProcessor.ApplyBeatmap(beatmap); var judgementResult = new JudgementResult(beatmap.HitObjects.Single(), new OsuJudgement()) @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Rulesets.Scoring }; scoreProcessor.ApplyResult(judgementResult); - Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(expectedScore).Within(0.5d)); + Assert.That(scoreProcessor.GetDisplayScore(scoringMode), Is.EqualTo(expectedScore).Within(0.5d)); } /// @@ -70,39 +70,29 @@ namespace osu.Game.Tests.Rulesets.Scoring /// Expected score after all objects have been judged, rounded to the nearest integer. /// /// This test intentionally misses the 3rd hitobject to achieve lower than 75% accuracy and 50% max combo. - /// - /// For standardised scoring, is calculated using the following formula: - /// 1_000_000 * (((3 * ) / (4 * )) * 30% + (bestCombo / maxCombo) * 70%) - /// - /// - /// For classic scoring, is calculated using the following formula: - /// / * 936 - /// where 936 is simplified from: - /// 75% * 4 * 300 * (1 + 1/25) - /// /// - [TestCase(ScoringMode.Standardised, HitResult.Miss, HitResult.Great, 0)] // (3 * 0) / (4 * 300) * 300_000 + (0 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.Meh, HitResult.Great, 387_500)] // (3 * 50) / (4 * 300) * 300_000 + (2 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.Ok, HitResult.Great, 425_000)] // (3 * 100) / (4 * 300) * 300_000 + (2 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.Good, HitResult.Perfect, 492_857)] // (3 * 200) / (4 * 350) * 300_000 + (2 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.Great, HitResult.Great, 575_000)] // (3 * 300) / (4 * 300) * 300_000 + (2 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.Perfect, HitResult.Perfect, 575_000)] // (3 * 350) / (4 * 350) * 300_000 + (2 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.SmallTickMiss, HitResult.SmallTickHit, 700_000)] // (3 * 0) / (4 * 10) * 300_000 + 700_000 (max combo 0) - [TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, HitResult.SmallTickHit, 925_000)] // (3 * 10) / (4 * 10) * 300_000 + 700_000 (max combo 0) - [TestCase(ScoringMode.Standardised, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)] // (3 * 0) / (4 * 30) * 300_000 + (0 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.LargeTickHit, HitResult.LargeTickHit, 575_000)] // (3 * 30) / (4 * 30) * 300_000 + (0 / 4) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.SmallBonus, HitResult.SmallBonus, 1_000_030)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 10 (bonus points) - [TestCase(ScoringMode.Standardised, HitResult.LargeBonus, HitResult.LargeBonus, 1_000_150)] // 1 * 300_000 + 700_000 (max combo 0) + 3 * 50 (bonus points) + [TestCase(ScoringMode.Standardised, HitResult.Miss, HitResult.Great, 0)] + [TestCase(ScoringMode.Standardised, HitResult.Meh, HitResult.Great, 79_333)] + [TestCase(ScoringMode.Standardised, HitResult.Ok, HitResult.Great, 158_667)] + [TestCase(ScoringMode.Standardised, HitResult.Good, HitResult.Perfect, 302_402)] + [TestCase(ScoringMode.Standardised, HitResult.Great, HitResult.Great, 492_894)] + [TestCase(ScoringMode.Standardised, HitResult.Perfect, HitResult.Perfect, 492_894)] + [TestCase(ScoringMode.Standardised, HitResult.SmallTickMiss, HitResult.SmallTickHit, 0)] + [TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, HitResult.SmallTickHit, 541_894)] + [TestCase(ScoringMode.Standardised, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)] + [TestCase(ScoringMode.Standardised, HitResult.LargeTickHit, HitResult.LargeTickHit, 492_894)] + [TestCase(ScoringMode.Standardised, HitResult.SmallBonus, HitResult.SmallBonus, 1_000_030)] + [TestCase(ScoringMode.Standardised, HitResult.LargeBonus, HitResult.LargeBonus, 1_000_150)] [TestCase(ScoringMode.Classic, HitResult.Miss, HitResult.Great, 0)] - [TestCase(ScoringMode.Classic, HitResult.Meh, HitResult.Great, 86)] - [TestCase(ScoringMode.Classic, HitResult.Ok, HitResult.Great, 104)] - [TestCase(ScoringMode.Classic, HitResult.Good, HitResult.Perfect, 140)] - [TestCase(ScoringMode.Classic, HitResult.Great, HitResult.Great, 190)] - [TestCase(ScoringMode.Classic, HitResult.Perfect, HitResult.Perfect, 190)] - [TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, HitResult.SmallTickHit, 18)] - [TestCase(ScoringMode.Classic, HitResult.SmallTickHit, HitResult.SmallTickHit, 31)] + [TestCase(ScoringMode.Classic, HitResult.Meh, HitResult.Great, 4)] + [TestCase(ScoringMode.Classic, HitResult.Ok, HitResult.Great, 15)] + [TestCase(ScoringMode.Classic, HitResult.Good, HitResult.Perfect, 53)] + [TestCase(ScoringMode.Classic, HitResult.Great, HitResult.Great, 140)] + [TestCase(ScoringMode.Classic, HitResult.Perfect, HitResult.Perfect, 140)] + [TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, HitResult.SmallTickHit, 0)] + [TestCase(ScoringMode.Classic, HitResult.SmallTickHit, HitResult.SmallTickHit, 11)] [TestCase(ScoringMode.Classic, HitResult.LargeTickMiss, HitResult.LargeTickHit, 0)] - [TestCase(ScoringMode.Classic, HitResult.LargeTickHit, HitResult.LargeTickHit, 12)] + [TestCase(ScoringMode.Classic, HitResult.LargeTickHit, HitResult.LargeTickHit, 9)] [TestCase(ScoringMode.Classic, HitResult.SmallBonus, HitResult.SmallBonus, 36)] [TestCase(ScoringMode.Classic, HitResult.LargeBonus, HitResult.LargeBonus, 36)] public void TestFourVariousResultsOneMiss(ScoringMode scoringMode, HitResult hitResult, HitResult maxResult, int expectedScore) @@ -113,59 +103,18 @@ namespace osu.Game.Tests.Rulesets.Scoring { HitObjects = new List(Enumerable.Repeat(new TestHitObject(maxResult), 4)) }; - scoreProcessor.Mode.Value = scoringMode; scoreProcessor.ApplyBeatmap(fourObjectBeatmap); for (int i = 0; i < 4; i++) { - var judgementResult = new JudgementResult(fourObjectBeatmap.HitObjects[i], new Judgement()) + var judgementResult = new JudgementResult(fourObjectBeatmap.HitObjects[i], new TestJudgement(maxResult)) { Type = i == 2 ? minResult : hitResult }; scoreProcessor.ApplyResult(judgementResult); } - Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(expectedScore).Within(0.5d)); - } - - /// - /// This test uses a beatmap with four small ticks and one object with the of . - /// Its goal is to ensure that with the of , - /// small ticks contribute to the accuracy portion, but not the combo portion. - /// In contrast, does not have separate combo and accuracy portion (they are multiplied by each other). - /// - [TestCase(ScoringMode.Standardised, HitResult.SmallTickHit, 978_571)] // (3 * 10 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000 - [TestCase(ScoringMode.Standardised, HitResult.SmallTickMiss, 914_286)] // (3 * 0 + 100) / (4 * 10 + 100) * 300_000 + (1 / 1) * 700_000 - [TestCase(ScoringMode.Classic, HitResult.SmallTickHit, 34)] - [TestCase(ScoringMode.Classic, HitResult.SmallTickMiss, 30)] - public void TestSmallTicksAccuracy(ScoringMode scoringMode, HitResult hitResult, int expectedScore) - { - IEnumerable hitObjects = Enumerable - .Repeat(new TestHitObject(HitResult.SmallTickHit), 4) - .Append(new TestHitObject(HitResult.Ok)); - IBeatmap fiveObjectBeatmap = new TestBeatmap(new RulesetInfo()) - { - HitObjects = hitObjects.ToList() - }; - scoreProcessor.Mode.Value = scoringMode; - scoreProcessor.ApplyBeatmap(fiveObjectBeatmap); - - for (int i = 0; i < 4; i++) - { - var judgementResult = new JudgementResult(fiveObjectBeatmap.HitObjects[i], new Judgement()) - { - Type = i == 2 ? HitResult.SmallTickMiss : hitResult - }; - scoreProcessor.ApplyResult(judgementResult); - } - - var lastJudgementResult = new JudgementResult(fiveObjectBeatmap.HitObjects.Last(), new Judgement()) - { - Type = HitResult.Ok - }; - scoreProcessor.ApplyResult(lastJudgementResult); - - Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(expectedScore).Within(0.5d)); + Assert.That(scoreProcessor.GetDisplayScore(scoringMode), Is.EqualTo(expectedScore).Within(0.5d)); } [Test] @@ -173,10 +122,9 @@ namespace osu.Game.Tests.Rulesets.Scoring [Values(ScoringMode.Standardised, ScoringMode.Classic)] ScoringMode scoringMode) { - scoreProcessor.Mode.Value = scoringMode; scoreProcessor.ApplyBeatmap(new TestBeatmap(new RulesetInfo())); - Assert.That(scoreProcessor.TotalScore.Value, Is.Zero); + Assert.That(scoreProcessor.GetDisplayScore(scoringMode), Is.Zero); } [TestCase(HitResult.IgnoreHit, HitResult.IgnoreMiss)] @@ -294,28 +242,6 @@ namespace osu.Game.Tests.Rulesets.Scoring Assert.AreEqual(expectedReturnValue, hitResult.IsScorable()); } - [TestCase(HitResult.Perfect, 1_000_000)] - [TestCase(HitResult.SmallTickHit, 1_000_000)] - [TestCase(HitResult.LargeTickHit, 1_000_000)] - [TestCase(HitResult.SmallBonus, 1_000_000 + Judgement.SMALL_BONUS_SCORE)] - [TestCase(HitResult.LargeBonus, 1_000_000 + Judgement.LARGE_BONUS_SCORE)] - public void TestGetScoreWithExternalStatistics(HitResult result, int expectedScore) - { - var statistic = new Dictionary { { result, 1 } }; - - scoreProcessor.ApplyBeatmap(new Beatmap - { - HitObjects = { new TestHitObject(result) } - }); - - Assert.That(scoreProcessor.ComputeScore(ScoringMode.Standardised, new ScoreInfo - { - Ruleset = new TestRuleset().RulesetInfo, - MaxCombo = result.AffectsCombo() ? 1 : 0, - Statistics = statistic - }), Is.EqualTo(expectedScore).Within(0.5d)); - } - #pragma warning disable CS0618 [Test] public void TestLegacyComboIncrease() @@ -330,29 +256,6 @@ namespace osu.Game.Tests.Rulesets.Scoring Assert.That(HitResult.LegacyComboIncrease.IsHit(), Is.True); Assert.That(HitResult.LegacyComboIncrease.IsScorable(), Is.True); Assert.That(HitResultExtensions.ALL_TYPES, Does.Not.Contain(HitResult.LegacyComboIncrease)); - - // Cannot be used to apply results. - Assert.Throws(() => scoreProcessor.ApplyBeatmap(new Beatmap - { - HitObjects = { new TestHitObject(HitResult.LegacyComboIncrease) } - })); - - ScoreInfo testScore = new ScoreInfo - { - MaxCombo = 1, - Statistics = new Dictionary - { - { HitResult.Great, 1 } - }, - MaximumStatistics = new Dictionary - { - { HitResult.Great, 1 }, - { HitResult.LegacyComboIncrease, 1 } - } - }; - - double totalScore = new TestScoreProcessor().ComputeScore(ScoringMode.Standardised, testScore); - Assert.That(totalScore, Is.EqualTo(750_000)); // 500K from accuracy (100%), and 250K from combo (50%). } #pragma warning restore CS0618 @@ -362,16 +265,24 @@ namespace osu.Game.Tests.Rulesets.Scoring const int count_judgements = 1000; const int count_misses = 1; - double actual = new TestScoreProcessor().ComputeAccuracy(new ScoreInfo + beatmap = new TestBeatmap(new RulesetInfo()) { - Statistics = new Dictionary + HitObjects = new List(Enumerable.Repeat(new TestHitObject(HitResult.Great), count_judgements)) + }; + + scoreProcessor = new TestScoreProcessor(); + scoreProcessor.ApplyBeatmap(beatmap); + + for (int i = 0; i < beatmap.HitObjects.Count; i++) + { + scoreProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[i], new TestJudgement(HitResult.Great)) { - { HitResult.Great, count_judgements - count_misses }, - { HitResult.Miss, count_misses } - } - }); + Type = i == 0 ? HitResult.Miss : HitResult.Great + }); + } const double expected = (count_judgements - count_misses) / (double)count_judgements; + double actual = scoreProcessor.Accuracy.Value; Assert.That(actual, Is.Not.EqualTo(0.0)); Assert.That(actual, Is.Not.EqualTo(1.0)); @@ -419,14 +330,18 @@ namespace osu.Game.Tests.Rulesets.Scoring private partial class TestScoreProcessor : ScoreProcessor { - protected override double DefaultAccuracyPortion => 0.5; - protected override double DefaultComboPortion => 0.5; - public TestScoreProcessor() : base(new TestRuleset()) { } + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) + { + return 500000 * comboProgress + + 500000 * Accuracy.Value * accuracyProgress + + bonusPortion; + } + // ReSharper disable once MemberHidesStaticFromOuterClass private class TestRuleset : Ruleset { diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index 649c662e41..906eea9553 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -21,7 +21,6 @@ using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; namespace osu.Game.Tests.Visual.Multiplayer @@ -188,15 +187,12 @@ namespace osu.Game.Tests.Visual.Multiplayer if (!lastHeaders.TryGetValue(userId, out var header)) { - lastHeaders[userId] = header = new FrameHeader(new ScoreInfo + lastHeaders[userId] = header = new FrameHeader(0, 0, 0, 0, new Dictionary { - Statistics = new Dictionary - { - [HitResult.Miss] = 0, - [HitResult.Meh] = 0, - [HitResult.Great] = 0 - } - }); + [HitResult.Miss] = 0, + [HitResult.Meh] = 0, + [HitResult.Great] = 0 + }, new ScoreProcessorStatistics(), DateTimeOffset.Now); } switch (RNG.Next(0, 3)) From 6f4e2b37edfdf443f993caf679c061bb38909d38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 May 2023 18:47:56 +0900 Subject: [PATCH 0952/1400] Add shadow to notifications and settings overlays to better distinguish from other overlays --- osu.Game/Overlays/NotificationOverlay.cs | 13 +++++++++++++ osu.Game/Overlays/SettingsPanel.cs | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 71a4c58afd..4a69fb6240 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -5,9 +5,11 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Framework.Logging; @@ -16,6 +18,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Overlays.Notifications; using osu.Game.Resources.Localisation.Web; using osuTK; +using osuTK.Graphics; using NotificationsStrings = osu.Game.Localisation.NotificationsStrings; namespace osu.Game.Overlays @@ -72,6 +75,14 @@ namespace osu.Game.Overlays mainContent = new Container { RelativeSizeAxes = Axes.Both, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0), + Type = EdgeEffectType.Shadow, + Radius = 10, + Hollow = true, + }, Children = new Drawable[] { new Box @@ -199,6 +210,7 @@ namespace osu.Game.Overlays this.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); mainContent.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); + mainContent.FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); toastTray.FlushAllToasts(); } @@ -211,6 +223,7 @@ namespace osu.Game.Overlays this.MoveToX(WIDTH, TRANSITION_LENGTH, Easing.OutQuint); mainContent.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); + mainContent.FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.In); } private void notificationClosed() => Schedule(() => diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index aefaccdb5d..382423eb57 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -10,15 +10,18 @@ using System.Threading.Tasks; using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; +using osuTK.Graphics; namespace osu.Game.Overlays { @@ -105,6 +108,13 @@ namespace osu.Game.Overlays Add(SectionsContainer = new SettingsSectionsContainer { Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0), + Type = EdgeEffectType.Shadow, + Hollow = true, + Radius = 10 + }, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), SelectedSection = { BindTarget = CurrentSection }, @@ -156,6 +166,8 @@ namespace osu.Game.Overlays ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); + SectionsContainer.FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); + // delay load enough to ensure it doesn't overlap with the initial animation. // this is done as there is still a brief stutter during load completion which is more visible if the transition is in progress. // the eventual goal would be to remove the need for this by splitting up load into smaller work pieces, or fixing the remaining @@ -175,6 +187,7 @@ namespace osu.Game.Overlays { base.PopOut(); + SectionsContainer.FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.In); ContentContainer.MoveToX(-WIDTH + ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); Sidebar?.MoveToX(-sidebar_width, TRANSITION_LENGTH, Easing.OutQuint); From 02d8e3a11e4d245f7b5587c59b4217418718d00a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 23 May 2023 18:48:10 +0900 Subject: [PATCH 0953/1400] Mark `FullscreenOverlay`'s shadow effect as `Hollow` to save on shader overhead --- osu.Game/Overlays/FullscreenOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 2cc8354e50..007791387c 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -56,6 +56,7 @@ namespace osu.Game.Overlays { Colour = Color4.Black.Opacity(0), Type = EdgeEffectType.Shadow, + Hollow = true, Radius = 10 }; From 7658536b5afcd3b499aa0b5b5bc70ba5b22b88ec Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 23 May 2023 19:32:19 +0900 Subject: [PATCH 0954/1400] Fix CI issues --- .../Rulesets/Scoring/ScoreProcessorTest.cs | 14 -------------- osu.Game/Screens/Ranking/ScorePanelList.cs | 4 ---- 2 files changed, 18 deletions(-) diff --git a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs index f51a4ad52b..e5e96d2033 100644 --- a/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs +++ b/osu.Game.Tests/Rulesets/Scoring/ScoreProcessorTest.cs @@ -289,20 +289,6 @@ namespace osu.Game.Tests.Rulesets.Scoring Assert.That(actual, Is.EqualTo(expected).Within(Precision.FLOAT_EPSILON)); } - private class TestRuleset : Ruleset - { - public override IEnumerable GetModsFor(ModType type) => throw new NotImplementedException(); - - public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new NotImplementedException(); - - public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException(); - - public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new NotImplementedException(); - - public override string Description => string.Empty; - public override string ShortName => string.Empty; - } - private class TestJudgement : Judgement { public override HitResult MaxResult { get; } diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs index 1f93389e94..b75f3d86ff 100644 --- a/osu.Game/Screens/Ranking/ScorePanelList.cs +++ b/osu.Game/Screens/Ranking/ScorePanelList.cs @@ -9,7 +9,6 @@ using System.Diagnostics; using System.Linq; using System.Threading; using JetBrains.Annotations; -using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -67,9 +66,6 @@ namespace osu.Game.Screens.Ranking public readonly Bindable SelectedScore = new Bindable(); - [Resolved] - private ScoreManager scoreManager { get; set; } - private readonly CancellationTokenSource loadCancellationSource = new CancellationTokenSource(); private readonly Flow flow; private readonly Scroll scroll; From ebda35c3c9a896861ec526bad90ebc2e154b3131 Mon Sep 17 00:00:00 2001 From: Johannes vd Berg Date: Tue, 23 May 2023 12:57:25 +0200 Subject: [PATCH 0955/1400] Add ghost ticks to exhibit current divisor on `BeatDivisorControl` --- .../Compose/Components/BeatDivisorControl.cs | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 3bfe81e6a7..431fb2f659 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -398,28 +398,25 @@ namespace osu.Game.Screens.Edit.Compose.Components ClearInternal(); CurrentNumber.ValueChanged -= moveMarker; - foreach (int divisor in beatDivisor.ValidDivisors.Value.Presets) + int largestDivisor = beatDivisor.ValidDivisors.Value.Presets.Max(); + for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { - AddInternal(new Tick(divisor) + int divisor = largestDivisor; + foreach (int validDivisor in beatDivisor.ValidDivisors.Value.Presets) + { + if (divisor > validDivisor && (tickIndex * validDivisor) % largestDivisor == 0) + divisor = validDivisor; + } + bool solidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; + AddInternal(new Tick(solidTick, divisor) { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, Colour = BindableBeatDivisor.GetColourFor(divisor, colours), - X = getMappedPosition(divisor), + X = tickIndex / (float)largestDivisor, }); } - - // Add a fake 1/1 at the end to give context. - AddInternal(new Tick(1) - { - Anchor = Anchor.CentreRight, - Origin = Anchor.Centre, - Depth = float.MaxValue, - Alpha = 0.05f, - Colour = BindableBeatDivisor.GetColourFor(1, colours), - }); - AddInternal(marker = new Marker()); CurrentNumber.ValueChanged += moveMarker; CurrentNumber.TriggerChange(); @@ -428,6 +425,12 @@ namespace osu.Game.Screens.Edit.Compose.Components private void moveMarker(ValueChangedEvent divisor) { marker.MoveToX(getMappedPosition(divisor.NewValue), 100, Easing.OutQuint); + + foreach (Tick child in InternalChildren.OfType()) + { + float newAlpha = child.Solid ? 1f : divisor.NewValue % child.Divisor == 0 ? 0.2f : 0f; + child.FadeTo(newAlpha); + } } protected override void UpdateValue(float value) @@ -497,8 +500,12 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class Tick : Circle { - public Tick(int divisor) + public bool Solid; + public int Divisor; + public Tick(bool solid, int divisor) { + Solid = solid; + Divisor = divisor; Size = new Vector2(6f, 12) * BindableBeatDivisor.GetSize(divisor); InternalChild = new Box { RelativeSizeAxes = Axes.Both }; } From 37a796306d65a5c940d8cd715021083bdef9990a Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 14:30:35 +0200 Subject: [PATCH 0956/1400] Small format & comment --- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 431fb2f659..04cc736e7d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -402,13 +402,15 @@ namespace osu.Game.Screens.Edit.Compose.Components for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { int divisor = largestDivisor; + // Find lowest divisor that the tick fits into foreach (int validDivisor in beatDivisor.ValidDivisors.Value.Presets) { if (divisor > validDivisor && (tickIndex * validDivisor) % largestDivisor == 0) divisor = validDivisor; } - bool solidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; - AddInternal(new Tick(solidTick, divisor) + + bool isSolidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; + AddInternal(new Tick(isSolidTick, divisor) { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, @@ -417,6 +419,7 @@ namespace osu.Game.Screens.Edit.Compose.Components X = tickIndex / (float)largestDivisor, }); } + AddInternal(marker = new Marker()); CurrentNumber.ValueChanged += moveMarker; CurrentNumber.TriggerChange(); From 1b32370c6a489ec618e7022b197f3c82518a183a Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 15:05:38 +0200 Subject: [PATCH 0957/1400] Remove duplicate code by making `GetDivisorForBeatIndex` method more general --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 7 +++++-- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 8 +------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index aa8e202e22..f1b97571bd 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -154,12 +154,15 @@ namespace osu.Game.Screens.Edit /// /// The 0-based beat index. /// The beat divisor. + /// The list of valid divisors which can be chosen from. Assumes ordered from low to high. /// The applicable divisor. - public static int GetDivisorForBeatIndex(int index, int beatDivisor) + public static int GetDivisorForBeatIndex(int index, int beatDivisor, int[] validDivisors = null) { + validDivisors ??= PREDEFINED_DIVISORS; + int beat = index % beatDivisor; - foreach (int divisor in PREDEFINED_DIVISORS) + foreach (int divisor in validDivisors) { if ((beat * divisor) % beatDivisor == 0) return divisor; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 04cc736e7d..2dd5791943 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -401,13 +401,7 @@ namespace osu.Game.Screens.Edit.Compose.Components int largestDivisor = beatDivisor.ValidDivisors.Value.Presets.Max(); for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { - int divisor = largestDivisor; - // Find lowest divisor that the tick fits into - foreach (int validDivisor in beatDivisor.ValidDivisors.Value.Presets) - { - if (divisor > validDivisor && (tickIndex * validDivisor) % largestDivisor == 0) - divisor = validDivisor; - } + int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(tickIndex, largestDivisor, (int[])beatDivisor.ValidDivisors.Value.Presets); bool isSolidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; AddInternal(new Tick(isSolidTick, divisor) From 7b1e8ede54498bf66d54965769220dc626240c1f Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 15:11:27 +0200 Subject: [PATCH 0958/1400] Small format --- osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 2dd5791943..1af7d25dcd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -402,8 +402,8 @@ namespace osu.Game.Screens.Edit.Compose.Components for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(tickIndex, largestDivisor, (int[])beatDivisor.ValidDivisors.Value.Presets); - bool isSolidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; + AddInternal(new Tick(isSolidTick, divisor) { Anchor = Anchor.CentreLeft, From 921d7e4d89351a50fe6ec4e65f1ec01b3d650a36 Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 16:46:08 +0200 Subject: [PATCH 0959/1400] More fitting tests for new layout --- .../Editing/TestSceneBeatDivisorControl.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index c3d5ecac5c..b74e9f436b 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -65,17 +65,24 @@ namespace osu.Game.Tests.Visual.Editing InputManager.MoveMouseTo(tickMarkerHead.ScreenSpaceDrawQuad.Centre); InputManager.PressButton(MouseButton.Left); }); - AddStep("move to 8 and release", () => + AddStep("move to 1", () => InputManager.MoveMouseTo(getPositionForDivisor(1))); + AddStep("move to 16 and release", () => { - InputManager.MoveMouseTo(tickSliderBar.ScreenSpaceDrawQuad.Centre); + InputManager.MoveMouseTo(getPositionForDivisor(16)); InputManager.ReleaseButton(MouseButton.Left); }); - AddAssert("divisor is 8", () => bindableBeatDivisor.Value == 8); + AddAssert("divisor is 16", () => bindableBeatDivisor.Value == 16); AddStep("hold marker", () => InputManager.PressButton(MouseButton.Left)); - AddStep("move to 16", () => InputManager.MoveMouseTo(getPositionForDivisor(16))); - AddStep("move to ~10 and release", () => + AddStep("move to ~6 and release", () => + { + InputManager.MoveMouseTo(getPositionForDivisor(6)); + InputManager.ReleaseButton(MouseButton.Left); + }); + AddAssert("divisor clamped to 8", () => bindableBeatDivisor.Value == 8); + AddStep("move to ~10 and click", () => { InputManager.MoveMouseTo(getPositionForDivisor(10)); + InputManager.PressButton(MouseButton.Left); InputManager.ReleaseButton(MouseButton.Left); }); AddAssert("divisor clamped to 8", () => bindableBeatDivisor.Value == 8); From fa00f8b92a56db6669835efa70131e69308c9f67 Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 16:46:40 +0200 Subject: [PATCH 0960/1400] replace manual code with existing method --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index b74e9f436b..a4b36ef93a 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -90,12 +90,11 @@ namespace osu.Game.Tests.Visual.Editing private Vector2 getPositionForDivisor(int divisor) { - float relativePosition = (float)Math.Clamp(divisor, 0, 16) / 16; - var sliderDrawQuad = tickSliderBar.ScreenSpaceDrawQuad; - return new Vector2( - sliderDrawQuad.TopLeft.X + sliderDrawQuad.Width * relativePosition, - sliderDrawQuad.Centre.Y - ); + float localX = 1 - 1 / (float)divisor; + return tickSliderBar.ToScreenSpace(new Vector2( + localX, + 0.5f + )); } [Test] From b5f8093941873b6aa95bc62a61f7eb5d29e9ce52 Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 17:59:07 +0200 Subject: [PATCH 0961/1400] Use `RangePadding` to align mouse with slider --- osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs | 4 ++-- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index a4b36ef93a..353acfa4ba 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -90,10 +90,10 @@ namespace osu.Game.Tests.Visual.Editing private Vector2 getPositionForDivisor(int divisor) { - float localX = 1 - 1 / (float)divisor; + float localX = (1 - 1 / (float)divisor) * tickSliderBar.UsableWidth + tickSliderBar.RangePadding; return tickSliderBar.ToScreenSpace(new Vector2( localX, - 0.5f + tickSliderBar.DrawHeight / 2 )); } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 3bfe81e6a7..cec9806e94 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -383,7 +383,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { CurrentNumber.BindTo(this.beatDivisor = beatDivisor); - Padding = new MarginPadding { Horizontal = 5 }; + RangePadding = 5; + Padding = new MarginPadding { Horizontal = RangePadding }; } protected override void LoadComplete() From c5ef3ae1811f9216c2023c92de67ae2d548f4a66 Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 18:44:20 +0200 Subject: [PATCH 0962/1400] Code styling --- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 1af7d25dcd..4c3c9872a0 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -425,7 +425,7 @@ namespace osu.Game.Screens.Edit.Compose.Components foreach (Tick child in InternalChildren.OfType()) { - float newAlpha = child.Solid ? 1f : divisor.NewValue % child.Divisor == 0 ? 0.2f : 0f; + float newAlpha = child.IsSolid ? 1f : divisor.NewValue % child.Divisor == 0 ? 0.2f : 0f; child.FadeTo(newAlpha); } } @@ -497,11 +497,11 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class Tick : Circle { - public bool Solid; + public bool IsSolid; public int Divisor; - public Tick(bool solid, int divisor) + public Tick(bool isSolid, int divisor) { - Solid = solid; + IsSolid = isSolid; Divisor = divisor; Size = new Vector2(6f, 12) * BindableBeatDivisor.GetSize(divisor); InternalChild = new Box { RelativeSizeAxes = Axes.Both }; From 7fe19d1992633fc13e3cf68c35fb21e3734d39dd Mon Sep 17 00:00:00 2001 From: Gyoshi Date: Tue, 23 May 2023 18:45:49 +0200 Subject: [PATCH 0963/1400] `Last` instead of `Max` divisor to match code elsewhere --- osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 4c3c9872a0..4982ab9ef2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -398,7 +398,7 @@ namespace osu.Game.Screens.Edit.Compose.Components ClearInternal(); CurrentNumber.ValueChanged -= moveMarker; - int largestDivisor = beatDivisor.ValidDivisors.Value.Presets.Max(); + int largestDivisor = beatDivisor.ValidDivisors.Value.Presets.Last(); for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(tickIndex, largestDivisor, (int[])beatDivisor.ValidDivisors.Value.Presets); From 0ea3eea8d6acad4049dc7da12a6961f3e6e8454b Mon Sep 17 00:00:00 2001 From: Robin Oger Date: Tue, 23 May 2023 19:21:44 +0200 Subject: [PATCH 0964/1400] Make GameplayMenuOverlay translatable This allows translator to translate the pause and failed in game menus --- .../GameplayMenuOverlayStrings.cs | 49 +++++++++++++++++++ osu.Game/Screens/Play/FailOverlay.cs | 10 ++-- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 7 +-- osu.Game/Screens/Play/PauseOverlay.cs | 12 +++-- 4 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Localisation/GameplayMenuOverlayStrings.cs diff --git a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs new file mode 100644 index 0000000000..bba16e014a --- /dev/null +++ b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs @@ -0,0 +1,49 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class GameplayMenuOverlayStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.GameplayMenuOverlay"; + + /// + /// "Continue" + /// + public static LocalisableString Continue => new TranslatableString(getKey(@"continue"), @"Continue"); + + /// + /// "Retry" + /// + public static LocalisableString Retry => new TranslatableString(getKey(@"retry"), @"Retry"); + + /// + /// "Quit" + /// + public static LocalisableString Quit => new TranslatableString(getKey(@"quit"), @"Quit"); + + /// + /// "failed" + /// + public static LocalisableString FailedHeader => new TranslatableString(getKey(@"failed_header"), @"failed"); + + /// + /// "paused" + /// + public static LocalisableString PausedHeader => new TranslatableString(getKey(@"paused_header"), @"paused"); + + /// + /// "you're dead, try again?" + /// + public static LocalisableString FailedDescription => new TranslatableString(getKey(@"failed_description"), @"you're dead, try again?"); + + /// + /// "you're not going to do what i think you're going to do, are ya?" + /// + public static LocalisableString PausedDescription => new TranslatableString(getKey(@"paused_description"), @"you're not going to do what i think you're going to do, are ya?"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 4fbc937b59..5b026a4c06 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -15,6 +15,8 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Screens.Play { @@ -22,14 +24,14 @@ namespace osu.Game.Screens.Play { public Func> SaveReplay; - public override string Header => "failed"; - public override string Description => "you're dead, try again?"; + public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader; + public override LocalisableString Description => GameplayMenuOverlayStrings.FailedDescription; [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); - AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); // from #10339 maybe this is a better visual effect Add(new Container { diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 81146a4ea6..b83d17fdb2 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -15,6 +15,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -51,9 +52,9 @@ namespace osu.Game.Screens.Play /// protected virtual Action SelectAction => () => InternalButtons.Selected?.TriggerClick(); - public abstract string Header { get; } + public abstract LocalisableString Header { get; } - public abstract string Description { get; } + public abstract LocalisableString Description { get; } protected SelectionCycleFillFlowContainer InternalButtons; public IReadOnlyList Buttons => InternalButtons; @@ -170,7 +171,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseMove(MouseMoveEvent e) => true; - protected void AddButton(string text, Color4 colour, Action action) + protected void AddButton(LocalisableString text, Color4 colour, Action action) { var button = new Button { diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index db42998c45..c3c1c493d4 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -9,9 +9,11 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Skinning; using osuTK.Graphics; @@ -23,8 +25,8 @@ namespace osu.Game.Screens.Play public override bool IsPresent => base.IsPresent || pauseLoop.IsPlaying; - public override string Header => "paused"; - public override string Description => "you're not going to do what i think you're going to do, are ya?"; + public override LocalisableString Header => GameplayMenuOverlayStrings.PausedHeader; + public override LocalisableString Description => GameplayMenuOverlayStrings.PausedDescription; private SkinnableSound pauseLoop; @@ -33,9 +35,9 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Continue", colours.Green, () => OnResume?.Invoke()); - AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); - AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Continue, colours.Green, () => OnResume?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("Gameplay/pause-loop")) { From a24da89908958d1879851b5a756e11f2b48402b4 Mon Sep 17 00:00:00 2001 From: Robin Oger Date: Tue, 23 May 2023 21:37:12 +0200 Subject: [PATCH 0965/1400] Change to sentence casing See: https://github.com/ppy/osu/pull/23640#discussion_r1202879352 --- osu.Game/Localisation/GameplayMenuOverlayStrings.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs index bba16e014a..c89c35775b 100644 --- a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs +++ b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs @@ -35,14 +35,14 @@ namespace osu.Game.Localisation public static LocalisableString PausedHeader => new TranslatableString(getKey(@"paused_header"), @"paused"); /// - /// "you're dead, try again?" + /// "You're dead, try again?" /// - public static LocalisableString FailedDescription => new TranslatableString(getKey(@"failed_description"), @"you're dead, try again?"); + public static LocalisableString FailedDescription => new TranslatableString(getKey(@"failed_description"), @"You're dead, try again?"); /// - /// "you're not going to do what i think you're going to do, are ya?" + /// "You're not going to do what i think you're going to do, are ya?" /// - public static LocalisableString PausedDescription => new TranslatableString(getKey(@"paused_description"), @"you're not going to do what i think you're going to do, are ya?"); + public static LocalisableString PausedDescription => new TranslatableString(getKey(@"paused_description"), @"You're not going to do what i think you're going to do, are ya?"); private static string getKey(string key) => $@"{prefix}:{key}"; } From 067328233cf5715e8ce00936a6ce6bbe1b9795cd Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 23 May 2023 13:14:57 -0700 Subject: [PATCH 0966/1400] Remove `OsuScreen.ApplyLogoArrivingDefaults()` --- osu.Game/Screens/OsuScreen.cs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index bc4cc2b00f..9c098794a6 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -233,7 +233,13 @@ namespace osu.Game.Screens /// protected virtual void LogoArriving(OsuLogo logo, bool resuming) { - ApplyLogoArrivingDefaults(logo); + logo.Action = null; + logo.FadeOut(300, Easing.OutQuint); + logo.Anchor = Anchor.TopLeft; + logo.Origin = Anchor.Centre; + logo.RelativePositionAxes = Axes.Both; + logo.Triangles = true; + logo.Ripple = true; } private void applyArrivingDefaults(bool isResuming) @@ -244,22 +250,6 @@ namespace osu.Game.Screens }, true); } - /// - /// Applies default animations to an arriving logo. - /// Todo: This should not exist. - /// - /// The logo to apply animations to. - public static void ApplyLogoArrivingDefaults(OsuLogo logo) - { - logo.Action = null; - logo.FadeOut(300, Easing.OutQuint); - logo.Anchor = Anchor.TopLeft; - logo.Origin = Anchor.Centre; - logo.RelativePositionAxes = Axes.Both; - logo.Triangles = true; - logo.Ripple = true; - } - private void onExitingLogo() { logo?.AppendAnimatingAction(() => LogoExiting(logo), false); From e5451d1d79c7cceb3479515b8611c0954706f95c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 12:38:27 +0900 Subject: [PATCH 0967/1400] Centralise definition of overlay shadow opacity and reduce slightly --- osu.Game/Graphics/Containers/WaveContainer.cs | 1 + osu.Game/Overlays/FullscreenOverlay.cs | 2 +- osu.Game/Overlays/NotificationOverlay.cs | 2 +- osu.Game/Overlays/SettingsPanel.cs | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 952ef3f182..05a666721a 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -17,6 +17,7 @@ namespace osu.Game.Graphics.Containers { public const float APPEAR_DURATION = 800; public const float DISAPPEAR_DURATION = 500; + public const float SHADOW_OPACITY = 0.2f; private const Easing easing_show = Easing.OutSine; private const Easing easing_hide = Easing.InSine; diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 007791387c..032821f215 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -102,7 +102,7 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); + FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); } protected override void PopOut() diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 4a69fb6240..f2eefb6e4b 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -210,7 +210,7 @@ namespace osu.Game.Overlays this.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); mainContent.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); - mainContent.FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); + mainContent.FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); toastTray.FlushAllToasts(); } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 382423eb57..d571557993 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -115,6 +115,7 @@ namespace osu.Game.Overlays Hollow = true, Radius = 10 }, + MaskingSmoothness = 0, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), SelectedSection = { BindTarget = CurrentSection }, @@ -166,7 +167,7 @@ namespace osu.Game.Overlays ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); - SectionsContainer.FadeEdgeEffectTo(0.4f, WaveContainer.APPEAR_DURATION, Easing.Out); + SectionsContainer.FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); // delay load enough to ensure it doesn't overlap with the initial animation. // this is done as there is still a brief stutter during load completion which is more visible if the transition is in progress. From 561b759bf980216beca1ff2639da1018bc05c742 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 13:49:29 +0900 Subject: [PATCH 0968/1400] Tidy up implementation and ensure non-solid ticks start at zero alpha --- .../Compose/Components/BeatDivisorControl.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 07330a6e10..432c5ea280 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -400,12 +400,13 @@ namespace osu.Game.Screens.Edit.Compose.Components CurrentNumber.ValueChanged -= moveMarker; int largestDivisor = beatDivisor.ValidDivisors.Value.Presets.Last(); + for (int tickIndex = 0; tickIndex <= largestDivisor; tickIndex++) { int divisor = BindableBeatDivisor.GetDivisorForBeatIndex(tickIndex, largestDivisor, (int[])beatDivisor.ValidDivisors.Value.Presets); bool isSolidTick = divisor * (largestDivisor - tickIndex) == largestDivisor; - AddInternal(new Tick(isSolidTick, divisor) + AddInternal(new Tick(divisor, isSolidTick) { Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, @@ -424,10 +425,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { marker.MoveToX(getMappedPosition(divisor.NewValue), 100, Easing.OutQuint); - foreach (Tick child in InternalChildren.OfType()) + foreach (Tick tick in InternalChildren.OfType().Where(t => !t.AlwaysDisplayed)) { - float newAlpha = child.IsSolid ? 1f : divisor.NewValue % child.Divisor == 0 ? 0.2f : 0f; - child.FadeTo(newAlpha); + tick.FadeTo(divisor.NewValue % tick.Divisor == 0 ? 0.2f : 0f, 100, Easing.OutQuint); } } @@ -498,13 +498,18 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class Tick : Circle { - public bool IsSolid; - public int Divisor; - public Tick(bool isSolid, int divisor) + public readonly bool AlwaysDisplayed; + + public readonly int Divisor; + + public Tick(int divisor, bool alwaysDisplayed) { - IsSolid = isSolid; + AlwaysDisplayed = alwaysDisplayed; Divisor = divisor; + Size = new Vector2(6f, 12) * BindableBeatDivisor.GetSize(divisor); + Alpha = alwaysDisplayed ? 1 : 0; + InternalChild = new Box { RelativeSizeAxes = Axes.Both }; } } From e68ba6366c88554db3bee4332be5f1563e4257c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 14:04:10 +0900 Subject: [PATCH 0969/1400] Update new usages of "soft" to use the new constant --- .../Editor/TestSceneSliderSplitting.cs | 2 +- .../TestSceneDrumSampleTriggerSource.cs | 24 +++++++++---------- .../TestSceneHitObjectSampleAdjustments.cs | 10 ++++---- .../TestSceneGameplaySampleTriggerSource.cs | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs index a104433ea9..605771fb20 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { if (slider is null) return; - sample = new HitSampleInfo("hitwhistle", "soft", volume: 70); + sample = new HitSampleInfo("hitwhistle", HitSampleInfo.BANK_SOFT, volume: 70); slider.Samples.Add(sample.With()); }); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index 74da69e3eb..287d90b406 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.Tests StartTime = 100, Samples = new List { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft") + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT) } }; hit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -100,13 +100,13 @@ namespace osu.Game.Rulesets.Taiko.Tests }); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); - checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); - checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); AddStep("seek past hit", () => manualClock.CurrentTime = 200); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); - checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); - checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); } [Test] @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Taiko.Tests EndTime = 1100, Samples = new List { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft") + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT) } }; drumRoll.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -192,18 +192,18 @@ namespace osu.Game.Rulesets.Taiko.Tests }); AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); - checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); - checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); - checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); - checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); - checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "soft"); - checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "soft"); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); } [Test] diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index 0581ff269c..eb39221211 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Editing Position = (OsuPlayfield.BASE_SIZE + new Vector2(100, 0)) / 2, Samples = new List { - new HitSampleInfo(HitSampleInfo.HIT_NORMAL, "soft", volume: 60) + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT, volume: 60) } }); }); @@ -67,14 +67,14 @@ namespace osu.Game.Tests.Visual.Editing hitObjectHasSampleBank(0, "normal"); hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP); - hitObjectHasSampleBank(1, "soft"); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT); hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_CLAP); AddStep("remove clap addition", () => InputManager.Key(Key.R)); hitObjectHasSampleBank(0, "normal"); hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL); - hitObjectHasSampleBank(1, "soft"); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT); hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL); } @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Editing public void TestUndo() { clickSamplePiece(1); - samplePopoverHasSingleBank("soft"); + samplePopoverHasSingleBank(HitSampleInfo.BANK_SOFT); samplePopoverHasSingleVolume(60); setVolumeViaPopover(90); @@ -178,7 +178,7 @@ namespace osu.Game.Tests.Visual.Editing { for (int i = 0; i < h.Samples.Count; i++) { - h.Samples[i] = h.Samples[i].With(newBank: "soft"); + h.Samples[i] = h.Samples[i].With(newBank: HitSampleInfo.BANK_SOFT); } } }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index bf69da8c12..e52ec6f8cc 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Gameplay { StartTime = t += spacing, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 }), - Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, "soft") }, + Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, HitSampleInfo.BANK_SOFT) }, }, }); From a9ba16a2be5d8355248d658ddb90867799dc86ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 14:20:38 +0900 Subject: [PATCH 0970/1400] Update to support non-control-point sample changes --- .../Components/ComposeBlueprintContainer.cs | 4 ++-- .../Components/EditorSelectionHandler.cs | 23 ++++--------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index b4f2236847..3f3b4ad327 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -199,12 +199,12 @@ namespace osu.Game.Screens.Edit.Compose.Components private void bankChanged(string bankName, TernaryState state) { - if (currentPlacement == null) return; + if (CurrentPlacement == null) return; switch (state) { case TernaryState.True: - currentPlacement.HitObject.SampleControlPoint.SampleBank = bankName; + CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); break; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index 5d2eb33d8d..fa3a4cddaa 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { // Never remove a sample bank. // These are basically radio buttons, not toggles. - if (SelectedItems.All(h => h.SampleControlPoint.SampleBank == bankName)) + if (SelectedItems.All(h => h.Samples.All(s => s.Bank == bankName))) bindable.Value = TernaryState.True; } @@ -167,7 +167,7 @@ namespace osu.Game.Screens.Edit.Compose.Components foreach ((string bankName, var bindable) in SelectionBankStates) { - bindable.Value = GetStateFromSelection(SelectedItems, h => h.SampleControlPoint.SampleBank == bankName); + bindable.Value = GetStateFromSelection(SelectedItems, h => h.Samples.All(s => s.Bank == bankName)); } } @@ -183,25 +183,10 @@ namespace osu.Game.Screens.Edit.Compose.Components { EditorBeatmap.PerformOnSelection(h => { - if (h.SampleControlPoint.SampleBank == bankName) + if (h.Samples.All(s => s.Bank == bankName)) return; - h.SampleControlPoint.SampleBank = bankName; - EditorBeatmap.Update(h); - }); - } - - /// - /// Removes a sample bank from all selected s. - /// - /// The name of the sample bank. - public void RemoveSampleBank(string bankName) - { - EditorBeatmap.PerformOnSelection(h => - { - if (h.SampleControlPoint.SampleBank == bankName) - h.SampleControlPoint.SampleBankBindable.SetDefault(); - + h.Samples = h.Samples.Select(s => s.With(newBank: bankName)).ToList(); EditorBeatmap.Update(h); }); } From a22ad98cb79567018833c14e9cc845e02bf564cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 14:56:11 +0900 Subject: [PATCH 0971/1400] Fix hotkeys not actually working --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 62c3211e85..106ffc8ee7 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -288,7 +288,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnKeyDown(KeyDownEvent e) { - if (e.ControlPressed || e.AltPressed || e.SuperPressed || e.ShiftPressed) + if (e.ControlPressed || e.AltPressed || e.SuperPressed) return false; if (checkLeftToggleFromKey(e.Key, out int leftIndex)) From fc22c754641b2b11c4f4ecaf714df70cf1fd6b0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 16:14:05 +0900 Subject: [PATCH 0972/1400] Don't use `switch` for single `case` statement --- .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 3f3b4ad327..d2dd83eb1a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -201,12 +201,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (CurrentPlacement == null) return; - switch (state) - { - case TernaryState.True: - CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); - break; - } + if (state == TernaryState.True) + CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); } public readonly Bindable NewCombo = new Bindable { Description = "New Combo" }; From 3a05dffa506aa0babb6dec23356a8cc21c763d10 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 17:11:12 +0900 Subject: [PATCH 0973/1400] Add "auto" bank selection during placement --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 18 +++++++++++++----- .../Components/ComposeBlueprintContainer.cs | 2 ++ .../Components/EditorSelectionHandler.cs | 16 +++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 551e557599..a0a04c13d0 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -32,6 +32,11 @@ namespace osu.Game.Rulesets.Edit /// public PlacementState PlacementActive { get; private set; } + /// + /// Whether the sample bank should be taken from the previous hit object. + /// + public bool AutomaticBankAssignment; + /// /// The that is being placed. /// @@ -86,11 +91,6 @@ namespace osu.Game.Rulesets.Edit /// Whether this call is committing a value for HitObject.StartTime and continuing with further adjustments. protected void BeginPlacement(bool commitStart = false) { - // Take the hitnormal sample of the last hit object - var lastHitNormal = getPreviousHitObject()?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); - if (lastHitNormal != null) - HitObject.Samples[0] = lastHitNormal; - placementHandler.BeginPlacement(HitObject); if (commitStart) PlacementActive = PlacementState.Active; @@ -155,6 +155,14 @@ namespace osu.Game.Rulesets.Edit if (HitObject is IHasComboInformation comboInformation) comboInformation.UpdateComboInformation(getPreviousHitObject() as IHasComboInformation); } + + if (AutomaticBankAssignment) + { + // Take the hitnormal sample of the last hit object + var lastHitNormal = getPreviousHitObject()?.Samples?.FirstOrDefault(o => o.Name == HitSampleInfo.HIT_NORMAL); + if (lastHitNormal != null) + HitObject.Samples[0] = lastHitNormal; + } } /// diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index d2dd83eb1a..25babae6ff 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -201,6 +201,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (CurrentPlacement == null) return; + if (bankName == EditorSelectionHandler.HIT_BANK_AUTO) + CurrentPlacement.AutomaticBankAssignment = state == TernaryState.True; if (state == TernaryState.True) CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); } diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index fa3a4cddaa..dc7e12ea93 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -21,6 +21,12 @@ namespace osu.Game.Screens.Edit.Compose.Components { public partial class EditorSelectionHandler : SelectionHandler { + /// + /// A special bank name that is only used in the editor UI. + /// When selected and in placement mode, the bank of the last hit object will always be used. + /// + public const string HIT_BANK_AUTO = "auto"; + [Resolved] protected EditorBeatmap EditorBeatmap { get; private set; } @@ -59,7 +65,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// private void createStateBindables() { - foreach (string bankName in HitSampleInfo.AllBanks) + foreach (string bankName in HitSampleInfo.AllBanks.Prepend(HIT_BANK_AUTO)) { var bindable = new Bindable { @@ -100,6 +106,14 @@ namespace osu.Game.Screens.Edit.Compose.Components } else { + // Auto should just not apply if there's a selection already made. + // Maybe we could make it a disabled button in the future, but right now the editor buttons don't support disabled state. + if (bankName == HIT_BANK_AUTO) + { + bindable.Value = TernaryState.False; + break; + } + AddSampleBank(bankName); } From 8e5ba2208d29451882378130e2be0854a7b142a6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 17:33:48 +0900 Subject: [PATCH 0974/1400] Add test coverage of new hotkeys --- .../TestSceneHitObjectSampleAdjustments.cs | 100 +++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index eb39221211..b0b51a5dbd 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; @@ -170,7 +171,7 @@ namespace osu.Game.Tests.Visual.Editing } [Test] - public void TestMultipleSelectionWithSameSampleBank() + public void TestPopoverMultipleSelectionWithSameSampleBank() { AddStep("unify sample bank", () => { @@ -204,7 +205,7 @@ namespace osu.Game.Tests.Visual.Editing } [Test] - public void TestMultipleSelectionWithDifferentSampleBank() + public void TestPopoverMultipleSelectionWithDifferentSampleBank() { AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); clickSamplePiece(0); @@ -226,6 +227,101 @@ namespace osu.Game.Tests.Visual.Editing samplePopoverHasSingleBank(HitSampleInfo.BANK_NORMAL); } + [Test] + public void TestHotkeysMultipleSelectionWithSameSampleBank() + { + AddStep("unify sample bank", () => + { + foreach (var h in EditorBeatmap.HitObjects) + { + for (int i = 0; i < h.Samples.Count; i++) + { + h.Samples[i] = h.Samples[i].With(newBank: HitSampleInfo.BANK_SOFT); + } + } + }); + + AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects)); + + hitObjectHasSampleBank(0, HitSampleInfo.BANK_SOFT); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_SOFT); + + AddStep("Press normal bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.W); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + hitObjectHasSampleBank(0, HitSampleInfo.BANK_NORMAL); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_NORMAL); + + AddStep("Press drum bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.R); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM); + + AddStep("Press auto bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Q); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + // Should be a noop. + hitObjectHasSampleBank(0, HitSampleInfo.BANK_DRUM); + hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM); + } + + [Test] + public void TestHotkeysDuringPlacement() + { + AddStep("Enter placement mode", () => InputManager.Key(Key.Number2)); + AddStep("Move mouse to centre", () => InputManager.MoveMouseTo(Editor.ChildrenOfType().First().ScreenSpaceDrawQuad.Centre)); + + AddStep("Move between two objects", () => EditorClock.Seek(250)); + + AddStep("Press normal bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.W); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + checkPlacementSample(HitSampleInfo.BANK_NORMAL); + + AddStep("Press drum bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.R); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + checkPlacementSample(HitSampleInfo.BANK_DRUM); + + AddStep("Press auto bank shortcut", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Q); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + + checkPlacementSample(HitSampleInfo.BANK_NORMAL); + + AddStep("Move after second object", () => EditorClock.Seek(750)); + checkPlacementSample(HitSampleInfo.BANK_SOFT); + + AddStep("Move to first object", () => EditorClock.Seek(0)); + checkPlacementSample(HitSampleInfo.BANK_NORMAL); + + void checkPlacementSample(string expected) => AddAssert($"Placement sample is {expected}", () => EditorBeatmap.PlacementObject.Value.Samples.First().Bank, () => Is.EqualTo(expected)); + } + private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} sample piece", () => { var samplePiece = this.ChildrenOfType().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex)); From 8ada8b1c8cee225a02b99232b77d4f10f42c6dca Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 17:48:34 +0900 Subject: [PATCH 0975/1400] Remove description line from pause/fail screen These were in the designs but read pretty bad / evil. I can't think of any text to go in their place that makes sense, so let's just nuke it. --- osu.Game/Screens/Play/FailOverlay.cs | 1 - osu.Game/Screens/Play/GameplayMenuOverlay.cs | 10 ---------- osu.Game/Screens/Play/PauseOverlay.cs | 1 - 3 files changed, 12 deletions(-) diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 4fbc937b59..f1dd2abc4a 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -23,7 +23,6 @@ namespace osu.Game.Screens.Play public Func> SaveReplay; public override string Header => "failed"; - public override string Description => "you're dead, try again?"; [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 81146a4ea6..de0c4fe4f1 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -53,8 +53,6 @@ namespace osu.Game.Screens.Play public abstract string Header { get; } - public abstract string Description { get; } - protected SelectionCycleFillFlowContainer InternalButtons; public IReadOnlyList Buttons => InternalButtons; @@ -107,14 +105,6 @@ namespace osu.Game.Screens.Play Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f) }, - new OsuSpriteText - { - Text = Description, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f) - } } }, InternalButtons = new SelectionCycleFillFlowContainer diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index db42998c45..984f43d77a 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -24,7 +24,6 @@ namespace osu.Game.Screens.Play public override bool IsPresent => base.IsPresent || pauseLoop.IsPlaying; public override string Header => "paused"; - public override string Description => "you're not going to do what i think you're going to do, are ya?"; private SkinnableSound pauseLoop; From 456f3005d61292a714d43d4acb82d673a5e30677 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 17:58:48 +0900 Subject: [PATCH 0976/1400] Apply nullability to `GameplayMenuOverlay` and use `TextFlowContainer` for text --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 76 ++++++-------------- 1 file changed, 20 insertions(+), 56 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index de0c4fe4f1..f1e10912ac 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; -using Humanizer; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -20,6 +17,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -38,8 +36,8 @@ namespace osu.Game.Screens.Play public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; - public Action OnRetry; - public Action OnQuit; + public Action? OnRetry; + public Action? OnQuit; /// /// Action that is invoked when is triggered. @@ -53,10 +51,13 @@ namespace osu.Game.Screens.Play public abstract string Header { get; } - protected SelectionCycleFillFlowContainer InternalButtons; + protected SelectionCycleFillFlowContainer InternalButtons = null!; public IReadOnlyList Buttons => InternalButtons; - private FillFlowContainer retryCounterContainer; + private TextFlowContainer playInfoText = null!; + + [Resolved] + private GlobalActionContainer globalAction { get; set; } = null!; protected GameplayMenuOverlay() { @@ -84,28 +85,13 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Children = new Drawable[] { - new FillFlowContainer + new OsuSpriteText { + Text = Header, + Font = OsuFont.GetFont(size: 48), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - new OsuSpriteText - { - Text = Header, - Font = OsuFont.GetFont(size: 30), - Spacing = new Vector2(5, 0), - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Colour = colours.Yellow, - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f) - }, - } + Colour = colours.Yellow, }, InternalButtons = new SelectionCycleFillFlowContainer { @@ -122,10 +108,11 @@ namespace osu.Game.Screens.Play Radius = 50 }, }, - retryCounterContainer = new FillFlowContainer + playInfoText = new OsuTextFlowContainer(cp => cp.Font = OsuFont.GetFont(size: 18)) { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, AutoSizeAxes = Axes.Both, } } @@ -147,7 +134,8 @@ namespace osu.Game.Screens.Play return; retries = value; - if (retryCounterContainer != null) + + if (IsLoaded) updateRetryCount(); } } @@ -160,7 +148,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseMove(MouseMoveEvent e) => true; - protected void AddButton(string text, Color4 colour, Action action) + protected void AddButton(string text, Color4 colour, Action? action) { var button = new Button { @@ -212,30 +200,9 @@ namespace osu.Game.Screens.Play // "You've retried 1,065 times in this session" // "You've retried 1 time in this session" - retryCounterContainer.Children = new Drawable[] - { - new OsuSpriteText - { - Text = "You've retried ", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - Font = OsuFont.GetFont(size: 18), - }, - new OsuSpriteText - { - Text = "time".ToQuantity(retries), - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - }, - new OsuSpriteText - { - Text = " in this session", - Shadow = true, - ShadowColour = new Color4(0, 0, 0, 0.25f), - Font = OsuFont.GetFont(size: 18), - } - }; + playInfoText.Clear(); + playInfoText.AddText("Retry count: "); + playInfoText.AddText(retries.ToString(), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); } private partial class Button : DialogButton @@ -250,9 +217,6 @@ namespace osu.Game.Screens.Play } } - [Resolved] - private GlobalActionContainer globalAction { get; set; } - protected override bool Handle(UIEvent e) { switch (e) From 79c9a48ff7b7e926b27be6321569b95baee44860 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 18:09:19 +0900 Subject: [PATCH 0977/1400] Show song progress at pause/fail screen --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 36 ++++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index f1e10912ac..4e1913463c 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -121,7 +122,7 @@ namespace osu.Game.Screens.Play State.ValueChanged += _ => InternalButtons.Deselect(); - updateRetryCount(); + updateInfoText(); } private int retries; @@ -136,11 +137,16 @@ namespace osu.Game.Screens.Play retries = value; if (IsLoaded) - updateRetryCount(); + updateInfoText(); } } - protected override void PopIn() => this.FadeIn(TRANSITION_DURATION, Easing.In); + protected override void PopIn() + { + this.FadeIn(TRANSITION_DURATION, Easing.In); + updateInfoText(); + } + protected override void PopOut() => this.FadeOut(TRANSITION_DURATION, Easing.In); // Don't let mouse down events through the overlay or people can click circles while paused. @@ -195,14 +201,30 @@ namespace osu.Game.Screens.Play { } - private void updateRetryCount() - { - // "You've retried 1,065 times in this session" - // "You've retried 1 time in this session" + [Resolved] + private IGameplayClock? gameplayClock { get; set; } + [Resolved] + private DrawableRuleset? drawableRuleset { get; set; } + + private void updateInfoText() + { playInfoText.Clear(); playInfoText.AddText("Retry count: "); playInfoText.AddText(retries.ToString(), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); + + if (gameplayClock != null && drawableRuleset != null) + { + double firstHitTime = drawableRuleset.Objects.FirstOrDefault()?.StartTime ?? 0; + //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). + double lastHitTime = drawableRuleset.Objects.LastOrDefault()?.GetEndTime() ?? 0; + + double progress = Math.Clamp((gameplayClock.CurrentTime - firstHitTime) / (lastHitTime - firstHitTime), 0, 1); + + playInfoText.NewLine(); + playInfoText.AddText("Song progress: "); + playInfoText.AddText(progress.ToString("0%"), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); + } } private partial class Button : DialogButton From 3b9e1e8a9491c8db305320951c58360622f57846 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 19:16:51 +0900 Subject: [PATCH 0978/1400] Ensure editor selection buttons remain on screen when selection is near edge Addresses https://github.com/ppy/osu/discussions/23599. --- .../Edit/Compose/Components/SelectionBox.cs | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 17790547ed..677b0cd76e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -22,6 +22,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { public const float BORDER_RADIUS = 3; + private const float button_padding = 5; + public Func OnRotation; public Func OnScale; public Func OnFlip; @@ -182,6 +184,13 @@ namespace osu.Game.Screens.Edit.Compose.Components return base.OnKeyDown(e); } + protected override void Update() + { + base.Update(); + + ensureButtonsOnScreen(); + } + private void recreate() { if (LoadState < LoadState.Loading) @@ -234,11 +243,12 @@ namespace osu.Game.Screens.Edit.Compose.Components }, buttons = new FillFlowContainer { - Y = 20, - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, + Height = 30, Direction = FillDirection.Horizontal, + Margin = new MarginPadding(button_padding), Anchor = Anchor.BottomCentre, - Origin = Anchor.Centre + Origin = Anchor.TopCentre } }; @@ -352,5 +362,29 @@ namespace osu.Game.Screens.Edit.Compose.Components if (activeOperations++ == 0) OperationStarted?.Invoke(); } + + private void ensureButtonsOnScreen() + { + buttons.Position = Vector2.Zero; + + var buttonsQuad = buttons.ScreenSpaceDrawQuad; + var thisQuad = ScreenSpaceDrawQuad; + + // Shrink the parent quad to give a bit of padding so the buttons don't stick *right* on the border. + // AABBFloat assumes no rotation. one would hope the whole editor is not being rotated. + var parentQuad = Parent.ScreenSpaceDrawQuad.AABBFloat.Shrink(ToLocalSpace(thisQuad.TopLeft + new Vector2(button_padding * 2))); + + float leftExcess = buttonsQuad.TopLeft.X - parentQuad.TopLeft.X; + float rightExcess = parentQuad.TopRight.X - buttonsQuad.TopRight.X; + float bottomExcess = thisQuad.BottomLeft.Y + buttonsQuad.Height - parentQuad.BottomLeft.Y; + + if (leftExcess < 0) + buttons.X += ToLocalSpace(thisQuad.TopLeft - new Vector2(leftExcess)).X; + else if (rightExcess < 0) + buttons.X -= ToLocalSpace(thisQuad.TopLeft - new Vector2(rightExcess)).X; + + if (bottomExcess > 0) + buttons.Y += ToLocalSpace(thisQuad.TopLeft - new Vector2(bottomExcess)).X; + } } } From b14b1072c29a039c68d2cbe76d05023cd93b7e70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 19:24:14 +0900 Subject: [PATCH 0979/1400] Allow deselecting any selection in the editor using the `Back` binding (escape key) --- .../Compose/Components/BlueprintContainer.cs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index cb7c083d87..0fcf84ec8e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -16,6 +16,7 @@ using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osuTK; using osuTK.Input; @@ -26,7 +27,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// A container which provides a "blueprint" display of items. /// Includes selection and manipulation support via a . /// - public abstract partial class BlueprintContainer : CompositeDrawable, IKeyBindingHandler + public abstract partial class BlueprintContainer : CompositeDrawable, IKeyBindingHandler, IKeyBindingHandler where T : class { protected DragBox DragBox { get; private set; } @@ -279,6 +280,30 @@ namespace osu.Game.Screens.Edit.Compose.Components { } + public bool OnPressed(KeyBindingPressEvent e) + { + if (e.Repeat) + return false; + + switch (e.Action) + { + case GlobalAction.Back: + if (SelectedItems.Count > 0) + { + DeselectAll(); + return true; + } + + break; + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + #region Blueprint Addition/Removal protected virtual void AddBlueprintFor(T item) From 663cec1ff6307a87e527b6ac6d76fa57d3d9b1e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 23:51:28 +0900 Subject: [PATCH 0980/1400] Combine editor navigation test scenes --- .../Editing/TestSceneEditorNavigation.cs | 57 ------------------- .../TestSceneBeatmapEditorNavigation.cs | 44 ++++++++++++++ 2 files changed, 44 insertions(+), 57 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs deleted file mode 100644 index 5914290d40..0000000000 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorNavigation.cs +++ /dev/null @@ -1,57 +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.Linq; -using NUnit.Framework; -using osu.Framework.Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Extensions.ObjectExtensions; -using osu.Game.Beatmaps; -using osu.Game.Database; -using osu.Game.Rulesets.Mania; -using osu.Game.Rulesets.Osu; -using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.GameplayTest; -using osu.Game.Screens.Select; -using osu.Game.Tests.Resources; - -namespace osu.Game.Tests.Visual.Editing -{ - public partial class TestSceneEditorNavigation : OsuGameTestScene - { - [Test] - public void TestEditorGameplayTestAlwaysUsesOriginalRuleset() - { - BeatmapSetInfo beatmapSet = null!; - - AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); - AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); - - AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); - AddUntilStep("wait for song select", - () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) - && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect - && songSelect.IsLoaded); - AddStep("switch ruleset", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo); - - AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); - AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); - AddStep("test gameplay", () => ((Editor)Game.ScreenStack.CurrentScreen).TestGameplay()); - - AddUntilStep("wait for player", () => - { - // notifications may fire at almost any inopportune time and cause annoying test failures. - // relentlessly attempt to dismiss any and all interfering overlays, which includes notifications. - // this is theoretically not foolproof, but it's the best that can be done here. - Game.CloseAllOverlays(); - return Game.ScreenStack.CurrentScreen is EditorPlayer editorPlayer && editorPlayer.IsLoaded; - }); - - AddAssert("current ruleset is osu!", () => Game.Ruleset.Value.Equals(new OsuRuleset().RulesetInfo)); - - AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield())); - AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect); - AddAssert("previous ruleset restored", () => Game.Ruleset.Value.Equals(new ManiaRuleset().RulesetInfo)); - } - } -} diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 603573058e..0307bc7ce5 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -3,15 +3,59 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; +using osu.Game.Screens.Edit.GameplayTest; using osu.Game.Screens.Menu; +using osu.Game.Screens.Select; +using osu.Game.Tests.Resources; namespace osu.Game.Tests.Visual.Navigation { public partial class TestSceneBeatmapEditorNavigation : OsuGameTestScene { + [Test] + public void TestEditorGameplayTestAlwaysUsesOriginalRuleset() + { + BeatmapSetInfo beatmapSet = null!; + + AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); + AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); + + AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); + AddUntilStep("wait for song select", + () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) + && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect + && songSelect.IsLoaded); + AddStep("switch ruleset", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + AddStep("test gameplay", () => ((Editor)Game.ScreenStack.CurrentScreen).TestGameplay()); + + AddUntilStep("wait for player", () => + { + // notifications may fire at almost any inopportune time and cause annoying test failures. + // relentlessly attempt to dismiss any and all interfering overlays, which includes notifications. + // this is theoretically not foolproof, but it's the best that can be done here. + Game.CloseAllOverlays(); + return Game.ScreenStack.CurrentScreen is EditorPlayer editorPlayer && editorPlayer.IsLoaded; + }); + + AddAssert("current ruleset is osu!", () => Game.Ruleset.Value.Equals(new OsuRuleset().RulesetInfo)); + + AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield())); + AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect); + AddAssert("previous ruleset restored", () => Game.Ruleset.Value.Equals(new ManiaRuleset().RulesetInfo)); + } + /// /// When entering the editor, a new beatmap is created as part of the asynchronous load process. /// This test ensures that in the case of an early exit from the editor (ie. while it's still loading) From 604432718116abaadf32778fa47bedc353f504d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 24 May 2023 23:57:37 +0900 Subject: [PATCH 0981/1400] Add test coverage for escape deselecting any active selection --- .../TestSceneBeatmapEditorNavigation.cs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 0307bc7ce5..5f026468c7 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -7,6 +7,7 @@ using osu.Framework.Extensions; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Screens; +using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets.Mania; @@ -16,6 +17,7 @@ using osu.Game.Screens.Edit.GameplayTest; using osu.Game.Screens.Menu; using osu.Game.Screens.Select; using osu.Game.Tests.Resources; +using osuTK.Input; namespace osu.Game.Tests.Visual.Navigation { @@ -82,5 +84,63 @@ namespace osu.Game.Tests.Visual.Navigation BeatmapSetInfo[] allBeatmapSets() => Game.Realm.Run(realm => realm.All().Where(x => !x.DeletePending).ToArray()); } + + [Test] + public void TestExitEditorWithoutSelection() + { + BeatmapSetInfo beatmapSet = null!; + + AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); + AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); + + AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); + AddUntilStep("wait for song select", + () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) + && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect + && songSelect.IsLoaded); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + + AddStep("escape once", () => InputManager.Key(Key.Escape)); + + AddUntilStep("wait for editor exit", () => Game.ScreenStack.CurrentScreen is not Editor); + } + + [Test] + public void TestExitEditorWithSelection() + { + BeatmapSetInfo beatmapSet = null!; + + AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); + AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); + + AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); + AddUntilStep("wait for song select", + () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) + && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect + && songSelect.IsLoaded); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + + AddStep("make selection", () => + { + var beatmap = getEditorBeatmap(); + beatmap.SelectedHitObjects.AddRange(beatmap.HitObjects.Take(5)); + }); + + AddAssert("selection exists", () => getEditorBeatmap().SelectedHitObjects, () => Has.Count.GreaterThan(0)); + + AddStep("escape once", () => InputManager.Key(Key.Escape)); + + AddAssert("selection exists", () => getEditorBeatmap().SelectedHitObjects, () => Has.Count.Zero); + + AddStep("escape again", () => InputManager.Key(Key.Escape)); + + AddUntilStep("wait for editor exit", () => Game.ScreenStack.CurrentScreen is not Editor); + } + + private EditorBeatmap getEditorBeatmap() => ((Editor)Game.ScreenStack.CurrentScreen).ChildrenOfType().Single(); } } From cd3602406b5999efe741b4d2fd3a3f97a2cf272c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 May 2023 18:54:48 +0200 Subject: [PATCH 0982/1400] Remove unused using directive --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index f1e10912ac..7f4979b840 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -17,7 +17,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; -using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; From 07b5874eeee3a5854898318eda111bd9a64870da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 May 2023 20:18:36 +0200 Subject: [PATCH 0983/1400] Fix test step name --- .../Visual/Navigation/TestSceneBeatmapEditorNavigation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 5f026468c7..1b2bb57b84 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("escape once", () => InputManager.Key(Key.Escape)); - AddAssert("selection exists", () => getEditorBeatmap().SelectedHitObjects, () => Has.Count.Zero); + AddAssert("selection empty", () => getEditorBeatmap().SelectedHitObjects, () => Has.Count.Zero); AddStep("escape again", () => InputManager.Key(Key.Escape)); From 6ec4ecfdd734d7db0cd430055e6c01b5753540d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 24 May 2023 22:17:51 +0200 Subject: [PATCH 0984/1400] Mention fallback default in `GetDivisorForBeatIndex()` --- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index f1b97571bd..1da224d850 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -154,7 +154,7 @@ namespace osu.Game.Screens.Edit /// /// The 0-based beat index. /// The beat divisor. - /// The list of valid divisors which can be chosen from. Assumes ordered from low to high. + /// The list of valid divisors which can be chosen from. Assumes ordered from low to high. Defaults to if omitted. /// The applicable divisor. public static int GetDivisorForBeatIndex(int index, int beatDivisor, int[] validDivisors = null) { From 6d9ba9248dd2dd01a75c988fceabc44fd716f2ad Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 25 May 2023 16:38:22 +0900 Subject: [PATCH 0985/1400] Massage tests a bit more --- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 4 ++-- .../Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs | 4 ++-- .../Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs | 4 ++-- .../Visual/Gameplay/TestSceneSkinnableScoreCounter.cs | 5 +++-- .../Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs | 5 +++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index ae46dda750..f97019e466 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -31,8 +31,8 @@ namespace osu.Game.Tests.Visual.Gameplay private HUDOverlay hudOverlay = null!; - [Cached] - private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + [Cached(typeof(ScoreProcessor))] + private ScoreProcessor scoreProcessor => gameplayState.ScoreProcessor; [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs index 93fec60de4..4ae115a68d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorMultipleSkins.cs @@ -22,8 +22,8 @@ namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneSkinEditorMultipleSkins : SkinnableTestScene { - [Cached] - private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + [Cached(typeof(ScoreProcessor))] + private ScoreProcessor scoreProcessor => gameplayState.ScoreProcessor; [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs index 0439656aae..89432940ba 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHUDOverlay.cs @@ -28,8 +28,8 @@ namespace osu.Game.Tests.Visual.Gameplay { private HUDOverlay hudOverlay; - [Cached] - private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + [Cached(typeof(ScoreProcessor))] + private ScoreProcessor scoreProcessor => gameplayState.ScoreProcessor; [Cached(typeof(HealthProcessor))] private HealthProcessor healthProcessor = new DrainingHealthProcessor(0); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs index c95e8ee5b2..2cb3303dd6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs @@ -10,13 +10,14 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; +using osu.Game.Tests.Gameplay; namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneSkinnableScoreCounter : SkinnableHUDComponentTestScene { - [Cached] - private ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + [Cached(typeof(ScoreProcessor))] + private ScoreProcessor scoreProcessor = TestGameplayState.Create(new OsuRuleset()).ScoreProcessor; protected override Drawable CreateDefaultImplementation() => new DefaultScoreCounter(); protected override Drawable CreateLegacyImplementation() => new LegacyScoreCounter(); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs index 8ae6a2a5fc..dbd14db818 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSoloGameplayLeaderboard.cs @@ -16,13 +16,14 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Select; +using osu.Game.Tests.Gameplay; namespace osu.Game.Tests.Visual.Gameplay { public partial class TestSceneSoloGameplayLeaderboard : OsuTestScene { - [Cached] - private readonly ScoreProcessor scoreProcessor = new ScoreProcessor(new OsuRuleset()); + [Cached(typeof(ScoreProcessor))] + private readonly ScoreProcessor scoreProcessor = TestGameplayState.Create(new OsuRuleset()).ScoreProcessor; private readonly BindableList scores = new BindableList(); From 058edb5d5fe4e5003b045f4aeeabb187a977661f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 17:15:31 +0900 Subject: [PATCH 0986/1400] Centralise beatmap playable duration and bounds lookups --- .../UserInterface/TestSceneSegmentedGraph.cs | 4 +- osu.Game/Beatmaps/BeatmapUpdater.cs | 18 +------- osu.Game/Beatmaps/IBeatmap.cs | 44 +++++++++++++++++++ .../Play/HUD/ArgonSongProgressGraph.cs | 4 +- .../Play/HUD/DefaultSongProgressGraph.cs | 4 +- osu.Game/Screens/Play/HUD/SongProgress.cs | 8 ++-- 6 files changed, 55 insertions(+), 27 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs index 1144b9053d..320ec48e07 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSegmentedGraph.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; @@ -137,8 +138,7 @@ namespace osu.Game.Tests.Visual.UserInterface if (!objects.Any()) return; - double firstHit = objects.First().StartTime; - double lastHit = objects.Max(o => o.GetEndTime()); + (double firstHit, double lastHit) = BeatmapExtensions.CalculatePlayableBounds(objects); if (lastHit == 0) lastHit = objects.Last().StartTime; diff --git a/osu.Game/Beatmaps/BeatmapUpdater.cs b/osu.Game/Beatmaps/BeatmapUpdater.cs index af9f32f834..046adb8327 100644 --- a/osu.Game/Beatmaps/BeatmapUpdater.cs +++ b/osu.Game/Beatmaps/BeatmapUpdater.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using System.Linq; using System.Threading.Tasks; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Logging; @@ -11,7 +10,6 @@ using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Database; using osu.Game.Online.API; -using osu.Game.Rulesets.Objects; namespace osu.Game.Beatmaps { @@ -74,7 +72,7 @@ namespace osu.Game.Beatmaps var calculator = ruleset.CreateDifficultyCalculator(working); beatmap.StarRating = calculator.Calculate().StarRating; - beatmap.Length = calculateLength(working.Beatmap); + beatmap.Length = working.Beatmap.CalculatePlayableLength(); beatmap.BPM = 60000 / working.Beatmap.GetMostCommonBeatLength(); } @@ -82,20 +80,6 @@ namespace osu.Game.Beatmaps workingBeatmapCache.Invalidate(beatmapSet); }); - private double calculateLength(IBeatmap b) - { - if (!b.HitObjects.Any()) - return 0; - - var lastObject = b.HitObjects.Last(); - - //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). - double endTime = lastObject.GetEndTime(); - double startTime = b.HitObjects.First().StartTime; - - return endTime - startTime; - } - #region Implementation of IDisposable public void Dispose() diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index f6771f7adf..671f5ce8db 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -104,6 +104,19 @@ namespace osu.Game.Beatmaps } } + /// + /// Find the total milliseconds between the first and last hittable objects. + /// + /// + /// This is cached to , so using that is preferrable when available. + /// + public static double CalculatePlayableLength(this IBeatmap beatmap) => CalculatePlayableLength(beatmap.HitObjects); + + /// + /// Find the timestamps in milliseconds of the start and end of the playable region. + /// + public static (double start, double end) CalculatePlayableBounds(this IBeatmap beatmap) => CalculatePlayableBounds(beatmap.HitObjects); + /// /// Find the absolute end time of the latest in a beatmap. Will throw if beatmap contains no objects. /// @@ -114,5 +127,36 @@ namespace osu.Game.Beatmaps /// It's not super efficient so calls should be kept to a minimum. /// public static double GetLastObjectTime(this IBeatmap beatmap) => beatmap.HitObjects.Max(h => h.GetEndTime()); + + #region Helper methods + + /// + /// Find the total milliseconds between the first and last hittable objects. + /// + /// + /// This is cached to , so using that is preferrable when available. + /// + public static double CalculatePlayableLength(IEnumerable objects) + { + (double start, double end) = CalculatePlayableBounds(objects); + + return end - start; + } + + /// + /// Find the timestamps in milliseconds of the start and end of the playable region. + /// + public static (double start, double end) CalculatePlayableBounds(IEnumerable objects) + { + if (!objects.Any()) + return (0, 0); + + double lastObjectTime = objects.Max(o => o.GetEndTime()); + double firstObjectTime = objects.First().StartTime; + + return (firstObjectTime, lastObjectTime); + } + + #endregion } } diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs index 0899476ed4..63ab9d15e0 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using osu.Framework.Graphics; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Graphics.UserInterface; @@ -26,8 +27,7 @@ namespace osu.Game.Screens.Play.HUD if (!objects.Any()) return; - double firstHit = objects.First().StartTime; - double lastHit = objects.Max(o => o.GetEndTime()); + (double firstHit, double lastHit) = BeatmapExtensions.CalculatePlayableBounds(objects); if (lastHit == 0) lastHit = objects.Last().StartTime; diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs index bee5978817..047c64a4a4 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgressGraph.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Collections.Generic; using System.Diagnostics; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play.HUD @@ -26,8 +27,7 @@ namespace osu.Game.Screens.Play.HUD if (!objects.Any()) return; - double firstHit = objects.First().StartTime; - double lastHit = objects.Max(o => o.GetEndTime()); + (double firstHit, double lastHit) = BeatmapExtensions.CalculatePlayableBounds(objects); if (lastHit == 0) lastHit = objects.Last().StartTime; diff --git a/osu.Game/Screens/Play/HUD/SongProgress.cs b/osu.Game/Screens/Play/HUD/SongProgress.cs index ebe2fb83e6..4391193df8 100644 --- a/osu.Game/Screens/Play/HUD/SongProgress.cs +++ b/osu.Game/Screens/Play/HUD/SongProgress.cs @@ -2,12 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Skinning; @@ -52,9 +52,9 @@ namespace osu.Game.Screens.Play.HUD set { objects = value; - FirstHitTime = objects.FirstOrDefault()?.StartTime ?? 0; - //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). - LastHitTime = objects.LastOrDefault()?.GetEndTime() ?? 0; + + (FirstHitTime, LastHitTime) = BeatmapExtensions.CalculatePlayableBounds(objects); + UpdateObjects(objects); } } From 37c6e632d0f325b36368e91ba749bde0634bdf46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 17:38:35 +0900 Subject: [PATCH 0987/1400] Switch to using new extension method for length calculations --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 4e1913463c..52251db898 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -12,13 +12,12 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.UI; using osuTK; using osuTK.Graphics; @@ -205,7 +204,7 @@ namespace osu.Game.Screens.Play private IGameplayClock? gameplayClock { get; set; } [Resolved] - private DrawableRuleset? drawableRuleset { get; set; } + private GameplayState? gameplayState { get; set; } private void updateInfoText() { @@ -213,11 +212,9 @@ namespace osu.Game.Screens.Play playInfoText.AddText("Retry count: "); playInfoText.AddText(retries.ToString(), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); - if (gameplayClock != null && drawableRuleset != null) + if (gameplayState != null && gameplayClock != null) { - double firstHitTime = drawableRuleset.Objects.FirstOrDefault()?.StartTime ?? 0; - //TODO: this isn't always correct (consider mania where a non-last object may last for longer than the last in the list). - double lastHitTime = drawableRuleset.Objects.LastOrDefault()?.GetEndTime() ?? 0; + (double firstHitTime, double lastHitTime) = gameplayState.Beatmap.CalculatePlayableBounds(); double progress = Math.Clamp((gameplayClock.CurrentTime - firstHitTime) / (lastHitTime - firstHitTime), 0, 1); From 1e14b024938a584dc61725e4ed5d423459a8f29c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 17:57:37 +0900 Subject: [PATCH 0988/1400] Fix bindable feedback loop --- .../Edit/Compose/Components/EditorSelectionHandler.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index dc7e12ea93..d618541685 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -85,6 +85,11 @@ namespace osu.Game.Screens.Edit.Compose.Components } else { + // Auto should never apply when there is a selection made. + // This is also required to stop a bindable feedback loop when a HitObject has zero samples (and LINQ `All` below becomes true). + if (bankName == HIT_BANK_AUTO) + break; + // Never remove a sample bank. // These are basically radio buttons, not toggles. if (SelectedItems.All(h => h.Samples.All(s => s.Bank == bankName))) From 1049257b56b5dc0e2d71dc2db7d5a31c1062de78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 18:46:31 +0900 Subject: [PATCH 0989/1400] Simplify `SelectionHandler`'s `DeselectAll` implementation We are already doing other operations in this class directly on `SelectedItems`, so might as well change this one to match --- .../Screens/Edit/Compose/Components/BlueprintContainer.cs | 1 - .../Screens/Edit/Compose/Components/SelectionHandler.cs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 0fcf84ec8e..56a6b18433 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -92,7 +92,6 @@ namespace osu.Game.Screens.Edit.Compose.Components }; SelectionHandler = CreateSelectionHandler(); - SelectionHandler.DeselectAll = DeselectAll; SelectionHandler.SelectedItems.BindTo(SelectedItems); AddRangeInternal(new[] diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 9e4fb26688..f73a25c339 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -197,9 +197,9 @@ namespace osu.Game.Screens.Edit.Compose.Components #region Selection Handling /// - /// Bind an action to deselect all selected blueprints. + /// Deselect all selected items. /// - internal Action DeselectAll { private get; set; } + protected void DeselectAll() => SelectedItems.Clear(); /// /// Handle a blueprint becoming selected. @@ -303,7 +303,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (blueprint.IsSelected) return false; - DeselectAll?.Invoke(); + DeselectAll(); blueprint.Select(); return true; } From 57c63dbb290a32faa39e9a68af10dc032bfeeb23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 19:24:15 +0900 Subject: [PATCH 0990/1400] Add xmldoc for `GetDisplayScore` --- osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 74a3925435..b7247ed8cc 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -57,6 +57,10 @@ namespace osu.Game.Screens.Play.HUD public BindableInt Combo { get; } = new BindableInt(); public BindableBool HasQuit { get; } = new BindableBool(); public Bindable DisplayOrder { get; } = new Bindable(); + + /// + /// A function providing a display score. If a custom function is not provided, this defaults to using . + /// public Func GetDisplayScore { get; set; } public Color4? BackgroundColour { get; set; } From 609c7227eee913dbb602b5eefdd628bb5c9c216d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 19:55:11 +0900 Subject: [PATCH 0991/1400] Fix changes to font weight in a couple of combined implementations --- .../Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs | 4 +++- .../OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs | 3 +++ .../Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs index 983fab8525..3e6d7a2e54 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/OnlinePlayPill.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -12,6 +13,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { protected PillContainer Pill { get; private set; } = null!; protected OsuTextFlowContainer TextFlow { get; private set; } = null!; + protected virtual FontUsage Font => OsuFont.GetFont(size: 12); protected OnlinePlayPill() { @@ -23,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { InternalChild = Pill = new PillContainer { - Child = TextFlow = new OsuTextFlowContainer(s => s.Font = OsuFont.GetFont(size: 12)) + Child = TextFlow = new OsuTextFlowContainer(s => s.Font = Font) { AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index e88624f877..10f6e59260 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osuTK.Graphics; @@ -15,6 +16,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [Resolved] private OsuColour colours { get; set; } + protected override FontUsage Font => base.Font.With(weight: FontWeight.SemiBold); + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index ab3d293db8..ca9917ad00 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -6,6 +6,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; @@ -20,6 +21,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components [Resolved] private OsuColour colours { get; set; } + protected override FontUsage Font => base.Font.With(weight: FontWeight.SemiBold); + protected override void LoadComplete() { base.LoadComplete(); From 7a5349d747862fc4ad165b82f6b54035ced4156c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 20:09:40 +0900 Subject: [PATCH 0992/1400] Remove constructor from `MultiplayerPlaylistItem` which is only used in tests --- .../Multiplayer/TestSceneMatchStartControl.cs | 2 +- .../Multiplayer/TestSceneMultiplayer.cs | 4 ++-- .../TestSceneMultiplayerPlaylist.cs | 2 +- .../TestSceneMultiplayerQueueList.cs | 2 +- .../Online/Rooms/MultiplayerPlaylistItem.cs | 19 +----------------- .../Multiplayer/TestMultiplayerClient.cs | 20 +++++++++++++++++-- 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs index 3efc7fbd30..6d309078e6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs @@ -129,7 +129,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Playlist = { - new MultiplayerPlaylistItem(playlistItem), + TestMultiplayerClient.CreateMultiplayerPlaylistItem(playlistItem), }, Users = { localUser }, Host = localUser, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index d747d23229..09624f63b7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -906,7 +906,7 @@ namespace osu.Game.Tests.Visual.Multiplayer enterGameplay(); AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 })); - AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem( + AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, TestMultiplayerClient.CreateMultiplayerPlaylistItem( new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) { RulesetID = new OsuRuleset().RulesetInfo.OnlineID, @@ -938,7 +938,7 @@ namespace osu.Game.Tests.Visual.Multiplayer enterGameplay(); AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 })); - AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem( + AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, TestMultiplayerClient.CreateMultiplayerPlaylistItem( new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo) { RulesetID = new OsuRuleset().RulesetInfo.OnlineID, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index d7578b4114..2100f82886 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// private void addItemStep(bool expired = false, int? userId = null) => AddStep("add item", () => { - MultiplayerClient.AddUserPlaylistItem(userId ?? API.LocalUser.Value.OnlineID, new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap) + MultiplayerClient.AddUserPlaylistItem(userId ?? API.LocalUser.Value.OnlineID, TestMultiplayerClient.CreateMultiplayerPlaylistItem(new PlaylistItem(importedBeatmap) { Expired = expired, PlayedAt = DateTimeOffset.Now diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs index bb37f1a5a7..47fb4e06ea 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs @@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add playlist item", () => { - MultiplayerPlaylistItem item = new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap)); + MultiplayerPlaylistItem item = TestMultiplayerClient.CreateMultiplayerPlaylistItem(new PlaylistItem(importedBeatmap)); MultiplayerClient.AddUserPlaylistItem(userId(), item).WaitSafely(); diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index daf45c5aee..8be703e620 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -56,26 +56,9 @@ namespace osu.Game.Online.Rooms [Key(10)] public double StarRating { get; set; } + [SerializationConstructor] public MultiplayerPlaylistItem() { } - - /// - /// This constructor should only be used for test purposes. - /// - public MultiplayerPlaylistItem(PlaylistItem item) - { - ID = item.ID; - OwnerID = item.OwnerID; - BeatmapID = item.Beatmap.OnlineID; - BeatmapChecksum = item.Beatmap.MD5Hash; - RulesetID = item.RulesetID; - RequiredMods = item.RequiredMods.ToArray(); - AllowedMods = item.AllowedMods.ToArray(); - Expired = item.Expired; - PlaylistOrder = item.PlaylistOrder ?? 0; - PlayedAt = item.PlayedAt; - StarRating = item.Beatmap.StarRating; - } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index ad5e3f6c4d..0d9f91caa1 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -108,7 +108,8 @@ namespace osu.Game.Tests.Visual.Multiplayer // simulate the server's automatic assignment of users to teams on join. // the "best" team is the one with the least users on it. int bestTeam = teamVersus.Teams - .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))).MinBy(pair => pair.userCount).teamID; + .Select(team => (teamID: team.ID, userCount: ServerRoom.Users.Count(u => (u.MatchState as TeamVersusUserState)?.TeamID == team.ID))) + .MinBy(pair => pair.userCount).teamID; user.MatchState = new TeamVersusUserState { TeamID = bestTeam }; ((IMultiplayerClient)this).MatchUserStateChanged(clone(user.UserID), clone(user.MatchState)).WaitSafely(); @@ -232,7 +233,7 @@ namespace osu.Game.Tests.Visual.Multiplayer QueueMode = ServerAPIRoom.QueueMode.Value, AutoStartDuration = ServerAPIRoom.AutoStartDuration.Value }, - Playlist = ServerAPIRoom.Playlist.Select(item => new MultiplayerPlaylistItem(item)).ToList(), + Playlist = ServerAPIRoom.Playlist.Select(item => TestMultiplayerClient.CreateMultiplayerPlaylistItem(item)).ToList(), Users = { localUser }, Host = localUser }; @@ -637,5 +638,20 @@ namespace osu.Game.Tests.Visual.Multiplayer byte[]? serialized = MessagePackSerializer.Serialize(typeof(T), incoming, SignalRUnionWorkaroundResolver.OPTIONS); return MessagePackSerializer.Deserialize(serialized, SignalRUnionWorkaroundResolver.OPTIONS); } + + public static MultiplayerPlaylistItem CreateMultiplayerPlaylistItem(PlaylistItem item) => new MultiplayerPlaylistItem + { + ID = item.ID, + OwnerID = item.OwnerID, + BeatmapID = item.Beatmap.OnlineID, + BeatmapChecksum = item.Beatmap.MD5Hash, + RulesetID = item.RulesetID, + RequiredMods = item.RequiredMods.ToArray(), + AllowedMods = item.AllowedMods.ToArray(), + Expired = item.Expired, + PlaylistOrder = item.PlaylistOrder ?? 0, + PlayedAt = item.PlayedAt, + StarRating = item.Beatmap.StarRating, + }; } } From b3c2d120bf8e8d6e60e6a618f1df976d82b6d406 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 20:39:11 +0900 Subject: [PATCH 0993/1400] Fix `OnResume` / `OnSuspending` potentially getting called before `OnEntering` on a sub screen --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 3d80248306..cfaae56d0f 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -132,7 +132,9 @@ namespace osu.Game.Screens.OnlinePlay this.ScaleTo(1, 250, Easing.OutSine); Debug.Assert(screenStack.CurrentScreen != null); - screenStack.CurrentScreen.OnResuming(e); + + if (screenStack.CurrentScreen.IsCurrentScreen()) + screenStack.CurrentScreen.OnResuming(e); base.OnResuming(e); } @@ -143,7 +145,9 @@ namespace osu.Game.Screens.OnlinePlay this.FadeOut(250); Debug.Assert(screenStack.CurrentScreen != null); - screenStack.CurrentScreen.OnSuspending(e); + + if (screenStack.CurrentScreen.IsCurrentScreen()) + screenStack.CurrentScreen.OnSuspending(e); } public override bool OnExiting(ScreenExitEvent e) From 804671ca74995c1be6f429523b1b673dc00df184 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 21:41:19 +0900 Subject: [PATCH 0994/1400] Split out grid snapping modes into "relative" and "global" types --- .../Edit/CatchHitObjectComposer.cs | 2 +- .../Edit/OsuHitObjectComposer.cs | 7 +++++-- .../Editing/TestSceneDistanceSnapGrid.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- osu.Game/Rulesets/Edit/SnapType.cs | 20 +++++++++++++++++-- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index cd8894753f..611e69d614 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Catch.Edit result.ScreenSpacePosition.X = screenSpacePosition.X; - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.GlobalGrids)) { if (distanceSnapGrid.IsPresent && distanceSnapGrid.GetSnappedPosition(result.ScreenSpacePosition) is SnapResult snapResult && Vector2.Distance(snapResult.ScreenSpacePosition, result.ScreenSpacePosition) < distance_snap_radius) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index ff1e208186..ad6af6d74e 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit // We want to ensure that in this particular case, the time-snapping component of distance snap is still applied. // The easiest way to ensure this is to attempt application of distance snap after a nearby object is found, and copy over // the time value if the proposed positions are roughly the same. - if (snapType.HasFlagFast(SnapType.Grids) && DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) + if (snapType.HasFlagFast(SnapType.RelativeGrids) && DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) { (Vector2 distanceSnappedPosition, double distanceSnappedTime) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(snapResult.ScreenSpacePosition)); if (Precision.AlmostEquals(distanceSnapGrid.ToScreenSpace(distanceSnappedPosition), snapResult.ScreenSpacePosition, 1)) @@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Edit SnapResult result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType); - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.RelativeGrids)) { if (DistanceSnapToggle.Value == TernaryState.True && distanceSnapGrid != null) { @@ -164,7 +164,10 @@ namespace osu.Game.Rulesets.Osu.Edit result.ScreenSpacePosition = distanceSnapGrid.ToScreenSpace(pos); result.Time = time; } + } + if (snapType.HasFlagFast(SnapType.GlobalGrids)) + { if (rectangularGridSnapToggle.Value == TernaryState.True) { Vector2 pos = rectangularPositionSnapGrid.GetSnappedPosition(rectangularPositionSnapGrid.ToLocalSpace(result.ScreenSpacePosition)); diff --git a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs index 21b925a257..70e4420a45 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneDistanceSnapGrid.cs @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Editing private class SnapProvider : IDistanceSnapProvider { - public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.Grids) => new SnapResult(screenSpacePosition, 0); + public SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.AllGrids) => new SnapResult(screenSpacePosition, 0); public Bindable DistanceSpacingMultiplier { get; } = new BindableDouble(1); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index e2dbd2acdc..9ce6d957fc 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -428,7 +428,7 @@ namespace osu.Game.Rulesets.Edit var playfield = PlayfieldAtScreenSpacePosition(screenSpacePosition); double? targetTime = null; - if (snapType.HasFlagFast(SnapType.Grids)) + if (snapType.HasFlagFast(SnapType.GlobalGrids)) { if (playfield is ScrollingPlayfield scrollingPlayfield) { diff --git a/osu.Game/Rulesets/Edit/SnapType.cs b/osu.Game/Rulesets/Edit/SnapType.cs index 6eb46457c8..f5f9ab0437 100644 --- a/osu.Game/Rulesets/Edit/SnapType.cs +++ b/osu.Game/Rulesets/Edit/SnapType.cs @@ -11,8 +11,24 @@ namespace osu.Game.Rulesets.Edit public enum SnapType { None = 0, + + /// + /// Snapping to visible nearby objects. + /// NearbyObjects = 1 << 0, - Grids = 1 << 1, - All = NearbyObjects | Grids, + + /// + /// Grids which are global to the playfield. + /// + GlobalGrids = 1 << 1, + + /// + /// Grids which are relative to other nearby hit objects. + /// + RelativeGrids = 1 << 2, + + AllGrids = RelativeGrids | GlobalGrids, + + All = NearbyObjects | GlobalGrids | RelativeGrids, } } From 1cd69220ef640424b79f19784c557ac183333c2d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 21:41:42 +0900 Subject: [PATCH 0995/1400] Fix slider path placement snapping non-head nodes to distanced snapping grid As discussed at https://github.com/ppy/osu/discussions/23531. --- .../Blueprints/Sliders/Components/PathControlPointVisualiser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 17d0fc457a..c56ffcb140 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -309,7 +309,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components } else { - var result = snapProvider?.FindSnappedPositionAndTime(Parent.ToScreenSpace(e.MousePosition)); + var result = snapProvider?.FindSnappedPositionAndTime(Parent.ToScreenSpace(e.MousePosition), SnapType.GlobalGrids); Vector2 movementDelta = Parent.ToLocalSpace(result?.ScreenSpacePosition ?? Parent.ToScreenSpace(e.MousePosition)) - dragStartPositions[draggedControlPointIndex] - hitObject.Position; From beeca5a8dd1bc84f036f25caa5f4e00d4204d417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 May 2023 16:17:44 +0200 Subject: [PATCH 0996/1400] Use alternative layouting implementation --- .../Edit/Compose/Components/SelectionBox.cs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 677b0cd76e..fc57cbf17f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -247,8 +247,6 @@ namespace osu.Game.Screens.Edit.Compose.Components Height = 30, Direction = FillDirection.Horizontal, Margin = new MarginPadding(button_padding), - Anchor = Anchor.BottomCentre, - Origin = Anchor.TopCentre } }; @@ -367,24 +365,30 @@ namespace osu.Game.Screens.Edit.Compose.Components { buttons.Position = Vector2.Zero; - var buttonsQuad = buttons.ScreenSpaceDrawQuad; var thisQuad = ScreenSpaceDrawQuad; // Shrink the parent quad to give a bit of padding so the buttons don't stick *right* on the border. // AABBFloat assumes no rotation. one would hope the whole editor is not being rotated. var parentQuad = Parent.ScreenSpaceDrawQuad.AABBFloat.Shrink(ToLocalSpace(thisQuad.TopLeft + new Vector2(button_padding * 2))); - float leftExcess = buttonsQuad.TopLeft.X - parentQuad.TopLeft.X; - float rightExcess = parentQuad.TopRight.X - buttonsQuad.TopRight.X; - float bottomExcess = thisQuad.BottomLeft.Y + buttonsQuad.Height - parentQuad.BottomLeft.Y; + float topExcess = thisQuad.TopLeft.Y - parentQuad.TopLeft.Y; + float bottomExcess = parentQuad.BottomLeft.Y - thisQuad.BottomLeft.Y; + float leftExcess = thisQuad.TopLeft.X - parentQuad.TopLeft.X; + float rightExcess = parentQuad.TopRight.X - thisQuad.TopRight.X; - if (leftExcess < 0) - buttons.X += ToLocalSpace(thisQuad.TopLeft - new Vector2(leftExcess)).X; - else if (rightExcess < 0) - buttons.X -= ToLocalSpace(thisQuad.TopLeft - new Vector2(rightExcess)).X; + if (topExcess > bottomExcess) + { + buttons.Anchor = Anchor.TopCentre; + buttons.Origin = Anchor.BottomCentre; + } + else + { + buttons.Anchor = Anchor.BottomCentre; + buttons.Origin = Anchor.TopCentre; + } - if (bottomExcess > 0) - buttons.Y += ToLocalSpace(thisQuad.TopLeft - new Vector2(bottomExcess)).X; + if (leftExcess < 0) buttons.X += ToLocalSpace(thisQuad.TopLeft - new Vector2(leftExcess)).X; + if (rightExcess < 0) buttons.X += ToLocalSpace(thisQuad.TopLeft + new Vector2(rightExcess)).X; } } } From 949de35664fa32e6abe115a1c7bea1d30843e1b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 25 May 2023 23:19:55 +0900 Subject: [PATCH 0997/1400] Ensure selection is reset after immediately deleting objects Closes https://github.com/ppy/osu/issues/23518. --- osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index f73a25c339..5cedf1ca42 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -311,6 +311,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected void DeleteSelected() { DeleteItems(SelectedItems.ToArray()); + DeselectAll(); } #endregion From 3ad5f8b9c9973788780e540cb98e5b260367df98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 May 2023 16:39:54 +0200 Subject: [PATCH 0998/1400] Polish a few extreme edge cases --- .../Screens/Edit/Compose/Components/SelectionBox.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index fc57cbf17f..1c5faed0e5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -376,7 +376,12 @@ namespace osu.Game.Screens.Edit.Compose.Components float leftExcess = thisQuad.TopLeft.X - parentQuad.TopLeft.X; float rightExcess = parentQuad.TopRight.X - thisQuad.TopRight.X; - if (topExcess > bottomExcess) + if (topExcess + bottomExcess < buttons.Height + button_padding) + { + buttons.Anchor = Anchor.BottomCentre; + buttons.Origin = Anchor.BottomCentre; + } + else if (topExcess > bottomExcess) { buttons.Anchor = Anchor.TopCentre; buttons.Origin = Anchor.BottomCentre; @@ -387,8 +392,7 @@ namespace osu.Game.Screens.Edit.Compose.Components buttons.Origin = Anchor.TopCentre; } - if (leftExcess < 0) buttons.X += ToLocalSpace(thisQuad.TopLeft - new Vector2(leftExcess)).X; - if (rightExcess < 0) buttons.X += ToLocalSpace(thisQuad.TopLeft + new Vector2(rightExcess)).X; + buttons.X += ToLocalSpace(thisQuad.TopLeft - new Vector2(Math.Min(0, leftExcess)) + new Vector2(Math.Min(0, rightExcess))).X; } } } From 78f41f71095b25dd01a490aeddb3eb8e83aa47c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 May 2023 17:33:41 +0200 Subject: [PATCH 0999/1400] Fix spelling --- osu.Game/Beatmaps/IBeatmap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 671f5ce8db..9dc3084cb5 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps /// Find the total milliseconds between the first and last hittable objects. /// /// - /// This is cached to , so using that is preferrable when available. + /// This is cached to , so using that is preferable when available. /// public static double CalculatePlayableLength(this IBeatmap beatmap) => CalculatePlayableLength(beatmap.HitObjects); @@ -134,7 +134,7 @@ namespace osu.Game.Beatmaps /// Find the total milliseconds between the first and last hittable objects. /// /// - /// This is cached to , so using that is preferrable when available. + /// This is cached to , so using that is preferable when available. /// public static double CalculatePlayableLength(IEnumerable objects) { From adee624a8fe86da21a3f1377aae10aa96eec9007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 May 2023 21:32:19 +0200 Subject: [PATCH 1000/1400] Change `PlacementBlueprint.AutomaticBankAssignment` to property Mostly for consistency. --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index a0a04c13d0..717c026ded 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Edit /// /// Whether the sample bank should be taken from the previous hit object. /// - public bool AutomaticBankAssignment; + public bool AutomaticBankAssignment { get; set; } /// /// The that is being placed. From 7d8f08c0ea0e2e1f6d2952926f85557ff9447350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 25 May 2023 21:49:29 +0200 Subject: [PATCH 1001/1400] Fix `ComposeBlueprintContainer` briefly assigning `auto` bank Seems to have had no consequence due to the way `AutomaticBankAssignment` works (that flag is checked in `PlacementBlueprint.UpdateTimeAndPosition()`, which runs essentially every frame), but let's avoid putting it there at all ever. --- .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 25babae6ff..c8cfac454a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -203,7 +203,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (bankName == EditorSelectionHandler.HIT_BANK_AUTO) CurrentPlacement.AutomaticBankAssignment = state == TernaryState.True; - if (state == TernaryState.True) + else if (state == TernaryState.True) CurrentPlacement.HitObject.Samples = CurrentPlacement.HitObject.Samples.Select(s => s.With(newBank: bankName)).ToList(); } From 3c69956b55e29484888e9ec3564d1df30267aae4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 May 2023 10:41:29 +0900 Subject: [PATCH 1002/1400] Fix incorrect catch grid specification --- osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 611e69d614..8afeca3e51 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -132,7 +132,7 @@ namespace osu.Game.Rulesets.Catch.Edit result.ScreenSpacePosition.X = screenSpacePosition.X; - if (snapType.HasFlagFast(SnapType.GlobalGrids)) + if (snapType.HasFlagFast(SnapType.RelativeGrids)) { if (distanceSnapGrid.IsPresent && distanceSnapGrid.GetSnappedPosition(result.ScreenSpacePosition) is SnapResult snapResult && Vector2.Distance(snapResult.ScreenSpacePosition, result.ScreenSpacePosition) < distance_snap_radius) From cb468fa4eca95567cbbbad4c19ba2b507792182b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 May 2023 19:59:19 +0900 Subject: [PATCH 1003/1400] Fix `OverlappingScrollAlgorithm` returning incorrect results for `TimeAt` before first control point --- .../Algorithms/OverlappingScrollAlgorithm.cs | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 54079c7895..ead893c0af 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System; +using System.Diagnostics; using System.Linq; using osu.Framework.Lists; using osu.Game.Beatmaps.ControlPoints; @@ -40,29 +38,16 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms public double TimeAt(float position, double currentTime, double timeRange, float scrollLength) { - // Find the control point relating to the position. + Debug.Assert(controlPoints.Count > 0); + + // Iterate over control points and find the most relevant for the provided position. // Note: Due to velocity adjustments, overlapping control points will provide multiple valid time values for a single position // As such, this operation provides unexpected results by using the latter of the control points. + var relevantControlPoint = controlPoints.LastOrDefault(cp => PositionAt(cp.Time, currentTime, timeRange, scrollLength) <= position) ?? controlPoints.First(); - int i = 0; - float pos = 0; + float positionAtControlPoint = PositionAt(relevantControlPoint.Time, currentTime, timeRange, scrollLength); - for (; i < controlPoints.Count; i++) - { - float lastPos = pos; - pos = PositionAt(controlPoints[i].Time, currentTime, timeRange, scrollLength); - - if (pos > position) - { - i--; - pos = lastPos; - break; - } - } - - i = Math.Clamp(i, 0, controlPoints.Count - 1); - - return controlPoints[i].Time + (position - pos) * timeRange / controlPoints[i].Multiplier / scrollLength; + return relevantControlPoint.Time + (position - positionAtControlPoint) * timeRange / relevantControlPoint.Multiplier / scrollLength; } public void Reset() From 6b0e215246021777389876701ef7114c64bb4e89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 26 May 2023 20:39:22 +0900 Subject: [PATCH 1004/1400] Add `(int)` flooring and handle potential `NaN` value --- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 23 ++++++++++++++----- osu.Game/Screens/Play/HUD/SongProgressInfo.cs | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 52251db898..3a2e381f97 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -212,18 +212,29 @@ namespace osu.Game.Screens.Play playInfoText.AddText("Retry count: "); playInfoText.AddText(retries.ToString(), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); - if (gameplayState != null && gameplayClock != null) + if (getSongProgress() is int progress) { - (double firstHitTime, double lastHitTime) = gameplayState.Beatmap.CalculatePlayableBounds(); - - double progress = Math.Clamp((gameplayClock.CurrentTime - firstHitTime) / (lastHitTime - firstHitTime), 0, 1); - playInfoText.NewLine(); playInfoText.AddText("Song progress: "); - playInfoText.AddText(progress.ToString("0%"), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); + playInfoText.AddText($"{progress}%", cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); } } + private int? getSongProgress() + { + if (gameplayClock == null || gameplayState == null) + return null; + + (double firstHitTime, double lastHitTime) = gameplayState.Beatmap.CalculatePlayableBounds(); + + double playableLength = (lastHitTime - firstHitTime); + + if (playableLength == 0) + return 0; + + return (int)Math.Clamp(((gameplayClock.CurrentTime - firstHitTime) / playableLength) * 100, 0, 100); + } + private partial class Button : DialogButton { // required to ensure keyboard navigation always starts from an extremity (unless the cursor is moved) diff --git a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs index c04ecd671f..2f137f7e78 100644 --- a/osu.Game/Screens/Play/HUD/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/HUD/SongProgressInfo.cs @@ -145,12 +145,12 @@ namespace osu.Game.Screens.Play.HUD double time = gameplayClock?.CurrentTime ?? Time.Current; double songCurrentTime = time - startTime; - int currentPercent = Math.Max(0, Math.Min(100, (int)(songCurrentTime / songLength * 100))); + int currentPercent = songLength == 0 ? 0 : Math.Max(0, Math.Min(100, (int)(songCurrentTime / songLength * 100))); int currentSecond = (int)Math.Floor(songCurrentTime / 1000.0); if (currentPercent != previousPercent) { - progress.Text = currentPercent + @"%"; + progress.Text = $@"{currentPercent}%"; previousPercent = currentPercent; } From e35201cb991aac8b27d68cb3dd49eb431d68d844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 26 May 2023 19:51:20 +0200 Subject: [PATCH 1005/1400] Don't snap non-head slider nodes to distance grid during placement either 1cd69220ef640424b79f19784c557ac183333c2d only disabled snapping the aforementioned nodes to distance grid for already-placed sliders. `SliderPlacementBlueprint` has its own logic for placement, so the fix needs to be mirrored there too. --- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 28ceb80627..966092c6fe 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders } // Update the cursor position. - var result = snapProvider?.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position); + var result = snapProvider?.FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position, state == SliderPlacementState.Body ? SnapType.GlobalGrids : SnapType.All); cursor.Position = ToLocalSpace(result?.ScreenSpacePosition ?? inputManager.CurrentState.Mouse.Position) - HitObject.Position; } else if (cursor != null) From a01577cba528089335d6e52eb07d9f33357bd0d2 Mon Sep 17 00:00:00 2001 From: Robin Oger Date: Sat, 27 May 2023 12:29:14 +0200 Subject: [PATCH 1006/1400] Adapt changes to fit master --- osu.Game/Localisation/GameplayMenuOverlayStrings.cs | 10 ---------- osu.Game/Screens/Play/FailOverlay.cs | 8 +++++--- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 5 +++-- osu.Game/Screens/Play/PauseOverlay.cs | 10 ++++++---- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs index c89c35775b..597ee64347 100644 --- a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs +++ b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs @@ -34,16 +34,6 @@ namespace osu.Game.Localisation /// public static LocalisableString PausedHeader => new TranslatableString(getKey(@"paused_header"), @"paused"); - /// - /// "You're dead, try again?" - /// - public static LocalisableString FailedDescription => new TranslatableString(getKey(@"failed_description"), @"You're dead, try again?"); - - /// - /// "You're not going to do what i think you're going to do, are ya?" - /// - public static LocalisableString PausedDescription => new TranslatableString(getKey(@"paused_description"), @"You're not going to do what i think you're going to do, are ya?"); - private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index f1dd2abc4a..abfc401998 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -15,6 +15,8 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; +using osu.Game.Localisation; namespace osu.Game.Screens.Play { @@ -22,13 +24,13 @@ namespace osu.Game.Screens.Play { public Func> SaveReplay; - public override string Header => "failed"; + public override LocalisableString Header => GameplayMenuOverlayStrings.FailedHeader; [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); - AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); // from #10339 maybe this is a better visual effect Add(new Container { diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 3a2e381f97..a061b03e7e 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -49,7 +50,7 @@ namespace osu.Game.Screens.Play /// protected virtual Action SelectAction => () => InternalButtons.Selected?.TriggerClick(); - public abstract string Header { get; } + public abstract LocalisableString Header { get; } protected SelectionCycleFillFlowContainer InternalButtons = null!; public IReadOnlyList Buttons => InternalButtons; @@ -153,7 +154,7 @@ namespace osu.Game.Screens.Play protected override bool OnMouseMove(MouseMoveEvent e) => true; - protected void AddButton(string text, Color4 colour, Action? action) + protected void AddButton(LocalisableString text, Color4 colour, Action? action) { var button = new Button { diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 984f43d77a..2fbb4b3239 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -9,9 +9,11 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Localisation; using osu.Game.Skinning; using osuTK.Graphics; @@ -23,7 +25,7 @@ namespace osu.Game.Screens.Play public override bool IsPresent => base.IsPresent || pauseLoop.IsPlaying; - public override string Header => "paused"; + public override LocalisableString Header => "paused"; private SkinnableSound pauseLoop; @@ -32,9 +34,9 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(OsuColour colours) { - AddButton("Continue", colours.Green, () => OnResume?.Invoke()); - AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); - AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Continue, colours.Green, () => OnResume?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Retry, colours.YellowDark, () => OnRetry?.Invoke()); + AddButton(GameplayMenuOverlayStrings.Quit, new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); AddInternal(pauseLoop = new SkinnableSound(new SampleInfo("Gameplay/pause-loop")) { From cfa128002873f19df493a114971e7bd312aa1fed Mon Sep 17 00:00:00 2001 From: Robin Oger Date: Sat, 27 May 2023 12:47:05 +0200 Subject: [PATCH 1007/1400] GameplayMenuOverlay.cs: add translatable strings for `Retry count: ` and `Song progress: ` This makes the assumption that languages will prefer having the number on the right --- .../Localisation/GameplayMenuOverlayStrings.cs | 14 ++++++++++++-- osu.Game/Screens/Play/GameplayMenuOverlay.cs | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs index 597ee64347..f1a65ab430 100644 --- a/osu.Game/Localisation/GameplayMenuOverlayStrings.cs +++ b/osu.Game/Localisation/GameplayMenuOverlayStrings.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Localisation; @@ -34,6 +34,16 @@ namespace osu.Game.Localisation /// public static LocalisableString PausedHeader => new TranslatableString(getKey(@"paused_header"), @"paused"); + /// + /// "Retry count: " + /// + public static LocalisableString RetryCount => new TranslatableString(getKey(@"retry_count"), @"Retry count: "); + + /// + /// "Song progress: " + /// + public static LocalisableString SongProgress => new TranslatableString(getKey(@"song_progress"), @"Song progress: "); + private static string getKey(string key) => $@"{prefix}:{key}"; } -} +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index a061b03e7e..0680842891 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -21,6 +21,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; +using osu.Game.Localisation; namespace osu.Game.Screens.Play { @@ -210,13 +211,13 @@ namespace osu.Game.Screens.Play private void updateInfoText() { playInfoText.Clear(); - playInfoText.AddText("Retry count: "); + playInfoText.AddText(GameplayMenuOverlayStrings.RetryCount); playInfoText.AddText(retries.ToString(), cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); if (getSongProgress() is int progress) { playInfoText.NewLine(); - playInfoText.AddText("Song progress: "); + playInfoText.AddText(GameplayMenuOverlayStrings.SongProgress); playInfoText.AddText($"{progress}%", cp => cp.Font = cp.Font.With(weight: FontWeight.Bold)); } } From 318431a1b7550c1269ebf72c2033b9a793a69677 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 27 May 2023 21:27:32 +0900 Subject: [PATCH 1008/1400] make `MaximumAchievable` to default --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 03149fd8c8..c951551af5 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -76,11 +76,11 @@ namespace osu.Game.Rulesets.Mods public enum AccuracyMode { - [LocalisableDescription(typeof(GameplayAccuracyCounterStrings), nameof(GameplayAccuracyCounterStrings.AccuracyDisplayModeStandard))] - Standard, - [LocalisableDescription(typeof(GameplayAccuracyCounterStrings), nameof(GameplayAccuracyCounterStrings.AccuracyDisplayModeMax))] MaximumAchievable, + + [LocalisableDescription(typeof(GameplayAccuracyCounterStrings), nameof(GameplayAccuracyCounterStrings.AccuracyDisplayModeStandard))] + Standard, } } } From ec61840e7d0d9ed5a60f246c44379542d07cb2bd Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 27 May 2023 23:25:01 +0900 Subject: [PATCH 1009/1400] Provides higher precision settings --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index c951551af5..5c0aa2ad00 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -37,8 +37,8 @@ namespace osu.Game.Rulesets.Mods public BindableNumber MinimumAccuracy { get; } = new BindableDouble { MinValue = 0.60, - MaxValue = 0.99, - Precision = 0.01, + MaxValue = 0.9999, + Precision = 0.0001, Default = 0.9, Value = 0.9, }; From 89c8ef3c9b28b6761a1ce2e4f3eceb1d74a9b07b Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 27 May 2023 23:35:09 +0900 Subject: [PATCH 1010/1400] Format percentage based on significant decimal digits --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 0e26029ffa..688a8ce8e6 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -89,14 +89,20 @@ namespace osu.Game.Graphics.UserInterface double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo); - if (DisplayAsPercentage) - return floatValue.ToString("0%"); - decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits); // Find the number of significant digits (we could have less than 5 after normalize()) int significantDigits = FormatUtils.FindPrecision(decimalPrecision); + if (DisplayAsPercentage) + { + if (significantDigits <= 2) + return floatValue.ToString("0%"); + + string format = "0." + new string('0', significantDigits - 2) + "%"; + return floatValue.ToString(format); + } + string negativeSign = Math.Round(floatValue, significantDigits) < 0 ? "-" : string.Empty; return $"{negativeSign}{Math.Abs(floatValue).ToString($"N{significantDigits}")}"; From a05312c9a26b3f2178779e6220aa4f82ffc65137 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sat, 27 May 2023 23:44:50 +0900 Subject: [PATCH 1011/1400] simplify format method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 688a8ce8e6..e5f5f97eb7 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -96,11 +96,7 @@ namespace osu.Game.Graphics.UserInterface if (DisplayAsPercentage) { - if (significantDigits <= 2) - return floatValue.ToString("0%"); - - string format = "0." + new string('0', significantDigits - 2) + "%"; - return floatValue.ToString(format); + return floatValue.ToString($@"P{Math.Max(0, significantDigits - 2)}"); } string negativeSign = Math.Round(floatValue, significantDigits) < 0 ? "-" : string.Empty; From 333e785f8bcebe7ca98712f70dfd27ec759a9f25 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 28 May 2023 09:50:11 +0900 Subject: [PATCH 1012/1400] Revert "Provides higher precision settings" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ec61840e7d0d9ed5a60f246c44379542d07cb2bd. 😐 --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index 5c0aa2ad00..c951551af5 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -37,8 +37,8 @@ namespace osu.Game.Rulesets.Mods public BindableNumber MinimumAccuracy { get; } = new BindableDouble { MinValue = 0.60, - MaxValue = 0.9999, - Precision = 0.0001, + MaxValue = 0.99, + Precision = 0.01, Default = 0.9, Value = 0.9, }; From 5ff023113fed2c6ef46454e62e9db2f5e8afcc3d Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 28 May 2023 10:04:26 +0300 Subject: [PATCH 1013/1400] Update xmldoc for `ForcedSearchTerm` --- osu.Game/Overlays/Mods/ModSearchContainer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs index f9bf11d1f1..b959274391 100644 --- a/osu.Game/Overlays/Mods/ModSearchContainer.cs +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -10,6 +10,9 @@ namespace osu.Game.Overlays.Mods /// /// A string that should match the children /// + /// + /// Same as except the filtering is guarantied to be performed even when can't be run. + /// public string ForcedSearchTerm { get => SearchTerm; From 0e5c99b760a8e3e2298f5bfb1ac2fb8d82ee83d2 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 28 May 2023 13:12:57 +0300 Subject: [PATCH 1014/1400] Fix search bar showing incorrectly --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d3a2e001e7..3d42059540 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -185,7 +185,7 @@ namespace osu.Game.Overlays.Mods { Padding = new MarginPadding { - Top = (ShowTotalMultiplier ? ModsEffectDisplay.HEIGHT : 0) + PADDING, + Top = ModsEffectDisplay.HEIGHT + PADDING, Bottom = PADDING }, RelativeSizeAxes = Axes.Both, From e43c233b4879006e3cbd36eb77eaade7b23a183c Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 28 May 2023 13:21:41 +0300 Subject: [PATCH 1015/1400] Reword `ForcedSearchTerm` xmldoc --- osu.Game/Overlays/Mods/ModSearchContainer.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs index b959274391..132c02db1e 100644 --- a/osu.Game/Overlays/Mods/ModSearchContainer.cs +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -8,10 +8,11 @@ namespace osu.Game.Overlays.Mods public partial class ModSearchContainer : SearchContainer { /// - /// A string that should match the children + /// Same as except the filtering is guarantied to be performed /// /// - /// Same as except the filtering is guarantied to be performed even when can't be run. + /// This is required because can be hidden when search term applied + /// therefore cannot be reached and filter cannot automatically re-validate itself. /// public string ForcedSearchTerm { From b0501c4e5cbca682254fff771ce7c6128e6f672e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 10:24:59 +0900 Subject: [PATCH 1016/1400] Actually use paused header --- osu.Game/Screens/Play/PauseOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs index 2fbb4b3239..88561ada71 100644 --- a/osu.Game/Screens/Play/PauseOverlay.cs +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play public override bool IsPresent => base.IsPresent || pauseLoop.IsPlaying; - public override LocalisableString Header => "paused"; + public override LocalisableString Header => GameplayMenuOverlayStrings.PausedHeader; private SkinnableSound pauseLoop; From a789d1e49c85687e120e42f83a7dbc4a6980c0eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 18:38:16 +0900 Subject: [PATCH 1017/1400] Add xmldoc and change naming around `ScoreProcessorStatistics` a bit --- .../Gameplay/TestSceneScoreProcessor.cs | 4 +-- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 36 +++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index fbe4dba8ed..a261185473 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -80,7 +80,7 @@ namespace osu.Game.Tests.Gameplay { MaximumBaseScore = 300, BaseScore = 0, - CountAccuracyJudgements = 1, + AccuracyJudgementCount = 1, ComboPortion = 0, BonusPortion = 0 }, DateTimeOffset.Now) @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Gameplay { MaximumBaseScore = 0, BaseScore = 0, - CountAccuracyJudgements = 0, + AccuracyJudgementCount = 0, ComboPortion = 0, BonusPortion = 0 }, DateTimeOffset.Now) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b470c09859..a0d8187642 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -407,7 +407,7 @@ namespace osu.Game.Rulesets.Scoring { MaximumBaseScore = currentMaximumBaseScore, BaseScore = currentBaseScore, - CountAccuracyJudgements = currentCountAccuracyJudgements, + AccuracyJudgementCount = currentCountAccuracyJudgements, ComboPortion = currentComboPortion, BonusPortion = currentBonusPortion }; @@ -416,7 +416,7 @@ namespace osu.Game.Rulesets.Scoring { currentMaximumBaseScore = statistics.MaximumBaseScore; currentBaseScore = statistics.BaseScore; - currentCountAccuracyJudgements = statistics.CountAccuracyJudgements; + currentCountAccuracyJudgements = statistics.AccuracyJudgementCount; currentComboPortion = statistics.ComboPortion; currentBonusPortion = statistics.BonusPortion; } @@ -497,18 +497,40 @@ namespace osu.Game.Rulesets.Scoring [MessagePackObject] public class ScoreProcessorStatistics { + /// + /// The sum of all accuracy-affecting judgements at the current point in time. + /// + /// + /// Used to compute accuracy. + /// See: and . + /// [Key(0)] - public double MaximumBaseScore { get; set; } - - [Key(1)] public double BaseScore { get; set; } - [Key(2)] - public int CountAccuracyJudgements { get; set; } + /// + /// The maximum sum of accuracy-affecting judgements at the current point in time. + /// + /// + /// Used to compute accuracy. + /// + [Key(1)] + public double MaximumBaseScore { get; set; } + /// + /// The count of accuracy-affecting judgements at the current point in time. + /// + [Key(2)] + public int AccuracyJudgementCount { get; set; } + + /// + /// The combo score at the current point in time. + /// [Key(3)] public double ComboPortion { get; set; } + /// + /// The bonus score at the current point in time. + /// [Key(4)] public double BonusPortion { get; set; } } From 22be045de3bd788529e1dd52eabf41597350abd3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 18:48:17 +0900 Subject: [PATCH 1018/1400] Apply NRT to `GameplayScoreCounter` --- osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs index a696d2cad7..bc953e05d2 100644 --- a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -15,8 +13,9 @@ namespace osu.Game.Screens.Play.HUD { public abstract partial class GameplayScoreCounter : ScoreCounter { - private Bindable scoreDisplayMode; - private Bindable totalScoreBindable; + private Bindable scoreDisplayMode = null!; + + private Bindable totalScoreBindable = null!; protected GameplayScoreCounter() : base(6) From 9a886125ad973f7af619c7f284e340e26855ec79 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 19:00:01 +0900 Subject: [PATCH 1019/1400] Ensure `GameplayScoreCounter`'s display score is updated on `ScoringMode` change This isn't strictly required, but only because of a kind of hacky behaviour where `HUDOverlay` will recreate all components on a scoring mode change currently (see https://github.com/ppy/osu/blob/8f6df5ea0f7f721c630fc8cad93bb3eef869d1d9/osu.Game/Screens/Play/HUDOverlay.cs#L410-L418). Best we do this just in case that happens to go away in the future. --- osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs index bc953e05d2..a086aa6d72 100644 --- a/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/GameplayScoreCounter.cs @@ -25,6 +25,9 @@ namespace osu.Game.Screens.Play.HUD [BackgroundDependencyLoader] private void load(OsuConfigManager config, ScoreProcessor scoreProcessor) { + totalScoreBindable = scoreProcessor.TotalScore.GetBoundCopy(); + totalScoreBindable.BindValueChanged(_ => updateDisplayScore()); + scoreDisplayMode = config.GetBindable(OsuSetting.ScoreDisplayMode); scoreDisplayMode.BindValueChanged(scoreMode => { @@ -41,10 +44,11 @@ namespace osu.Game.Screens.Play.HUD default: throw new ArgumentOutOfRangeException(nameof(scoreMode)); } + + updateDisplayScore(); }, true); - totalScoreBindable = scoreProcessor.TotalScore.GetBoundCopy(); - totalScoreBindable.BindValueChanged(_ => Current.Value = scoreProcessor.GetDisplayScore(scoreDisplayMode.Value), true); + void updateDisplayScore() => Current.Value = scoreProcessor.GetDisplayScore(scoreDisplayMode.Value); } } } From fcd7a1d51a915d289e14a69d6b29a8294f59bfb1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 19:41:53 +0900 Subject: [PATCH 1020/1400] Move `GetDisplayScore` xmldoc to interface and remove getter --- osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs | 3 --- osu.Game/Screens/Play/HUD/ILeaderboardScore.cs | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index b7247ed8cc..496fc82019 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -58,9 +58,6 @@ namespace osu.Game.Screens.Play.HUD public BindableBool HasQuit { get; } = new BindableBool(); public Bindable DisplayOrder { get; } = new Bindable(); - /// - /// A function providing a display score. If a custom function is not provided, this defaults to using . - /// public Func GetDisplayScore { get; set; } public Color4? BackgroundColour { get; set; } diff --git a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs index cc1d83e0c7..5de38396fb 100644 --- a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs @@ -23,6 +23,9 @@ namespace osu.Game.Screens.Play.HUD /// Bindable DisplayOrder { get; } - Func GetDisplayScore { get; set; } + /// + /// A function providing a display score. If a custom function is not provided, this defaults to using . + /// + Func GetDisplayScore { set; } } } From 1a6d9e9ff0dded325167a333eed03f1e8e85f928 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 19:46:50 +0900 Subject: [PATCH 1021/1400] Apply NRT to `GameplayLeaderboardScore` and change `GetDisplayedScore` handling I don't feel too confident with the default scoring function being assigned in the constructor to a publicly settable delegate. This just feels a bit more elegant, and handles the (likely-never-used) case where we need to restore the default function. An alternative would be to provide the function as a `ctor` argument, but I believe that wasn't done here to allow using the `ILeaderboardScore` interface. --- .../Play/HUD/GameplayLeaderboardScore.cs | 38 +++++++++---------- .../Screens/Play/HUD/ILeaderboardScore.cs | 6 +-- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 496fc82019..4ac2f1afda 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -1,10 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -50,7 +47,7 @@ namespace osu.Game.Screens.Play.HUD public Bindable Expanded = new Bindable(); - private OsuSpriteText positionText, scoreText, accuracyText, comboText, usernameText; + private OsuSpriteText positionText = null!, scoreText = null!, accuracyText = null!, comboText = null!, usernameText = null!; public BindableLong TotalScore { get; } = new BindableLong(); public BindableDouble Accuracy { get; } = new BindableDouble(1); @@ -58,7 +55,12 @@ namespace osu.Game.Screens.Play.HUD public BindableBool HasQuit { get; } = new BindableBool(); public Bindable DisplayOrder { get; } = new Bindable(); - public Func GetDisplayScore { get; set; } + private Func? getDisplayScoreFunction; + + public Func GetDisplayScore + { + set => getDisplayScoreFunction = value; + } public Color4? BackgroundColour { get; set; } @@ -86,32 +88,31 @@ namespace osu.Game.Screens.Play.HUD } } - [CanBeNull] - public IUser User { get; } + public IUser? User { get; } /// /// Whether this score is the local user or a replay player (and should be focused / always visible). /// public readonly bool Tracked; - private Container mainFillContainer; + private Container mainFillContainer = null!; - private Box centralFill; + private Box centralFill = null!; - private Container backgroundPaddingAdjustContainer; + private Container backgroundPaddingAdjustContainer = null!; - private GridContainer gridContainer; + private GridContainer gridContainer = null!; - private Container scoreComponents; + private Container scoreComponents = null!; - private IBindable scoreDisplayMode; + private IBindable scoreDisplayMode = null!; /// /// Creates a new . /// /// The score's player. /// Whether the player is the local user or a replay player. - public GameplayLeaderboardScore([CanBeNull] IUser user, bool tracked) + public GameplayLeaderboardScore(IUser? user, bool tracked) { User = user; Tracked = tracked; @@ -242,7 +243,7 @@ namespace osu.Game.Screens.Play.HUD Origin = Anchor.CentreLeft, Colour = Color4.White, Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), - Text = User?.Username, + Text = User?.Username ?? string.Empty, Truncate = true, Shadow = false, } @@ -313,11 +314,6 @@ namespace osu.Game.Screens.Play.HUD HasQuit.BindValueChanged(_ => updateState()); } - private void updateScore() - { - scoreText.Text = GetDisplayScore(scoreDisplayMode.Value).ToString("N0"); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -328,6 +324,8 @@ namespace osu.Game.Screens.Play.HUD FinishTransforms(true); } + private void updateScore() => scoreText.Text = (getDisplayScoreFunction?.Invoke(scoreDisplayMode.Value) ?? TotalScore.Value).ToString("N0"); + private void changeExpandedState(ValueChangedEvent expanded) { if (expanded.NewValue) diff --git a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs b/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs index 5de38396fb..1a5d7fd9a8 100644 --- a/osu.Game/Screens/Play/HUD/ILeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/ILeaderboardScore.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. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Game.Rulesets.Scoring; @@ -24,8 +22,10 @@ namespace osu.Game.Screens.Play.HUD Bindable DisplayOrder { get; } /// - /// A function providing a display score. If a custom function is not provided, this defaults to using . + /// A custom function which handles converting a score to a display score using a provide . /// + /// + /// If no function is provided, will be used verbatim. Func GetDisplayScore { set; } } } From df662afbd56a9f2e7042eb4f1900ac6a1647c5f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 20:00:42 +0900 Subject: [PATCH 1022/1400] Pass `ScoreProcessorStatistics` to `FrameHeader`, rather than the full processor --- osu.Game/Online/Spectator/FrameDataBundle.cs | 2 +- osu.Game/Online/Spectator/FrameHeader.cs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Spectator/FrameDataBundle.cs b/osu.Game/Online/Spectator/FrameDataBundle.cs index b936847434..d58ddd5310 100644 --- a/osu.Game/Online/Spectator/FrameDataBundle.cs +++ b/osu.Game/Online/Spectator/FrameDataBundle.cs @@ -24,7 +24,7 @@ namespace osu.Game.Online.Spectator public FrameDataBundle(ScoreInfo score, ScoreProcessor scoreProcessor, IList frames) { Frames = frames; - Header = new FrameHeader(score, scoreProcessor); + Header = new FrameHeader(score, scoreProcessor.GetScoreProcessorStatistics()); } [JsonConstructor] diff --git a/osu.Game/Online/Spectator/FrameHeader.cs b/osu.Game/Online/Spectator/FrameHeader.cs index 4d1c2c2cff..45f920e65b 100644 --- a/osu.Game/Online/Spectator/FrameHeader.cs +++ b/osu.Game/Online/Spectator/FrameHeader.cs @@ -60,18 +60,17 @@ namespace osu.Game.Online.Spectator /// Construct header summary information from a point-in-time reference to a score which is actively being played. /// /// The score for reference. - /// The score processor for reference. - public FrameHeader(ScoreInfo score, ScoreProcessor scoreProcessor) + /// The score processor statistics for the current point in time. + public FrameHeader(ScoreInfo score, ScoreProcessorStatistics statistics) { TotalScore = score.TotalScore; Accuracy = score.Accuracy; Combo = score.Combo; MaxCombo = score.MaxCombo; - // copy for safety Statistics = new Dictionary(score.Statistics); - ScoreProcessorStatistics = scoreProcessor.GetScoreProcessorStatistics(); + ScoreProcessorStatistics = statistics; } [JsonConstructor] From b3ca409339fd15fa7f06608b584f614847d58885 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 29 May 2023 20:08:22 +0900 Subject: [PATCH 1023/1400] Rename a few remaining `CountAccuracyJudgement` variable --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a0d8187642..ac17de32d8 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -117,12 +117,12 @@ namespace osu.Game.Rulesets.Scoring /// /// The count of all accuracy-affecting judgements in the beatmap. /// - private int maximumCountAccuracyJudgements; + private int maximumAccuracyJudgementCount; /// /// The count of accuracy-affecting judgements at the current point in time. /// - private int currentCountAccuracyJudgements; + private int currentAccuracyJudgementCount; /// /// The maximum combo score in the beatmap. @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Scoring { currentMaximumBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore += Judgement.ToNumericResult(result.Type); - currentCountAccuracyJudgements++; + currentAccuracyJudgementCount++; } if (result.Type.IsBonus()) @@ -257,7 +257,7 @@ namespace osu.Game.Rulesets.Scoring { currentMaximumBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); currentBaseScore -= Judgement.ToNumericResult(result.Type); - currentCountAccuracyJudgements--; + currentAccuracyJudgementCount--; } if (result.Type.IsBonus()) @@ -293,7 +293,7 @@ namespace osu.Game.Rulesets.Scoring MaximumAccuracy.Value = maximumBaseScore > 0 ? (currentBaseScore + (maximumBaseScore - currentMaximumBaseScore)) / maximumBaseScore : 1; double comboProgress = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1; - double accuracyProcess = maximumCountAccuracyJudgements > 0 ? (double)currentCountAccuracyJudgements / maximumCountAccuracyJudgements : 1; + double accuracyProcess = maximumAccuracyJudgementCount > 0 ? (double)currentAccuracyJudgementCount / maximumAccuracyJudgementCount : 1; TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboProgress, accuracyProcess, currentBonusPortion) * scoreMultiplier); } @@ -321,7 +321,7 @@ namespace osu.Game.Rulesets.Scoring maximumBaseScore = currentBaseScore; maximumComboPortion = currentComboPortion; - maximumCountAccuracyJudgements = currentCountAccuracyJudgements; + maximumAccuracyJudgementCount = currentAccuracyJudgementCount; maximumResultCounts.Clear(); maximumResultCounts.AddRange(scoreResultCounts); @@ -333,7 +333,7 @@ namespace osu.Game.Rulesets.Scoring currentBaseScore = 0; currentMaximumBaseScore = 0; - currentCountAccuracyJudgements = 0; + currentAccuracyJudgementCount = 0; currentComboPortion = 0; currentBonusPortion = 0; @@ -407,7 +407,7 @@ namespace osu.Game.Rulesets.Scoring { MaximumBaseScore = currentMaximumBaseScore, BaseScore = currentBaseScore, - AccuracyJudgementCount = currentCountAccuracyJudgements, + AccuracyJudgementCount = currentAccuracyJudgementCount, ComboPortion = currentComboPortion, BonusPortion = currentBonusPortion }; @@ -416,7 +416,7 @@ namespace osu.Game.Rulesets.Scoring { currentMaximumBaseScore = statistics.MaximumBaseScore; currentBaseScore = statistics.BaseScore; - currentCountAccuracyJudgements = statistics.AccuracyJudgementCount; + currentAccuracyJudgementCount = statistics.AccuracyJudgementCount; currentComboPortion = statistics.ComboPortion; currentBonusPortion = statistics.BonusPortion; } From 22c6d6c5262a97af2f1a129c2a6a6292ed76bad2 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 29 May 2023 14:22:40 +0300 Subject: [PATCH 1024/1400] Prevent checkbox from toggle on when column have no valid panels --- osu.Game/Overlays/Mods/ModColumn.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 71d964c618..f7d7d4db73 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -151,7 +151,10 @@ namespace osu.Game.Overlays.Mods if (toggleAllCheckbox != null && !SelectionAnimationRunning) { toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.IsValid) ? 1 : 0; - toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.IsValid).All(panel => panel.Active.Value); + + //Prevent checkbox from checking when column have on valid panels + if (availableMods.Any(panel => panel.IsValid)) + toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.IsValid).All(panel => panel.Active.Value); } } From 1c199b83e3453678888cfbe03b73cb123e43cfdb Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 29 May 2023 21:14:03 +0900 Subject: [PATCH 1025/1400] Replace mania scroll "time" with scroll "speed" --- .../ManiaRulesetConfigManager.cs | 29 +++++++++++--- .../ManiaSettingsSubsection.cs | 9 ++--- .../UI/DrawableManiaRuleset.cs | 38 ++++++++++--------- .../Localisation/RulesetSettingsStrings.cs | 2 +- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 99a80ef28d..5ba5125c2d 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -15,24 +15,41 @@ namespace osu.Game.Rulesets.Mania.Configuration public ManiaRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null) : base(settings, ruleset, variant) { + migrate(); } protected override void InitialiseDefaults() { base.InitialiseDefaults(); - SetDefault(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 5); +#pragma warning disable CS0618 + // Although obsolete, this is still required to populate the bindable from the database in case migration is required. + SetDefault(ManiaRulesetSetting.ScrollTime, null); +#pragma warning restore CS0618 + + SetDefault(ManiaRulesetSetting.ScrollSpeed, 8, 1, 40); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); SetDefault(ManiaRulesetSetting.TimingBasedNoteColouring, false); } +#pragma warning disable CS0618 + private void migrate() + { + if (Get(ManiaRulesetSetting.ScrollTime) is double scrollTime) + { + SetValue(ManiaRulesetSetting.ScrollSpeed, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / scrollTime)); + SetValue(ManiaRulesetSetting.ScrollTime, null); + } + } +#pragma warning restore CS0618 + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings { - new TrackedSetting(ManiaRulesetSetting.ScrollTime, - scrollTime => new SettingDescription( - rawValue: scrollTime, + new TrackedSetting(ManiaRulesetSetting.ScrollSpeed, + speed => new SettingDescription( + rawValue: speed, name: RulesetSettingsStrings.ScrollSpeed, - value: RulesetSettingsStrings.ScrollSpeedTooltip(scrollTime, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / scrollTime)) + value: RulesetSettingsStrings.ScrollSpeedTooltip(DrawableManiaRuleset.ComputeScrollTime(speed), speed) ) ) }; @@ -40,7 +57,9 @@ namespace osu.Game.Rulesets.Mania.Configuration public enum ManiaRulesetSetting { + [Obsolete("Use ScrollSpeed instead.")] // Can be removed 2023-11-30 ScrollTime, + ScrollSpeed, ScrollDirection, TimingBasedNoteColouring } diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index fc0b4a9ed9..a5434a36ab 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -34,10 +33,10 @@ namespace osu.Game.Rulesets.Mania LabelText = RulesetSettingsStrings.ScrollingDirection, Current = config.GetBindable(ManiaRulesetSetting.ScrollDirection) }, - new SettingsSlider + new SettingsSlider { LabelText = RulesetSettingsStrings.ScrollSpeed, - Current = config.GetBindable(ManiaRulesetSetting.ScrollTime), + Current = config.GetBindable(ManiaRulesetSetting.ScrollSpeed), KeyboardStep = 5 }, new SettingsCheckbox @@ -48,9 +47,9 @@ namespace osu.Game.Rulesets.Mania }; } - private partial class ManiaScrollSlider : RoundedSliderBar + private partial class ManiaScrollSlider : RoundedSliderBar { - public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(Current.Value, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / Current.Value)); + public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value); } } } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index af8758fb5e..2d373c0471 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -33,12 +33,12 @@ namespace osu.Game.Rulesets.Mania.UI public partial class DrawableManiaRuleset : DrawableScrollingRuleset { /// - /// The minimum time range. This occurs at a of 40. + /// The minimum time range. This occurs at a of 40. /// public const double MIN_TIME_RANGE = 290; /// - /// The maximum time range. This occurs at a of 1. + /// The maximum time range. This occurs with a of 1. /// public const double MAX_TIME_RANGE = 11485; @@ -69,7 +69,8 @@ namespace osu.Game.Rulesets.Mania.UI protected override ScrollVisualisationMethod VisualisationMethod => scrollMethod; private readonly Bindable configDirection = new Bindable(); - private readonly BindableDouble configTimeRange = new BindableDouble(); + private readonly BindableInt configScrollSpeed = new BindableInt(); + private double smoothTimeRange; // Stores the current speed adjustment active in gameplay. private readonly Track speedAdjustmentTrack = new TrackVirtual(0); @@ -78,6 +79,9 @@ namespace osu.Game.Rulesets.Mania.UI : base(ruleset, beatmap, mods) { BarLines = new BarLineGenerator(Beatmap).BarLines; + + TimeRange.MinValue = 1; + TimeRange.MaxValue = MAX_TIME_RANGE; } [BackgroundDependencyLoader] @@ -104,30 +108,28 @@ namespace osu.Game.Rulesets.Mania.UI Config.BindWith(ManiaRulesetSetting.ScrollDirection, configDirection); configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true); - Config.BindWith(ManiaRulesetSetting.ScrollTime, configTimeRange); - TimeRange.MinValue = configTimeRange.MinValue; - TimeRange.MaxValue = configTimeRange.MaxValue; + Config.BindWith(ManiaRulesetSetting.ScrollSpeed, configScrollSpeed); + configScrollSpeed.BindValueChanged(speed => this.TransformTo(nameof(smoothTimeRange), ComputeScrollTime(speed.NewValue), 200, Easing.OutQuint)); + + TimeRange.Value = smoothTimeRange = ComputeScrollTime(configScrollSpeed.Value); } - protected override void AdjustScrollSpeed(int amount) - { - this.TransformTo(nameof(relativeTimeRange), relativeTimeRange + amount, 200, Easing.OutQuint); - } - - private double relativeTimeRange - { - get => MAX_TIME_RANGE / configTimeRange.Value; - set => configTimeRange.Value = MAX_TIME_RANGE / value; - } + protected override void AdjustScrollSpeed(int amount) => configScrollSpeed.Value += amount; protected override void Update() { base.Update(); - updateTimeRange(); } - private void updateTimeRange() => TimeRange.Value = configTimeRange.Value * speedAdjustmentTrack.AggregateTempo.Value * speedAdjustmentTrack.AggregateFrequency.Value; + private void updateTimeRange() => TimeRange.Value = smoothTimeRange * speedAdjustmentTrack.AggregateTempo.Value * speedAdjustmentTrack.AggregateFrequency.Value; + + /// + /// Computes a scroll time (in milliseconds) from a scroll speed in the range of 1-40. + /// + /// The scroll speed. + /// The scroll time. + public static double ComputeScrollTime(int scrollSpeed) => MAX_TIME_RANGE / scrollSpeed; public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new ManiaPlayfieldAdjustmentContainer(); diff --git a/osu.Game/Localisation/RulesetSettingsStrings.cs b/osu.Game/Localisation/RulesetSettingsStrings.cs index 52e6a5eaac..91bbece004 100644 --- a/osu.Game/Localisation/RulesetSettingsStrings.cs +++ b/osu.Game/Localisation/RulesetSettingsStrings.cs @@ -82,7 +82,7 @@ namespace osu.Game.Localisation /// /// "{0}ms (speed {1})" /// - public static LocalisableString ScrollSpeedTooltip(double arg0, int arg1) => new TranslatableString(getKey(@"ruleset"), @"{0}ms (speed {1})", arg0, arg1); + public static LocalisableString ScrollSpeedTooltip(double scrollTime, int scrollSpeed) => new TranslatableString(getKey(@"ruleset"), @"{0:0}ms (speed {1})", scrollTime, scrollSpeed); private static string getKey(string key) => $@"{prefix}:{key}"; } From 314a0f80f319a05b97d3e2f5787c3ef3177b79a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 May 2023 22:12:37 +0200 Subject: [PATCH 1026/1400] Reword setting name & description --- osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs index c951551af5..0072c21053 100644 --- a/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs +++ b/osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mods Value = 0.9, }; - [SettingSource("Accuracy Mode", "The Accuracy mode that will be used to Judge.")] + [SettingSource("Accuracy mode", "The mode of accuracy that will trigger failure.")] public Bindable AccuracyJudgeMode { get; } = new Bindable(); private readonly Bindable currentAccuracy = new Bindable(); From 1b57b0d31c71aaf1578d83293be11a665fc2cdd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 29 May 2023 22:33:46 +0200 Subject: [PATCH 1027/1400] Add testing --- .../Mods/TestSceneModAccuracyChallenge.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs new file mode 100644 index 0000000000..6bdb9132e1 --- /dev/null +++ b/osu.Game.Tests/Visual/Mods/TestSceneModAccuracyChallenge.cs @@ -0,0 +1,69 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osuTK; + +namespace osu.Game.Tests.Visual.Mods +{ + public partial class TestSceneModAccuracyChallenge : ModTestScene + { + protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); + + protected override TestPlayer CreateModPlayer(Ruleset ruleset) + { + var player = base.CreateModPlayer(ruleset); + return player; + } + + protected override bool AllowFail => true; + + [Test] + public void TestMaximumAchievableAccuracy() => + CreateModTest(new ModTestData + { + Mod = new ModAccuracyChallenge + { + MinimumAccuracy = { Value = 0.6 } + }, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = Enumerable.Range(0, 5).Select(i => new HitCircle + { + StartTime = i * 250, + Position = new Vector2(i * 50) + }).Cast().ToList() + }, + PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 3 + }); + + [Test] + public void TestStandardAccuracy() => + CreateModTest(new ModTestData + { + Mod = new ModAccuracyChallenge + { + MinimumAccuracy = { Value = 0.6 }, + AccuracyJudgeMode = { Value = ModAccuracyChallenge.AccuracyMode.Standard } + }, + Autoplay = false, + Beatmap = new Beatmap + { + HitObjects = Enumerable.Range(0, 5).Select(i => new HitCircle + { + StartTime = i * 250, + Position = new Vector2(i * 50) + }).Cast().ToList() + }, + PassCondition = () => Player.GameplayState.HasFailed && Player.ScoreProcessor.JudgedHits >= 1 + }); + } +} From 79694897bef29810846bc156455880b19658723f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 12:58:22 +0900 Subject: [PATCH 1028/1400] Ensure a potential exception from `cleanupPendingDeletions` doesn't mark realm corrupt The whole restructure here is to move the nested call out of the `try-catch`. I noticed this while looking at a corrupt database issue a user reported (https://github.com/ppy/osu/discussions/23694). It's not the first time we've seen a corrupt database error where the "corrupt" version works just fine on a second attempt. Maybe this isn't the issue and it's just a transitive file access violation but it definitely feels like this should be fixed regardless. --- osu.Game/Database/RealmAccess.cs | 79 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 831e328439..55b5e0114d 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -179,43 +179,9 @@ namespace osu.Game.Database applyFilenameSchemaSuffix(ref Filename); #endif - string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}"; - - // Attempt to recover a newer database version if available. - if (storage.Exists(newerVersionFilename)) - { - Logger.Log(@"A newer realm database has been found, attempting recovery...", LoggingTarget.Database); - attemptRecoverFromFile(newerVersionFilename); - } - - try - { + using (var realm = prepareFirstRealmAccess()) // This method triggers the first `getRealmInstance` call, which will implicitly run realm migrations and bring the schema up-to-date. - cleanupPendingDeletions(); - } - catch (Exception e) - { - // See https://github.com/realm/realm-core/blob/master/src%2Frealm%2Fobject-store%2Fobject_store.cpp#L1016-L1022 - // This is the best way we can detect a schema version downgrade. - if (e.Message.StartsWith(@"Provided schema version", StringComparison.Ordinal)) - { - Logger.Error(e, "Your local database is too new to work with this version of osu!. Please close osu! and install the latest release to recover your data."); - - // If a newer version database already exists, don't backup again. We can presume that the first backup is the one we care about. - if (!storage.Exists(newerVersionFilename)) - createBackup(newerVersionFilename); - - storage.Delete(Filename); - } - else - { - Logger.Error(e, "Realm startup failed with unrecoverable error; starting with a fresh database. A backup of your database has been made."); - createBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_corrupt{realm_extension}"); - storage.Delete(Filename); - } - - cleanupPendingDeletions(); - } + cleanupPendingDeletions(realm); } /// @@ -312,9 +278,46 @@ namespace osu.Game.Database Logger.Log(@"Recovery complete!", LoggingTarget.Database); } - private void cleanupPendingDeletions() + private Realm prepareFirstRealmAccess() + { + string newerVersionFilename = $"{Filename.Replace(realm_extension, string.Empty)}_newer_version{realm_extension}"; + + // Attempt to recover a newer database version if available. + if (storage.Exists(newerVersionFilename)) + { + Logger.Log(@"A newer realm database has been found, attempting recovery...", LoggingTarget.Database); + attemptRecoverFromFile(newerVersionFilename); + } + + try + { + return getRealmInstance(); + } + catch (Exception e) + { + // See https://github.com/realm/realm-core/blob/master/src%2Frealm%2Fobject-store%2Fobject_store.cpp#L1016-L1022 + // This is the best way we can detect a schema version downgrade. + if (e.Message.StartsWith(@"Provided schema version", StringComparison.Ordinal)) + { + Logger.Error(e, "Your local database is too new to work with this version of osu!. Please close osu! and install the latest release to recover your data."); + + // If a newer version database already exists, don't backup again. We can presume that the first backup is the one we care about. + if (!storage.Exists(newerVersionFilename)) + createBackup(newerVersionFilename); + } + else + { + Logger.Error(e, "Realm startup failed with unrecoverable error; starting with a fresh database. A backup of your database has been made."); + createBackup($"{Filename.Replace(realm_extension, string.Empty)}_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}_corrupt{realm_extension}"); + } + + storage.Delete(Filename); + return getRealmInstance(); + } + } + + private void cleanupPendingDeletions(Realm realm) { - using (var realm = getRealmInstance()) using (var transaction = realm.BeginWrite()) { var pendingDeleteScores = realm.All().Where(s => s.DeletePending); From a0be52626639b8cbe2e6db7280fc3c106bdb9cd6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 13:04:32 +0900 Subject: [PATCH 1029/1400] Adjust realm backup procedure to hard fail if running out of attempts Previously, if the backup procedure failed, startup would continue and the user's realm database may be deleted. I think in such a fail case I'd rather the game didn't startup so the user gets in touch (or reads the log files themselves) rather than potentially losing data. --- osu.Game/Database/RealmAccess.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 55b5e0114d..2e66ad8b02 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -912,7 +912,7 @@ namespace osu.Game.Database int attempts = 10; - while (attempts-- > 0) + while (true) { try { @@ -930,6 +930,9 @@ namespace osu.Game.Database } catch (IOException) { + if (attempts-- <= 0) + throw; + // file may be locked during use. Thread.Sleep(500); } From e35623df22874e4dfc3c9f9ad721bebb422aa570 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 13:38:39 +0900 Subject: [PATCH 1030/1400] Update to use new `Filter` method and remove silly `ForcedSearchTerm` --- osu.Game/Overlays/Mods/ModSearchContainer.cs | 17 +++++++---------- osu.Game/Overlays/Mods/ModSelectColumn.cs | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs index 132c02db1e..784322b892 100644 --- a/osu.Game/Overlays/Mods/ModSearchContainer.cs +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -7,23 +7,20 @@ namespace osu.Game.Overlays.Mods { public partial class ModSearchContainer : SearchContainer { - /// - /// Same as except the filtering is guarantied to be performed - /// - /// - /// This is required because can be hidden when search term applied - /// therefore cannot be reached and filter cannot automatically re-validate itself. - /// - public string ForcedSearchTerm + public new string SearchTerm { - get => SearchTerm; + get => base.SearchTerm; set { if (value == SearchTerm) return; SearchTerm = value; - Update(); + + // Manual filtering here is required because ModColumn can be hidden when search term applied, + // causing the whole SearchContainer to become non-present and never actually perform a subsequent + // filter. + Filter(); } } } diff --git a/osu.Game/Overlays/Mods/ModSelectColumn.cs b/osu.Game/Overlays/Mods/ModSelectColumn.cs index c80eb8c09c..338ebdaef4 100644 --- a/osu.Game/Overlays/Mods/ModSelectColumn.cs +++ b/osu.Game/Overlays/Mods/ModSelectColumn.cs @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Mods public string SearchTerm { - set => ItemsFlow.ForcedSearchTerm = value; + set => ItemsFlow.SearchTerm = value; } protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => base.ReceivePositionalInputAtSubTree(screenSpacePos) && Active.Value; From 4e0f40bee5f31dc15b6165d2d65ef7a283048ffc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 14:20:26 +0900 Subject: [PATCH 1031/1400] Split out multiplier retrieval into a function and use a default multiplier for all rulesets --- .../Scoring/Legacy/ScoreInfoExtensions.cs | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index af991c7ea3..84bf6d15f6 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -23,10 +23,32 @@ namespace osu.Game.Scoring.Legacy if (mode == ScoringMode.Standardised) return score; + int maxBasicJudgements = maximumStatistics + .Where(k => k.Key.IsBasic()) + .Select(k => k.Value) + .DefaultIfEmpty(0) + .Sum(); + + // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. + // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. + double scaledRawScore = score / ScoreProcessor.MAX_SCORE; + + return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * getStandardisedToClassicMultiplier(rulesetId)); + } + + /// + /// Returns a ballpark multiplier which gives a similar "feel" for how large scores should get when displayed in "classic" mode. + /// This is different per ruleset to match the different algorithms used in the scoring implementation. + /// + private static double getStandardisedToClassicMultiplier(int rulesetId) + { double multiplier; switch (rulesetId) { + // For non-legacy rulesets, just go with the same as the osu! ruleset. + // This is arbitrary, but at least allows the setting to do something to the score. + default: case 0: multiplier = 36; break; @@ -42,17 +64,9 @@ namespace osu.Game.Scoring.Legacy case 3: multiplier = 16; break; - - default: - return score; } - int maxBasicJudgements = maximumStatistics.Where(k => k.Key.IsBasic()).Select(k => k.Value).DefaultIfEmpty(0).Sum(); - - // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. - // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. - double scaledRawScore = score / ScoreProcessor.MAX_SCORE; - return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, maxBasicJudgements), 2) * multiplier); + return multiplier; } public static int? GetCountGeki(this ScoreInfo scoreInfo) From 3e94d4bb5ad417c2df44cff2a9818ce0b0ebdf8f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 15:18:22 +0900 Subject: [PATCH 1032/1400] Fix cursor ripples appearing in a weird place when "autopilot" mod is enabled --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 4782a0e49c..3841c9c716 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -24,7 +24,17 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Automation; public override LocalisableString Description => @"Automatic cursor movement - just follow the rhythm."; public override double ScoreMultiplier => 0.1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAutoplay), typeof(OsuModMagnetised), typeof(OsuModRepel) }; + + public override Type[] IncompatibleMods => new[] + { + typeof(OsuModSpunOut), + typeof(ModRelax), + typeof(ModFailCondition), + typeof(ModNoFail), + typeof(ModAutoplay), + typeof(OsuModMagnetised), + typeof(OsuModRepel) + }; public bool PerformFail() => false; @@ -34,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Mods private List replayFrames = null!; - private int currentFrame; + private int currentFrame = -1; public void Update(Playfield playfield) { @@ -43,8 +53,9 @@ namespace osu.Game.Rulesets.Osu.Mods double time = playfield.Clock.CurrentTime; // Very naive implementation of autopilot based on proximity to replay frames. + // Special case for the first frame is required to ensure the mouse is in a sane position until the actual time of the first frame is hit. // TODO: this needs to be based on user interactions to better match stable (pausing until judgement is registered). - if (Math.Abs(replayFrames[currentFrame + 1].Time - time) <= Math.Abs(replayFrames[currentFrame].Time - time)) + if (currentFrame < 0 || Math.Abs(replayFrames[currentFrame + 1].Time - time) <= Math.Abs(replayFrames[currentFrame].Time - time)) { currentFrame++; new MousePositionAbsoluteInput { Position = playfield.ToScreenSpace(replayFrames[currentFrame].Position) }.Apply(inputManager.CurrentState, inputManager); From 1bde35c61b30a1bda2e5f468b40fdbc9a441e917 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 15:24:06 +0900 Subject: [PATCH 1033/1400] Remove link to very dated blog post --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index eb2fe6d0eb..91f1746183 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ We are accepting bug reports (please report with as much detail as possible and - Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer). - You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management). -- Read peppy's [blog post](https://blog.ppy.sh/a-definitive-lazer-faq/) exploring where the project is currently and the roadmap going forward. ## Running osu! From 654940afb0256cff12aef9f90737b25b135a1fed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 15:28:41 +0900 Subject: [PATCH 1034/1400] Update various text --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 91f1746183..d4b401e528 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Curre ## Status -This project is under heavy development, but is in a stable state. Users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve to the point of eventually replacing the existing stable client as an update. +This project is under constant development, but we aim to keep things in a stable state. Users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve to the point of eventually replacing the existing stable client as an update. -**IMPORTANT:** Gameplay mechanics (and other features which you may have come to know and love) are in a constant state of flux. Game balance and final quality-of-life passes come at the end of development, preceded by experimentation and changes which may potentially **reduce playability or usability**. This is done in order to allow us to move forward as developers and designers more efficiently. If this offends you, please consider sticking to the stable releases of osu! (found on the website). We are not yet open to heated discussion over game mechanics and will not be using github as a forum for such discussions just yet. +**IMPORTANT:** Gameplay mechanics (and other features which you may have come to know and love) are in a constant state of flux. Game balance and final quality-of-life passes come at the end of development, preceded by experimentation and changes which may potentially **reduce playability or usability**. This is done in order to allow us to move forward as developers and designers more efficiently. If this offends you, please consider sticking to a [stable release](https://osu.ppy.sh/home/download) of osu!. We are not yet open to heated discussion over game mechanics and will not be using github as a forum for such discussions just yet. We are accepting bug reports (please report with as much detail as possible and follow the existing issue templates). Feature requests are also welcome, but understand that our focus is on completing the game to feature parity before adding new features. A few resources are available as starting points to getting involved and understanding the project: @@ -27,9 +27,9 @@ We are accepting bug reports (please report with as much detail as possible and ## Running osu! -If you are looking to install or test osu! without setting up a development environment, you can consume our [binary releases](https://github.com/ppy/osu/releases). Handy links below will download the latest version for your operating system of choice: +If you are looking to install or test osu! without setting up a development environment, you can consume our [releases](https://github.com/ppy/osu/releases). You can also generally download a version for your current device from the [osu! site](https://osu.ppy.sh/home/download). Failing that, you may use the links below to download the latest version for your operating system of choice: -**Latest build:** +**Latest release:** | [Windows 8.1+ (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | macOS 10.15+ ([Intel](https://github.com/ppy/osu/releases/latest/download/osu.app.Intel.zip), [Apple Silicon](https://github.com/ppy/osu/releases/latest/download/osu.app.Apple.Silicon.zip)) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS 13.4+](https://osu.ppy.sh/home/testflight) | [Android 5+](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk) | | ------------- | ------------- | ------------- | ------------- | ------------- | From 4d2c3f17e828ab991344c866d897051d65184f6a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 15:30:29 +0900 Subject: [PATCH 1035/1400] Remove outdated prerequisites --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d4b401e528..e4b8e1fc97 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,8 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir Please make sure you have the following prerequisites: - A desktop platform with the [.NET 6.0 SDK](https://dotnet.microsoft.com/download) installed. -- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). -- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). -- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding. + +When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as the latest version of [Visual Studio](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). ### Downloading the source code From 9d844f2381ba0b81c7312f9e2779ed131176d39b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 15:37:12 +0900 Subject: [PATCH 1036/1400] Update documentation for local framework / resources --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e4b8e1fc97..cf7ce35791 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,29 @@ _Due to a historical feature gap between .NET Core and Xamarin, running `dotnet` ### Testing with resource/framework modifications -Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be achieved by running some commands as documented on the [osu-resources](https://github.com/ppy/osu-resources/wiki/Testing-local-resources-checkout-with-other-projects) and [osu-framework](https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects) wiki pages. +Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be quickly achieved using included commands: + +Windows: + +```ps +UseLocalFramework.ps1 +UseLocalResources.ps1 +``` + +macOS / Linux: + +```ps +UseLocalFramework.sh +UseLocalResources.sh +``` + +Note that these commands assume you have the relevant project(s) checked out in adjacent directories: + +``` +|- osu // this repository +|- osu-framework +|- osu-resources +``` ### Code analysis From b456c36f6453309ad902c8a488696dd6798ed86f Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Tue, 30 May 2023 17:27:48 +0900 Subject: [PATCH 1037/1400] Migrate in InitialiseDefaults() --- .../Configuration/ManiaRulesetConfigManager.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index 5ba5125c2d..b2155968ea 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -15,33 +15,27 @@ namespace osu.Game.Rulesets.Mania.Configuration public ManiaRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null) : base(settings, ruleset, variant) { - migrate(); } protected override void InitialiseDefaults() { base.InitialiseDefaults(); -#pragma warning disable CS0618 - // Although obsolete, this is still required to populate the bindable from the database in case migration is required. - SetDefault(ManiaRulesetSetting.ScrollTime, null); -#pragma warning restore CS0618 - SetDefault(ManiaRulesetSetting.ScrollSpeed, 8, 1, 40); SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); SetDefault(ManiaRulesetSetting.TimingBasedNoteColouring, false); - } #pragma warning disable CS0618 - private void migrate() - { + // Although obsolete, this is still required to populate the bindable from the database in case migration is required. + SetDefault(ManiaRulesetSetting.ScrollTime, null); + if (Get(ManiaRulesetSetting.ScrollTime) is double scrollTime) { SetValue(ManiaRulesetSetting.ScrollSpeed, (int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / scrollTime)); SetValue(ManiaRulesetSetting.ScrollTime, null); } - } #pragma warning restore CS0618 + } public override TrackedSettings CreateTrackedSettings() => new TrackedSettings { From ed850196d9b780b4cd30511f8b0c37750a0c30ab Mon Sep 17 00:00:00 2001 From: John Date: Tue, 30 May 2023 01:43:08 -0700 Subject: [PATCH 1038/1400] Reverted to applying the color change in OnUpdate, removed EnableComboColour flag from DrawableHitObject.cs --- osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs | 11 ++++------- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 ------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs index 4fda6130c0..f6fffaf736 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs @@ -31,13 +31,10 @@ namespace osu.Game.Rulesets.Osu.Mods { if (currentBeatmap.IsNull() || drawable.IsNull()) return; - drawable.ApplyCustomUpdateState += (drawableObject, state) => - { - int snapDivisor = currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawableObject.HitObject.StartTime); - - drawableObject.EnableComboColour = false; - drawableObject.AccentColour.Value = BindableBeatDivisor.GetColourFor(snapDivisor, colours); - }; + drawable.OnUpdate += _ => + drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor( + currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), + colours); } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index cbaa07bebc..07c0d1f8a1 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -74,11 +74,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool PropagateNonPositionalInputSubTree => HandleUserInput; - /// - /// Whether this object should be coloured using its combo position - /// - public bool EnableComboColour { get; set; } = true; - /// /// Invoked by this or a nested after a has been applied. /// @@ -533,7 +528,6 @@ namespace osu.Game.Rulesets.Objects.Drawables protected void UpdateComboColour() { if (!(HitObject is IHasComboInformation combo)) return; - if (!EnableComboColour) return; Color4 colour = combo.GetComboColour(CurrentSkin); From 741ee84ed6f14bc8b4e0bf7f073698d4319399c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 30 May 2023 18:38:28 +0900 Subject: [PATCH 1039/1400] Add comment and use full conditional similar to extension method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index cfaae56d0f..50d1d1addd 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -133,7 +133,10 @@ namespace osu.Game.Screens.OnlinePlay Debug.Assert(screenStack.CurrentScreen != null); - if (screenStack.CurrentScreen.IsCurrentScreen()) + // if a subscreen was pushed to the nested stack while this screen was not present, this path will proxy `OnResuming()` + // to the subscreen before `OnEntering()` can even be called for the subscreen, breaking ordering expectations. + // to work around this, do not proxy resume to screens that haven't loaded yet. + if ((screenStack.CurrentScreen as Drawable)?.IsLoaded == true) screenStack.CurrentScreen.OnResuming(e); base.OnResuming(e); From d119447a10a1ac0312a6aa9691348cbabed8c6ba Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 30 May 2023 16:41:42 +0300 Subject: [PATCH 1040/1400] Fix editor timeline hitobjects popping in --- .../Compose/Components/Timeline/TimelineHitObjectBlueprint.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index ea063e9216..900f0ff4a2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -244,6 +244,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft; + protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; + private partial class Tick : Circle { public Tick() From 62d177440730e507ff3b080dd8c1c1eca66ea6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 May 2023 21:54:56 +0200 Subject: [PATCH 1041/1400] Apply same comment & reworded condition to suspend too --- osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs index 50d1d1addd..37b50b4863 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs @@ -133,7 +133,7 @@ namespace osu.Game.Screens.OnlinePlay Debug.Assert(screenStack.CurrentScreen != null); - // if a subscreen was pushed to the nested stack while this screen was not present, this path will proxy `OnResuming()` + // if a subscreen was pushed to the nested stack while the stack was not present, this path will proxy `OnResuming()` // to the subscreen before `OnEntering()` can even be called for the subscreen, breaking ordering expectations. // to work around this, do not proxy resume to screens that haven't loaded yet. if ((screenStack.CurrentScreen as Drawable)?.IsLoaded == true) @@ -149,7 +149,10 @@ namespace osu.Game.Screens.OnlinePlay Debug.Assert(screenStack.CurrentScreen != null); - if (screenStack.CurrentScreen.IsCurrentScreen()) + // if a subscreen was pushed to the nested stack while the stack was not present, this path will proxy `OnSuspending()` + // to the subscreen before `OnEntering()` can even be called for the subscreen, breaking ordering expectations. + // to work around this, do not proxy suspend to screens that haven't loaded yet. + if ((screenStack.CurrentScreen as Drawable)?.IsLoaded == true) screenStack.CurrentScreen.OnSuspending(e); } From 2e81cae201e77229445b97923aaa62be739ac47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 30 May 2023 23:17:07 +0200 Subject: [PATCH 1042/1400] Move comment to more correct place --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 2e66ad8b02..1aef8f1c67 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -179,8 +179,8 @@ namespace osu.Game.Database applyFilenameSchemaSuffix(ref Filename); #endif + // `prepareFirstRealmAccess()` triggers the first `getRealmInstance` call, which will implicitly run realm migrations and bring the schema up-to-date. using (var realm = prepareFirstRealmAccess()) - // This method triggers the first `getRealmInstance` call, which will implicitly run realm migrations and bring the schema up-to-date. cleanupPendingDeletions(realm); } From 18eb15bfa5af004fc2e35f2ec6c017b0cf4a44f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 May 2023 19:39:43 +0900 Subject: [PATCH 1043/1400] Gracefully handle failures in cleaning up pending file deletions --- osu.Game/Database/RealmAccess.cs | 71 ++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1aef8f1c67..94108531e8 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -318,46 +318,53 @@ namespace osu.Game.Database private void cleanupPendingDeletions(Realm realm) { - using (var transaction = realm.BeginWrite()) + try { - var pendingDeleteScores = realm.All().Where(s => s.DeletePending); - - foreach (var score in pendingDeleteScores) - realm.Remove(score); - - var pendingDeleteSets = realm.All().Where(s => s.DeletePending); - - foreach (var beatmapSet in pendingDeleteSets) + using (var transaction = realm.BeginWrite()) { - foreach (var beatmap in beatmapSet.Beatmaps) - { - // Cascade delete related scores, else they will have a null beatmap against the model's spec. - foreach (var score in beatmap.Scores) - realm.Remove(score); + var pendingDeleteScores = realm.All().Where(s => s.DeletePending); - realm.Remove(beatmap.Metadata); - realm.Remove(beatmap); + foreach (var score in pendingDeleteScores) + realm.Remove(score); + + var pendingDeleteSets = realm.All().Where(s => s.DeletePending); + + foreach (var beatmapSet in pendingDeleteSets) + { + foreach (var beatmap in beatmapSet.Beatmaps) + { + // Cascade delete related scores, else they will have a null beatmap against the model's spec. + foreach (var score in beatmap.Scores) + realm.Remove(score); + + realm.Remove(beatmap.Metadata); + realm.Remove(beatmap); + } + + realm.Remove(beatmapSet); } - realm.Remove(beatmapSet); + var pendingDeleteSkins = realm.All().Where(s => s.DeletePending); + + foreach (var s in pendingDeleteSkins) + realm.Remove(s); + + var pendingDeletePresets = realm.All().Where(s => s.DeletePending); + + foreach (var s in pendingDeletePresets) + realm.Remove(s); + + transaction.Commit(); } - var pendingDeleteSkins = realm.All().Where(s => s.DeletePending); - - foreach (var s in pendingDeleteSkins) - realm.Remove(s); - - var pendingDeletePresets = realm.All().Where(s => s.DeletePending); - - foreach (var s in pendingDeletePresets) - realm.Remove(s); - - transaction.Commit(); + // clean up files after dropping any pending deletions. + // in the future we may want to only do this when the game is idle, rather than on every startup. + new RealmFileStore(this, storage).Cleanup(); + } + catch (Exception e) + { + Logger.Error(e, "Failed to clean up unused files. This is not critical but please report if it happens regularly."); } - - // clean up files after dropping any pending deletions. - // in the future we may want to only do this when the game is idle, rather than on every startup. - new RealmFileStore(this, storage).Cleanup(); } /// From 20439e80f6658937a940b3d603582212acb605c2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 31 May 2023 23:24:15 +0900 Subject: [PATCH 1044/1400] Adjust background colour used in `LabelledDrawable`s to allow visibility of sliders --- osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs index 9b7087ce6d..16bad5785f 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -152,7 +152,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 [BackgroundDependencyLoader(true)] private void load(OverlayColourProvider? colourProvider, OsuColour osuColour) { - background.Colour = colourProvider?.Background5 ?? Color4Extensions.FromHex(@"1c2125"); + background.Colour = colourProvider?.Background4 ?? Color4Extensions.FromHex(@"1c2125"); descriptionText.Colour = osuColour.Yellow; } From 7bc3b2072caed1124ddc3b722957a08e0084fd44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 00:44:13 +0900 Subject: [PATCH 1045/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6aebae665d..c88bea8265 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0fd2b0c2c5..8a941ca6c1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index e4a169f8e5..1dcece7741 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 6e00b21a3200ceb5f416d19ecc6cb41fd62e7b6d Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 31 May 2023 19:16:16 +0300 Subject: [PATCH 1046/1400] Update framework version --- osu.Game/osu.Game.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0fd2b0c2c5..db6d9b07cd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -1,4 +1,4 @@ - + net6.0 Library @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + From 5a1c3aeb7e7ef0b735ef8f6fa071afd216f192ca Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 31 May 2023 19:36:42 +0300 Subject: [PATCH 1047/1400] Fix `SearchTerm` set causing infinite loop --- osu.Game/Overlays/Mods/ModSearchContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSearchContainer.cs b/osu.Game/Overlays/Mods/ModSearchContainer.cs index 784322b892..8787530d5c 100644 --- a/osu.Game/Overlays/Mods/ModSearchContainer.cs +++ b/osu.Game/Overlays/Mods/ModSearchContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Mods if (value == SearchTerm) return; - SearchTerm = value; + base.SearchTerm = value; // Manual filtering here is required because ModColumn can be hidden when search term applied, // causing the whole SearchContainer to become non-present and never actually perform a subsequent From 659fb80c16ce124dfd66ac1c4d3ea864e376ec0c Mon Sep 17 00:00:00 2001 From: timiimit Date: Wed, 31 May 2023 19:06:41 +0200 Subject: [PATCH 1048/1400] Add `BeatmapInfo.LastEditTime` property --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 393feff087..7ca0e24913 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -171,6 +171,8 @@ namespace osu.Game.Beatmaps public double TimelineZoom { get; set; } = 1.0; + public double? LastEditTime { get; set; } + [Ignored] public CountdownType Countdown { get; set; } = CountdownType.Normal; From a58426dab6ef91c11db45400ed16a6acfc2f6563 Mon Sep 17 00:00:00 2001 From: timiimit Date: Wed, 31 May 2023 19:07:04 +0200 Subject: [PATCH 1049/1400] Use `LastEditTime` in `Editor` --- osu.Game/Screens/Edit/Editor.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b8fa7f6579..c3d72c7aec 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -441,6 +441,8 @@ namespace osu.Game.Screens.Edit try { + editorBeatmap.BeatmapInfo.LastEditTime = clock.CurrentTime; + // save the loaded beatmap's data stream. beatmapManager.Save(editorBeatmap.BeatmapInfo, editorBeatmap.PlayableBeatmap, editorBeatmap.BeatmapSkin); } @@ -833,7 +835,11 @@ namespace osu.Game.Screens.Edit { double targetTime = 0; - if (Beatmap.Value.Beatmap.HitObjects.Count > 0) + if (editorBeatmap.BeatmapInfo.LastEditTime != null) + { + targetTime = editorBeatmap.BeatmapInfo.LastEditTime.Value; + } + else if (Beatmap.Value.Beatmap.HitObjects.Count > 0) { // seek to one beat length before the first hitobject targetTime = Beatmap.Value.Beatmap.HitObjects[0].StartTime; From 310c54fe28ed32af6ac804c084c5c1de18d38651 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 13:26:46 +0900 Subject: [PATCH 1050/1400] Add test coverage ensuring positional data is present in hit events --- .../Mods/TestSceneOsuModAutoplay.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs index 8fdab9f1f9..616a9c362d 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs @@ -17,6 +17,18 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods { public partial class TestSceneOsuModAutoplay : OsuModTestScene { + [Test] + public void TestCursorPositionStoredToJudgement() + { + CreateModTest(new ModTestData + { + Autoplay = true, + PassCondition = () => + Player.ScoreProcessor.JudgedHits >= 1 + && Player.ScoreProcessor.HitEvents.Any(e => e.Position != null) + }); + } + [Test] public void TestSpmUnaffectedByRateAdjust() => runSpmTest(new OsuModDaycore From e830b96e6182308093e0ab61afcb6f3bf01db9cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 13:09:47 +0900 Subject: [PATCH 1051/1400] Add back required override to make `AccuracyHeatmap` work --- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index ab07ac3e9d..f97be0d7ff 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -2,6 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Scoring @@ -13,6 +15,9 @@ namespace osu.Game.Rulesets.Osu.Scoring { } + protected override HitEvent CreateHitEvent(JudgementResult result) + => base.CreateHitEvent(result).With((result as OsuHitCircleJudgementResult)?.CursorPositionAtHit); + protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { return 700000 * comboProgress From dc595b83f12761a410240e404dc965a27258a37f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 14:25:18 +0900 Subject: [PATCH 1052/1400] Remove unused `Dimension` specification from `StatisticItem` --- osu.Game/Screens/Ranking/Statistics/StatisticItem.cs | 10 +--------- osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs index 5bbd260d3f..77a40959ae 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs @@ -6,7 +6,6 @@ using System; using JetBrains.Annotations; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; namespace osu.Game.Screens.Ranking.Statistics @@ -26,11 +25,6 @@ namespace osu.Game.Screens.Ranking.Statistics /// public readonly Func CreateContent; - /// - /// The of this row. This can be thought of as the column dimension of an encompassing . - /// - public readonly Dimension Dimension; - /// /// Whether this item requires hit events. If true, will not be called if no hit events are available. /// @@ -42,13 +36,11 @@ namespace osu.Game.Screens.Ranking.Statistics /// The name of the item. Can be to hide the item header. /// A function returning the content to be displayed. /// Whether this item requires hit events. If true, will not be called if no hit events are available. - /// The of this item. This can be thought of as the column dimension of an encompassing . - public StatisticItem(LocalisableString name, [NotNull] Func createContent, bool requiresHitEvents = false, [CanBeNull] Dimension dimension = null) + public StatisticItem(LocalisableString name, [NotNull] Func createContent, bool requiresHitEvents = false) { Name = name; RequiresHitEvents = requiresHitEvents; CreateContent = createContent; - Dimension = dimension; } } } diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs index 4c22afd8f7..c11c42e290 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs @@ -168,7 +168,7 @@ namespace osu.Game.Screens.Ranking.Statistics Origin = Anchor.Centre, }); - dimensions.Add(col.Dimension ?? new Dimension()); + dimensions.Add(new Dimension()); } rows.Add(new GridContainer From 985604fab5bb4a74ef7eacdcd842e8190c74047b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 14:35:14 +0900 Subject: [PATCH 1053/1400] Return `StatisticItem`s rather than `StatisticRow`s from ruleset There were no usages of more than one column being provided per row, so it seemed like unnecessarily complexity. I'm currently trying to reduce complexity so we can improve the layout of the results screen, which currently has up to three levels of nested `GridContainer`s. Of note, I can't add backwards compatibility because the method signature has not changed in `Ruleset` (only the return type). If we do want to keep compatibility with other rulesets, we could designate a new name for the updated method. --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 44 ++++--------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 58 +++++------------ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 44 ++++--------- .../Ranking/TestSceneStatisticsPanel.cs | 65 +++---------------- osu.Game/Rulesets/Ruleset.cs | 4 +- .../Statistics/SimpleStatisticTable.cs | 2 +- .../Ranking/Statistics/SoloStatisticsPanel.cs | 26 +++----- .../Ranking/Statistics/StatisticItem.cs | 2 +- .../Ranking/Statistics/StatisticRow.cs | 21 ------ .../Ranking/Statistics/StatisticsPanel.cs | 40 +++++------- 10 files changed, 83 insertions(+), 223 deletions(-) delete mode 100644 osu.Game/Screens/Ranking/Statistics/StatisticRow.cs diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index d324682989..e8fda3ec80 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -389,41 +389,23 @@ namespace osu.Game.Rulesets.Mania return base.GetDisplayNameForHitResult(result); } - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[] + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[] { - new StatisticRow + new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) { - Columns = new[] - { - new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }), + new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents) { - Columns = new[] - { - new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(score.HitEvents) - { - RelativeSizeAxes = Axes.X, - Height = 250 - }, true), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + Height = 250 + }, true), + new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] { - Columns = new[] - { - new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] - { - new AverageHitError(score.HitEvents), - new UnstableRate(score.HitEvents) - }), true) - } - } + new AverageHitError(score.HitEvents), + new UnstableRate(score.HitEvents) + }), true) }; public override IRulesetFilterCriteria CreateRulesetFilterCriteria() diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 922594a93a..8ce55d78dd 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -291,56 +291,32 @@ namespace osu.Game.Rulesets.Osu return base.GetDisplayNameForHitResult(result); } - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) { var timedHitEvents = score.HitEvents.Where(e => e.HitObject is HitCircle && !(e.HitObject is SliderTailCircle)).ToList(); return new[] { - new StatisticRow + new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) { - Columns = new[] - { - new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }), + new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents) { - Columns = new[] - { - new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents) - { - RelativeSizeAxes = Axes.X, - Height = 250 - }, true), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + Height = 250 + }, true), + new StatisticItem("Accuracy Heatmap", () => new AccuracyHeatmap(score, playableBeatmap) { - Columns = new[] - { - new StatisticItem("Accuracy Heatmap", () => new AccuracyHeatmap(score, playableBeatmap) - { - RelativeSizeAxes = Axes.X, - Height = 250 - }, true), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + Height = 250 + }, true), + new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] { - Columns = new[] - { - new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] - { - new AverageHitError(timedHitEvents), - new UnstableRate(timedHitEvents) - }), true) - } - } + new AverageHitError(timedHitEvents), + new UnstableRate(timedHitEvents) + }), true) }; } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index a35fdb890d..d6824109b3 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -229,45 +229,27 @@ namespace osu.Game.Rulesets.Taiko return base.GetDisplayNameForHitResult(result); } - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) { var timedHitEvents = score.HitEvents.Where(e => e.HitObject is Hit).ToList(); return new[] { - new StatisticRow + new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) { - Columns = new[] - { - new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }), + new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents) { - Columns = new[] - { - new StatisticItem("Timing Distribution", () => new HitEventTimingDistributionGraph(timedHitEvents) - { - RelativeSizeAxes = Axes.X, - Height = 250 - }, true), - } - }, - new StatisticRow + RelativeSizeAxes = Axes.X, + Height = 250 + }, true), + new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] { - Columns = new[] - { - new StatisticItem(string.Empty, () => new SimpleStatisticTable(3, new SimpleStatisticItem[] - { - new AverageHitError(timedHitEvents), - new UnstableRate(timedHitEvents) - }), true) - } - } + new AverageHitError(timedHitEvents), + new UnstableRate(timedHitEvents) + }), true) }; } } diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs index fcd5f97fcc..67211a3b72 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs @@ -174,78 +174,33 @@ namespace osu.Game.Tests.Visual.Ranking private class TestRulesetAllStatsRequireHitEvents : TestRuleset { - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[] { - return new[] - { - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Requiring Hit Events 1", - () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true) - } - }, - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Requiring Hit Events 2", - () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true) - } - } - }; - } + new StatisticItem("Statistic Requiring Hit Events 1", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true), + new StatisticItem("Statistic Requiring Hit Events 2", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true) + }; } private class TestRulesetNoStatsRequireHitEvents : TestRuleset { - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) { return new[] { - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Not Requiring Hit Events 1", - () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")) - } - }, - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Not Requiring Hit Events 2", - () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")) - } - } + new StatisticItem("Statistic Not Requiring Hit Events 1", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")), + new StatisticItem("Statistic Not Requiring Hit Events 2", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")) }; } } private class TestRulesetMixed : TestRuleset { - public override StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) + public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) { return new[] { - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Requiring Hit Events", - () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true) - } - }, - new StatisticRow - { - Columns = new[] - { - new StatisticItem("Statistic Not Requiring Hit Events", - () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")) - } - } + new StatisticItem("Statistic Requiring Hit Events", () => CreatePlaceholderStatistic("Placeholder statistic. Requires hit events"), true), + new StatisticItem("Statistic Not Requiring Hit Events", () => CreatePlaceholderStatistic("Placeholder statistic. Does not require hit events")) }; } } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index a77068eb14..490ec1475c 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -321,8 +321,8 @@ namespace osu.Game.Rulesets /// /// The to create the statistics for. The score is guaranteed to have populated. /// The , converted for this with all relevant s applied. - /// The s to display. Each may contain 0 or more . - public virtual StatisticRow[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty(); + /// The s to display. + public virtual StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty(); /// /// Get all valid s for this ruleset. diff --git a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs index d10888be43..d68df4558a 100644 --- a/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs +++ b/osu.Game/Screens/Ranking/Statistics/SimpleStatisticTable.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Ranking.Statistics { /// /// Represents a table with simple statistics (ones that only need textual display). - /// Richer visualisations should be done with s and s. + /// Richer visualisations should be done with s. /// public partial class SimpleStatisticTable : CompositeDrawable { diff --git a/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs index 57d072b7de..73b9897096 100644 --- a/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/SoloStatisticsPanel.cs @@ -23,32 +23,26 @@ namespace osu.Game.Screens.Ranking.Statistics public Bindable StatisticsUpdate { get; } = new Bindable(); - protected override ICollection CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap) + protected override ICollection CreateStatisticItems(ScoreInfo newScore, IBeatmap playableBeatmap) { - var rows = base.CreateStatisticRows(newScore, playableBeatmap); + var items = base.CreateStatisticItems(newScore, playableBeatmap); if (newScore.UserID > 1 && newScore.UserID == achievedScore.UserID && newScore.OnlineID > 0 && newScore.OnlineID == achievedScore.OnlineID) { - rows = rows.Append(new StatisticRow + items = items.Append(new StatisticItem("Overall Ranking", () => new OverallRanking { - Columns = new[] - { - new StatisticItem("Overall Ranking", () => new OverallRanking - { - RelativeSizeAxes = Axes.X, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 0.5f, - StatisticsUpdate = { BindTarget = StatisticsUpdate } - }) - } - }).ToArray(); + RelativeSizeAxes = Axes.X, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 0.5f, + StatisticsUpdate = { BindTarget = StatisticsUpdate } + })).ToArray(); } - return rows; + return items; } } } diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs index 77a40959ae..c5bdc6f6f5 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking.Statistics public readonly bool RequiresHitEvents; /// - /// Creates a new , to be displayed inside a in the results screen. + /// Creates a new , to be displayed in the results screen. /// /// The name of the item. Can be to hide the item header. /// A function returning the content to be displayed. diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs b/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs deleted file mode 100644 index 9f5f44918e..0000000000 --- a/osu.Game/Screens/Ranking/Statistics/StatisticRow.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using JetBrains.Annotations; - -namespace osu.Game.Screens.Ranking.Statistics -{ - /// - /// A row of statistics to be displayed in the results screen. - /// - public class StatisticRow - { - /// - /// The columns of this . - /// - [ItemNotNull] - public StatisticItem[] Columns; - } -} diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs index c11c42e290..31dd5df27a 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs @@ -100,9 +100,9 @@ namespace osu.Game.Screens.Ranking.Statistics bool hitEventsAvailable = newScore.HitEvents.Count != 0; Container container; - var statisticRows = CreateStatisticRows(newScore, task.GetResultSafely()); + var statisticItems = CreateStatisticItems(newScore, task.GetResultSafely()); - if (!hitEventsAvailable && statisticRows.SelectMany(r => r.Columns).All(c => c.RequiresHitEvents)) + if (!hitEventsAvailable && statisticItems.All(c => c.RequiresHitEvents)) { container = new FillFlowContainer { @@ -144,33 +144,25 @@ namespace osu.Game.Screens.Ranking.Statistics bool anyRequiredHitEvents = false; - foreach (var row in statisticRows) + foreach (var item in statisticItems) { - var columns = row.Columns; - - if (columns.Length == 0) - continue; - var columnContent = new List(); var dimensions = new List(); - foreach (var col in columns) + if (!hitEventsAvailable && item.RequiresHitEvents) { - if (!hitEventsAvailable && col.RequiresHitEvents) - { - anyRequiredHitEvents = true; - continue; - } - - columnContent.Add(new StatisticContainer(col) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - - dimensions.Add(new Dimension()); + anyRequiredHitEvents = true; + continue; } + columnContent.Add(new StatisticContainer(item) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + dimensions.Add(new Dimension()); + rows.Add(new GridContainer { Anchor = Anchor.TopCentre, @@ -219,11 +211,11 @@ namespace osu.Game.Screens.Ranking.Statistics } /// - /// Creates the s to be displayed in this panel for a given . + /// Creates the s to be displayed in this panel for a given . /// /// The score to create the rows for. /// The beatmap on which the score was set. - protected virtual ICollection CreateStatisticRows(ScoreInfo newScore, IBeatmap playableBeatmap) + protected virtual ICollection CreateStatisticItems(ScoreInfo newScore, IBeatmap playableBeatmap) => newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap); protected override bool OnClick(ClickEvent e) From 9f8a13480bcf6d760b11e92381b51d59d53a3e4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 15:16:47 +0900 Subject: [PATCH 1054/1400] Automatically disable tablet support on error Closes #23710. --- osu.Game/OsuGame.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fe6e479d19..33ac8cc101 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1136,12 +1136,19 @@ namespace osu.Game if (entry.Level == LogLevel.Error) { - Schedule(() => Notifications.Post(new SimpleNotification + Schedule(() => { - Text = $"Encountered tablet error: \"{message}\"", - Icon = FontAwesome.Solid.PenSquare, - IconColour = Colours.RedDark, - })); + Notifications.Post(new SimpleNotification + { + Text = $"Disabling tablet support due to error: \"{message}\"", + Icon = FontAwesome.Solid.PenSquare, + IconColour = Colours.RedDark, + }); + + var tabletHandler = Host.AvailableInputHandlers.OfType().FirstOrDefault(); + if (tabletHandler != null) + tabletHandler.Enabled.Value = false; + }); } else if (notifyOnWarning) { From 0a7d5a51d419055990d9da48345de1284408639f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 15:50:10 +0900 Subject: [PATCH 1055/1400] Fix mouse cursor potentially disappearing for good if screenshot capture fails --- osu.Game/Graphics/ScreenshotManager.cs | 115 +++++++++++++------------ 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index d799e82bc9..dd90cbc074 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -86,70 +86,75 @@ namespace osu.Game.Graphics { Interlocked.Increment(ref screenShotTasks); - if (!captureMenuCursor.Value) + try { - cursorVisibility.Value = false; - - // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value - const int frames_to_wait = 3; - - int framesWaited = 0; - - using (var framesWaitedEvent = new ManualResetEventSlim(false)) + if (!captureMenuCursor.Value) { - ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => + cursorVisibility.Value = false; + + // We need to wait for at most 3 draw nodes to be drawn, following which we can be assured at least one DrawNode has been generated/drawn with the set value + const int frames_to_wait = 3; + + int framesWaited = 0; + + using (var framesWaitedEvent = new ManualResetEventSlim(false)) { - if (framesWaited++ >= frames_to_wait) - // ReSharper disable once AccessToDisposedClosure - framesWaitedEvent.Set(); - }, 10, true); + ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => + { + if (framesWaited++ >= frames_to_wait) + // ReSharper disable once AccessToDisposedClosure + framesWaitedEvent.Set(); + }, 10, true); - if (!framesWaitedEvent.Wait(1000)) - throw new TimeoutException("Screenshot data did not arrive in a timely fashion"); + if (!framesWaitedEvent.Wait(1000)) + throw new TimeoutException("Screenshot data did not arrive in a timely fashion"); - waitDelegate.Cancel(); + waitDelegate.Cancel(); + } + } + + using (var image = await host.TakeScreenshotAsync().ConfigureAwait(false)) + { + host.GetClipboard()?.SetImage(image); + + (string filename, var stream) = getWritableStream(); + + if (filename == null) return; + + using (stream) + { + switch (screenshotFormat.Value) + { + case ScreenshotFormat.Png: + await image.SaveAsPngAsync(stream).ConfigureAwait(false); + break; + + case ScreenshotFormat.Jpg: + const int jpeg_quality = 92; + + await image.SaveAsJpegAsync(stream, new JpegEncoder { Quality = jpeg_quality }).ConfigureAwait(false); + break; + + default: + throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); + } + } + + notificationOverlay.Post(new SimpleNotification + { + Text = $"Screenshot {filename} saved!", + Activated = () => + { + storage.PresentFileExternally(filename); + return true; + } + }); } } - - using (var image = await host.TakeScreenshotAsync().ConfigureAwait(false)) + finally { - if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false) + if (Interlocked.Decrement(ref screenShotTasks) == 0) cursorVisibility.Value = true; - - host.GetClipboard()?.SetImage(image); - - (string filename, var stream) = getWritableStream(); - - if (filename == null) return; - - using (stream) - { - switch (screenshotFormat.Value) - { - case ScreenshotFormat.Png: - await image.SaveAsPngAsync(stream).ConfigureAwait(false); - break; - - case ScreenshotFormat.Jpg: - const int jpeg_quality = 92; - - await image.SaveAsJpegAsync(stream, new JpegEncoder { Quality = jpeg_quality }).ConfigureAwait(false); - break; - - default: - throw new InvalidOperationException($"Unknown enum member {nameof(ScreenshotFormat)} {screenshotFormat.Value}."); - } - } - - notificationOverlay.Post(new SimpleNotification - { - Text = $"Screenshot {filename} saved!", - Activated = () => - { - storage.PresentFileExternally(filename); - return true; - } - }); } }); From 289f0e9862d690cf40e7fcd081cd962a1791fb39 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 15:50:37 +0900 Subject: [PATCH 1056/1400] Use `FireAndForget` to avoid unobserved exception --- osu.Game/Graphics/ScreenshotManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index dd90cbc074..82f89d6889 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -19,6 +19,7 @@ using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Input.Bindings; +using osu.Game.Online.Multiplayer; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using SixLabors.ImageSharp; @@ -69,7 +70,7 @@ namespace osu.Game.Graphics { case GlobalAction.TakeScreenshot: shutter.Play(); - TakeScreenshotAsync(); + TakeScreenshotAsync().FireAndForget(); return true; } From 98f35f74811329500e558943464d003b3543f276 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 16:06:34 +0900 Subject: [PATCH 1057/1400] Fix osu!mania hold notes snapping to judgement area too early on early hits Closes https://github.com/ppy/osu/issues/23515. --- .../Objects/Drawables/DrawableHoldNote.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index ce34addeff..3f91328128 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -245,7 +245,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // As the note is being held, adjust the size of the sizing container. This has two effects: // 1. The contained masking container will mask the body and ticks. // 2. The head note will move along with the new "head position" in the container. - if (Head.IsHit && releaseTime == null && DrawHeight > 0) + // + // As per stable, this should not apply for early hits, waiting until the object starts to touch the + // judgement area first. + if (Head.IsHit && releaseTime == null && DrawHeight > 0 && Time.Current >= HitObject.StartTime) { // How far past the hit target this hold note is. float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; From f52ed41f107fe79db605fc35acab62faa9f9d9c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 16:28:03 +0900 Subject: [PATCH 1058/1400] Use better defaults of 1/4 and 1/6 when cycling types --- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 432c5ea280..e510d1aac8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -196,11 +196,11 @@ namespace osu.Game.Screens.Edit.Compose.Components switch ((BeatDivisorType)nextDivisorType) { case BeatDivisorType.Common: - beatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.COMMON; + beatDivisor.SetArbitraryDivisor(4); break; case BeatDivisorType.Triplets: - beatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.TRIPLETS; + beatDivisor.SetArbitraryDivisor(6); break; case BeatDivisorType.Custom: From bcde2cbc73bf31ed0d32cfe7a49e87b6afa174fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 16:28:47 +0900 Subject: [PATCH 1059/1400] Apply NRT to `BeatDivisorControl` --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 8 +++----- .../Screens/Edit/Compose/Components/BeatDivisorControl.cs | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 353acfa4ba..3ee5ea79db 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.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. -#nullable disable - using System; using System.Diagnostics; using System.Linq; @@ -23,8 +21,8 @@ namespace osu.Game.Tests.Visual.Editing { public partial class TestSceneBeatDivisorControl : OsuManualInputManagerTestScene { - private BeatDivisorControl beatDivisorControl; - private BindableBeatDivisor bindableBeatDivisor; + private BeatDivisorControl beatDivisorControl = null!; + private BindableBeatDivisor bindableBeatDivisor = null!; private SliderBar tickSliderBar => beatDivisorControl.ChildrenOfType>().Single(); private Triangle tickMarkerHead => tickSliderBar.ChildrenOfType().Single(); @@ -237,7 +235,7 @@ namespace osu.Game.Tests.Visual.Editing InputManager.Click(MouseButton.Left); }); - BeatDivisorControl.CustomDivisorPopover popover = null; + BeatDivisorControl.CustomDivisorPopover? popover = null; AddUntilStep("wait for popover", () => (popover = this.ChildrenOfType().SingleOrDefault()) != null && popover.IsLoaded); AddStep($"set divisor to {divisor}", () => { diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index e510d1aac8..213246d516 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.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. -#nullable disable - using System; using System.Diagnostics; using System.Linq; @@ -372,10 +370,10 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class TickSliderBar : SliderBar { - private Marker marker; + private Marker marker = null!; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; private readonly BindableBeatDivisor beatDivisor; @@ -517,7 +515,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class Marker : CompositeDrawable { [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; [BackgroundDependencyLoader] private void load() From 32207d411222f1328466a6e9c40a261ebb042c16 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 16:40:33 +0900 Subject: [PATCH 1060/1400] Remember the last used custom divisor when cycling divisor types --- .../Compose/Components/BeatDivisorControl.cs | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 213246d516..dce9e01192 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -29,6 +29,8 @@ namespace osu.Game.Screens.Edit.Compose.Components { public partial class BeatDivisorControl : CompositeDrawable { + private int? lastCustomDivisor; + private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); public BeatDivisorControl(BindableBeatDivisor beatDivisor) @@ -182,16 +184,30 @@ namespace osu.Game.Screens.Edit.Compose.Components }; } + protected override void LoadComplete() + { + base.LoadComplete(); + + beatDivisor.ValidDivisors.BindValueChanged(valid => + { + if (valid.NewValue.Type == BeatDivisorType.Custom) + lastCustomDivisor = valid.NewValue.Presets.Last(); + }, true); + } + private void cycleDivisorType(int direction) { - Debug.Assert(Math.Abs(direction) == 1); - int nextDivisorType = (int)beatDivisor.ValidDivisors.Value.Type + direction; - if (nextDivisorType > (int)BeatDivisorType.Triplets) - nextDivisorType = (int)BeatDivisorType.Common; - else if (nextDivisorType < (int)BeatDivisorType.Common) - nextDivisorType = (int)BeatDivisorType.Triplets; + int totalTypes = Enum.GetValues().Length; + BeatDivisorType currentType = beatDivisor.ValidDivisors.Value.Type; - switch ((BeatDivisorType)nextDivisorType) + Debug.Assert(Math.Abs(direction) == 1); + + cycleOnce(); + + if (lastCustomDivisor == null && currentType == BeatDivisorType.Custom) + cycleOnce(); + + switch (currentType) { case BeatDivisorType.Common: beatDivisor.SetArbitraryDivisor(4); @@ -202,9 +218,12 @@ namespace osu.Game.Screens.Edit.Compose.Components break; case BeatDivisorType.Custom: - beatDivisor.ValidDivisors.Value = BeatDivisorPresetCollection.Custom(beatDivisor.ValidDivisors.Value.Presets.Max()); + Debug.Assert(lastCustomDivisor != null); + beatDivisor.SetArbitraryDivisor(lastCustomDivisor.Value); break; } + + void cycleOnce() => currentType = (BeatDivisorType)(((int)currentType + totalTypes + direction) % totalTypes); } protected override bool OnKeyDown(KeyDownEvent e) @@ -302,12 +321,12 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.LoadComplete(); BeatDivisor.BindValueChanged(_ => updateState(), true); - divisorTextBox.OnCommit += (_, _) => setPresets(); + divisorTextBox.OnCommit += (_, _) => setPresetsFromTextBoxEntry(); Schedule(() => GetContainingInputManager().ChangeFocus(divisorTextBox)); } - private void setPresets() + private void setPresetsFromTextBoxEntry() { if (!int.TryParse(divisorTextBox.Text, out int divisor) || divisor < 1 || divisor > 64) { From 39489358fa5f91d56b54e92b4e8c8b939da5b659 Mon Sep 17 00:00:00 2001 From: Cootz Date: Thu, 1 Jun 2023 14:07:05 +0300 Subject: [PATCH 1061/1400] Apply appearance animation to `aboveColumnsContent` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 3d42059540..a491da1f76 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -507,7 +507,7 @@ namespace osu.Game.Overlays.Mods base.PopIn(); - multiplierDisplay? + aboveColumnsContent? .FadeIn(fade_in_duration, Easing.OutQuint) .MoveToY(0, fade_in_duration, Easing.OutQuint); @@ -565,7 +565,7 @@ namespace osu.Game.Overlays.Mods base.PopOut(); - multiplierDisplay? + aboveColumnsContent? .FadeOut(fade_out_duration / 2, Easing.OutQuint) .MoveToY(-distance, fade_out_duration / 2, Easing.OutQuint); From 949fe327402bb9418b2875aba0a0e7658f931b91 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 31 May 2023 01:23:42 +0300 Subject: [PATCH 1062/1400] Use combined area of children as a mask instead --- .../Timeline/TimelineHitObjectBlueprint.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 900f0ff4a2..31cf6ad766 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -50,6 +50,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly Container colouredComponents; private readonly OsuSpriteText comboIndexText; + private readonly SamplePointPiece samplePointPiece; + private readonly DifficultyPointPiece difficultyPointPiece = null!; [Resolved] private ISkinSource skin { get; set; } = null!; @@ -101,7 +103,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline }, } }, - new SamplePointPiece(Item) + samplePointPiece = new SamplePointPiece(Item) { Anchor = Anchor.BottomLeft, Origin = Anchor.TopCentre @@ -118,7 +120,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline if (item is IHasSliderVelocity) { - AddInternal(new DifficultyPointPiece(Item) + AddInternal(difficultyPointPiece = new DifficultyPointPiece(Item) { Anchor = Anchor.TopLeft, Origin = Anchor.BottomCentre @@ -244,7 +246,23 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft; - protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; + protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) + { + // Since children are exceeding the component size, we need to use a custom quad to compute whether it should be masked away. + + // When component isn't masked away there's no need to apply custom logic. + if (!base.ComputeIsMaskedAway(maskingBounds)) + return false; + + // If component is considered masked away we'll use children to create an extended quad. + var rect = RectangleF.Union(ScreenSpaceDrawQuad.AABBFloat, circle.ScreenSpaceDrawQuad.AABBFloat); + rect = RectangleF.Union(rect, samplePointPiece.ScreenSpaceDrawQuad.AABBFloat); + + if (difficultyPointPiece != null) + rect = RectangleF.Union(rect, difficultyPointPiece.ScreenSpaceDrawQuad.AABBFloat); + + return !Precision.AlmostIntersects(maskingBounds, rect); + } private partial class Tick : Circle { From 03eb7c78300cd689d504dd8874b700a67dec1fa3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 1 Jun 2023 21:21:01 +0300 Subject: [PATCH 1063/1400] Fix nullability --- .../Compose/Components/Timeline/TimelineHitObjectBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 31cf6ad766..638e2d43c8 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private readonly Container colouredComponents; private readonly OsuSpriteText comboIndexText; private readonly SamplePointPiece samplePointPiece; - private readonly DifficultyPointPiece difficultyPointPiece = null!; + private readonly DifficultyPointPiece? difficultyPointPiece; [Resolved] private ISkinSource skin { get; set; } = null!; From c2d89a32a985515edb376b9abd3d23555dda5445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 1 Jun 2023 21:18:00 +0200 Subject: [PATCH 1064/1400] Adjust inline comment --- .../Components/Timeline/TimelineHitObjectBlueprint.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs index 638e2d43c8..55f122669d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineHitObjectBlueprint.cs @@ -250,11 +250,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { // Since children are exceeding the component size, we need to use a custom quad to compute whether it should be masked away. - // When component isn't masked away there's no need to apply custom logic. + // If the component isn't considered masked away by itself, there's no need to apply custom logic. if (!base.ComputeIsMaskedAway(maskingBounds)) return false; - // If component is considered masked away we'll use children to create an extended quad. + // If the component is considered masked away, we'll use children to create an extended quad that encapsulates all parts of this blueprint + // to ensure it doesn't pop in and out of existence abruptly when scrolling the timeline. var rect = RectangleF.Union(ScreenSpaceDrawQuad.AABBFloat, circle.ScreenSpaceDrawQuad.AABBFloat); rect = RectangleF.Union(rect, samplePointPiece.ScreenSpaceDrawQuad.AABBFloat); From c33ddedca0b6cdfaf4054dc80bbdcd2f5f20e842 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jun 2023 08:48:47 +0900 Subject: [PATCH 1065/1400] Disable all tablet handlers to guard against a grim future --- osu.Game/OsuGame.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 33ac8cc101..3768dad370 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1145,8 +1145,11 @@ namespace osu.Game IconColour = Colours.RedDark, }); - var tabletHandler = Host.AvailableInputHandlers.OfType().FirstOrDefault(); - if (tabletHandler != null) + // We only have one tablet handler currently. + // The loop here is weakly guarding against a future where more than one is added. + // If this is ever the case, this logic needs adjustment as it should probably only + // disable the relevant tablet handler rather than all. + foreach (var tabletHandler in Host.AvailableInputHandlers.OfType()) tabletHandler.Enabled.Value = false; }); } From a44b20832372c0f509f7fda6bfe4b35e829d649f Mon Sep 17 00:00:00 2001 From: John Biddle Date: Thu, 1 Jun 2023 21:25:49 -0700 Subject: [PATCH 1066/1400] Updated languages in Language.cs to match what is in osu-web/resources/lang/. Added Catalan, Persian, Filipino, Hebrew, Croatian, Lithuanian, Latvian, Malay, Slovenian, Serbian, Tajik, and Sinhala. --- osu.Game/Localisation/Language.cs | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index 6a4e5110e6..3f0f24f45f 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -22,6 +22,9 @@ namespace osu.Game.Localisation [Description(@"Български")] bg, + [Description(@"Català")] + ca, + [Description(@"Česky")] cs, @@ -37,12 +40,24 @@ namespace osu.Game.Localisation [Description(@"español")] es, + [Description(@"فارسی")] + fa_ir, + [Description(@"Suomi")] fi, + [Description(@"Filipino")] + fil, + [Description(@"français")] fr, + [Description(@"עברית")] + he, + + [Description(@"Hrvatski")] + hr_hr, + [Description(@"Magyar")] hu, @@ -58,6 +73,15 @@ namespace osu.Game.Localisation [Description(@"한국어")] ko, + [Description(@"Lietuvių")] + lt, + + [Description(@"Latviešu")] + lv_lv, + + [Description(@"Melayu")] + ms_my, + [Description(@"Nederlands")] nl, @@ -79,12 +103,24 @@ namespace osu.Game.Localisation [Description(@"Русский")] ru, + [Description(@"සිංහල")] + si_lk, + [Description(@"Slovenčina")] sk, + [Description(@"Slovenščina")] + sl, + + [Description(@"Српски")] + sr, + [Description(@"Svenska")] sv, + [Description(@"Тоҷикӣ")] + tg_tj, + [Description(@"ไทย")] th, @@ -105,6 +141,9 @@ namespace osu.Game.Localisation [Description(@"简体中文")] zh, + [Description(@"繁體中文")] + zh_tw, + // Traditional Chinese (Hong Kong) is listed in web sources but has no associated localisations, // and was wrongly falling back to Simplified Chinese. // Can be revisited if localisations ever arrive. From 325c114c1c9ba4b7f1bfa0630c2d1ab0885d1cf1 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 2 Jun 2023 10:39:27 +0300 Subject: [PATCH 1067/1400] Remove redundant xmldocs --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a491da1f76..af8a7bd810 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -64,9 +64,6 @@ namespace osu.Game.Overlays.Mods } } - /// - /// Search term applied on mod overlay - /// public string SearchTerm { get => SearchTextBox.Current.Value; @@ -79,9 +76,6 @@ namespace osu.Game.Overlays.Mods } } - /// - /// Search box applied on mod overlay - /// public ShearedSearchTextBox SearchTextBox { get; private set; } = null!; /// From d400387329e9c255e39a8229697ef47aeeb639cf Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 2 Jun 2023 10:51:33 +0300 Subject: [PATCH 1068/1400] Replace `IConditionalFilterable` with `IFilterable` --- osu.Game/Overlays/Mods/ModPanel.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index cd94226d8f..e3bd3ad370 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -14,7 +14,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public partial class ModPanel : ModSelectPanel, IConditionalFilterable + public partial class ModPanel : ModSelectPanel, IFilterable { public Mod Mod => modState.Mod; public override BindableBool Active => modState.Active; @@ -110,13 +110,6 @@ namespace osu.Game.Overlays.Mods } } - /// - /// This property is always because it affects search result - /// - private readonly BindableBool canBeShown = new BindableBool(true); - - IBindable IConditionalFilterable.CanBeShown => canBeShown; - private void updateFilterState() { this.FadeTo(IsValid ? 1 : 0); From 4c7cca101eab9879a7605c604be75c43516f26bf Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 2 Jun 2023 11:33:38 +0300 Subject: [PATCH 1069/1400] Rename `IsValid` to `Visible` --- .../TestSceneMultiplayerMatchSubScreen.cs | 2 +- .../Visual/UserInterface/TestSceneModColumn.cs | 16 ++++++++-------- .../UserInterface/TestSceneModSelectOverlay.cs | 16 ++++++++-------- .../Mods/Input/ClassicModHotkeyHandler.cs | 2 +- .../Mods/Input/SequentialModHotkeyHandler.cs | 2 +- osu.Game/Overlays/Mods/ModColumn.cs | 10 +++++----- osu.Game/Overlays/Mods/ModPanel.cs | 6 +++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +++--- osu.Game/Overlays/Mods/ModState.cs | 4 ++-- osu.Game/Overlays/Mods/SelectAllModsButton.cs | 2 +- 10 files changed, 33 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 40acea475b..a41eff067b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -203,7 +203,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("mod select contains only double time mod", () => this.ChildrenOfType().Single().UserModsSelectOverlay .ChildrenOfType() - .SingleOrDefault(panel => panel.IsValid)?.Mod is OsuModDoubleTime); + .SingleOrDefault(panel => panel.Visible)?.Mod is OsuModDoubleTime); } [Test] diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 394a38fe5d..255dbfcdd3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -106,26 +106,26 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.IsValid) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.Visible) == 2); clickToggle(); AddUntilStep("wait for animation", () => !column.SelectionAnimationRunning); - AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => panel.IsValid)); + AddAssert("only visible items selected", () => column.ChildrenOfType().Where(panel => panel.Active.Value).All(panel => panel.Visible)); AddStep("unset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.Visible)); AddAssert("checkbox not selected", () => !column.ChildrenOfType().Single().Current.Value); AddStep("set filter", () => setFilter(mod => mod.Name.Contains("Wind", StringComparison.CurrentCultureIgnoreCase))); - AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.IsValid) == 2); + AddUntilStep("two panels visible", () => column.ChildrenOfType().Count(panel => panel.Visible) == 2); AddAssert("checkbox selected", () => column.ChildrenOfType().Single().Current.Value); AddStep("filter out everything", () => setFilter(_ => false)); - AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => !panel.IsValid)); + AddUntilStep("no panels visible", () => column.ChildrenOfType().All(panel => !panel.Visible)); AddUntilStep("checkbox hidden", () => !column.ChildrenOfType().Single().IsPresent); AddStep("inset filter", () => setFilter(null)); - AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); + AddUntilStep("all panels visible", () => column.ChildrenOfType().All(panel => panel.Visible)); AddUntilStep("checkbox visible", () => column.ChildrenOfType().Single().IsPresent); void clickToggle() => AddStep("click toggle", () => @@ -320,14 +320,14 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("search by mod name", () => column.SearchTerm = searchTerm); - AddAssert("only hidden is visible", () => column.ChildrenOfType().Where(panel => panel.IsValid).All(panel => panel.Mod is ModHidden)); + AddAssert("only hidden is visible", () => column.ChildrenOfType().Where(panel => panel.Visible).All(panel => panel.Mod is ModHidden)); } void clearSearch() { AddStep("clear search", () => column.SearchTerm = string.Empty); - AddAssert("all mods are visible", () => column.ChildrenOfType().All(panel => panel.IsValid)); + AddAssert("all mods are visible", () => column.ChildrenOfType().All(panel => panel.Visible)); } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 22baea2581..c42f9af6df 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -490,15 +490,15 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); changeRuleset(0); - AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.IsValid)); + AddAssert("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.Visible)); AddStep("make double time invalid", () => modSelectOverlay.IsValidMod = m => !(m is OsuModDoubleTime)); - AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => !panel.IsValid)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => panel.IsValid)); + AddUntilStep("double time not visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).All(panel => !panel.Visible)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModNightcore).Any(panel => panel.Visible)); AddStep("make double time valid again", () => modSelectOverlay.IsValidMod = _ => true); - AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.IsValid)); - AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => panel.IsValid)); + AddUntilStep("double time visible", () => modSelectOverlay.ChildrenOfType().Where(panel => panel.Mod is OsuModDoubleTime).Any(panel => panel.Visible)); + AddAssert("nightcore still visible", () => modSelectOverlay.ChildrenOfType().Where(b => b.Mod is OsuModNightcore).Any(panel => panel.Visible)); } [Test] @@ -524,7 +524,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set ruleset", () => Ruleset.Value = testRuleset.RulesetInfo); waitForColumnLoad(); - AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).IsValid); + AddAssert("unimplemented mod panel is filtered", () => !getPanelForMod(typeof(TestUnimplementedMod)).Visible); } [Test] @@ -585,7 +585,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("select DT + HD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden() }); AddStep("focus on search", () => modSelectOverlay.SearchTextBox.TakeFocus()); AddStep("apply search", () => modSelectOverlay.SearchTerm = "Easy"); - AddAssert("DT + HD selected and hidden", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.IsValid && panel.Active.Value) == 2); + AddAssert("DT + HD selected and hidden", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.Visible && panel.Active.Value) == 2); AddStep("press backspace", () => InputManager.Key(Key.BackSpace)); AddAssert("DT + HD still selected", () => modSelectOverlay.ChildrenOfType().Count(panel => panel.Active.Value) == 2); @@ -630,7 +630,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("deselect all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); AddStep("apply search", () => modSelectOverlay.SearchTerm = "Easy"); - AddAssert("DT + HD + RD are hidden and selected", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.IsValid && panel.Active.Value) == 3); + AddAssert("DT + HD + RD are hidden and selected", () => modSelectOverlay.ChildrenOfType().Count(panel => !panel.Visible && panel.Active.Value) == 3); AddAssert("deselect all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); AddStep("click deselect all button", () => diff --git a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs index 343f7242f1..59a631a7b5 100644 --- a/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/ClassicModHotkeyHandler.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Mods.Input if (!mod_type_lookup.TryGetValue(e.Key, out var typesToMatch)) return false; - var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && modState.IsValid).ToArray(); + var matchingMods = availableMods.Where(modState => matches(modState, typesToMatch) && modState.Visible).ToArray(); if (matchingMods.Length == 0) return false; diff --git a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs index cbfa96307d..e638063438 100644 --- a/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs +++ b/osu.Game/Overlays/Mods/Input/SequentialModHotkeyHandler.cs @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Mods.Input if (index < 0) return false; - var modState = availableMods.Where(modState => modState.IsValid).ElementAtOrDefault(index); + var modState = availableMods.Where(modState => modState.Visible).ElementAtOrDefault(index); if (modState == null) return false; diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index f7d7d4db73..9146cd7abe 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -146,15 +146,15 @@ namespace osu.Game.Overlays.Mods private void updateState() { - Alpha = availableMods.All(mod => !mod.IsValid) ? 0 : 1; + Alpha = availableMods.All(mod => !mod.Visible) ? 0 : 1; if (toggleAllCheckbox != null && !SelectionAnimationRunning) { - toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.IsValid) ? 1 : 0; + toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.Visible) ? 1 : 0; //Prevent checkbox from checking when column have on valid panels - if (availableMods.Any(panel => panel.IsValid)) - toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.IsValid).All(panel => panel.Active.Value); + if (availableMods.Any(panel => panel.Visible)) + toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.Visible).All(panel => panel.Active.Value); } } @@ -199,7 +199,7 @@ namespace osu.Game.Overlays.Mods { pendingSelectionOperations.Clear(); - foreach (var button in availableMods.Where(b => !b.Active.Value && b.IsValid)) + foreach (var button in availableMods.Where(b => !b.Active.Value && b.Visible)) pendingSelectionOperations.Enqueue(() => button.Active.Value = true); } diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index e3bd3ad370..86ecdfa31d 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -73,9 +73,9 @@ namespace osu.Game.Overlays.Mods } /// - /// Determine if is valid and can be shown + /// Whether the is passing all filters and visible for user /// - public bool IsValid => modState.IsValid; + public bool Visible => modState.Visible; public bool ValidForSelection { @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.Mods private void updateFilterState() { - this.FadeTo(IsValid ? 1 : 0); + this.FadeTo(Visible ? 1 : 0); } #endregion diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index af8a7bd810..1d5849e3f2 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -511,7 +511,7 @@ namespace osu.Game.Overlays.Mods { var column = columnFlow[i].Column; - bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => !modState.IsValid); + bool allFiltered = column is ModColumn modColumn && modColumn.AvailableMods.All(modState => !modState.Visible); double delay = allFiltered ? 0 : nonFilteredColumnCount * 30; double duration = allFiltered ? 0 : fade_in_duration; @@ -573,7 +573,7 @@ namespace osu.Game.Overlays.Mods if (column is ModColumn modColumn) { - allFiltered = modColumn.AvailableMods.All(modState => !modState.IsValid); + allFiltered = modColumn.AvailableMods.All(modState => !modState.Visible); modColumn.FlushPendingSelections(); } @@ -623,7 +623,7 @@ namespace osu.Game.Overlays.Mods return true; } - ModState? firstMod = columnFlow.Columns.OfType().FirstOrDefault(m => m.IsPresent)?.AvailableMods.FirstOrDefault(x => x.IsValid); + ModState? firstMod = columnFlow.Columns.OfType().FirstOrDefault(m => m.IsPresent)?.AvailableMods.FirstOrDefault(x => x.Visible); if (firstMod is not null) firstMod.Active.Value = !firstMod.Active.Value; diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index be770ec937..5e0d768021 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.cs @@ -39,9 +39,9 @@ namespace osu.Game.Overlays.Mods public BindableBool ValidForSelection { get; } = new BindableBool(true); /// - /// Determine if is valid and can be shown + /// Whether the is passing all filters and visible for user /// - public bool IsValid => MatchingFilter.Value && ValidForSelection.Value; + public bool Visible => MatchingFilter.Value && ValidForSelection.Value; /// /// Whether the mod is matching the current filter, i.e. it is available for user selection. diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index dad4f7b629..8a6180a7c8 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Mods { Enabled.Value = availableMods.Value .SelectMany(pair => pair.Value) - .Any(modState => !modState.Active.Value && modState.IsValid); + .Any(modState => !modState.Active.Value && modState.Visible); } public bool OnPressed(KeyBindingPressEvent e) From bfe80fe143249cefe1798db4675c024075d3db12 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 2 Jun 2023 17:37:43 +0900 Subject: [PATCH 1070/1400] Fix legacy diffcalc creating all mods unnecessarily --- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 8dd1b51cae..00c90bd317 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Difficulty foreach (var combination in CreateDifficultyAdjustmentModCombinations()) { - Mod classicMod = rulesetInstance.CreateAllMods().SingleOrDefault(m => m is ModClassic); + Mod classicMod = rulesetInstance.CreateMod(); var finalCombination = ModUtils.FlattenMod(combination); if (classicMod != null) From 9d4ba5d64ab354b8163efc73a6287ec610a32fa9 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 2 Jun 2023 12:00:03 +0300 Subject: [PATCH 1071/1400] Remove unnecessary null checks --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 1d5849e3f2..ad5d571535 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -501,7 +501,7 @@ namespace osu.Game.Overlays.Mods base.PopIn(); - aboveColumnsContent? + aboveColumnsContent .FadeIn(fade_in_duration, Easing.OutQuint) .MoveToY(0, fade_in_duration, Easing.OutQuint); @@ -559,7 +559,7 @@ namespace osu.Game.Overlays.Mods base.PopOut(); - aboveColumnsContent? + aboveColumnsContent .FadeOut(fade_out_duration / 2, Easing.OutQuint) .MoveToY(-distance, fade_out_duration / 2, Easing.OutQuint); From a5fd833214566781159fa51ccc57df785c10817b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 2 Jun 2023 23:01:03 +0900 Subject: [PATCH 1072/1400] Fix "bubbles" mod not adding pool to hierarchy (and constructing too early) --- osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs index 12e2090f89..b74b722bad 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs @@ -42,14 +42,14 @@ namespace osu.Game.Rulesets.Osu.Mods private PlayfieldAdjustmentContainer bubbleContainer = null!; + private DrawablePool bubblePool = null!; + private readonly Bindable currentCombo = new BindableInt(); private float maxSize; private float bubbleSize; private double bubbleFade; - private readonly DrawablePool bubblePool = new DrawablePool(100); - public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) @@ -72,6 +72,7 @@ namespace osu.Game.Rulesets.Osu.Mods bubbleContainer = drawableRuleset.CreatePlayfieldAdjustmentContainer(); drawableRuleset.Overlays.Add(bubbleContainer); + drawableRuleset.Overlays.Add(bubblePool = new DrawablePool(100)); } public void ApplyToDrawableHitObject(DrawableHitObject drawableObject) From 69b640a185a1850159064a2701cba7726c27da44 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 3 Jun 2023 10:47:48 +0300 Subject: [PATCH 1073/1400] Remove hotkeys handling from `DeselectAllModsButton` --- osu.Game/Overlays/Mods/DeselectAllModsButton.cs | 5 +---- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index bdb37e3ead..3e5a3b12d1 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -18,7 +18,6 @@ namespace osu.Game.Overlays.Mods public partial class DeselectAllModsButton : ShearedButton, IKeyBindingHandler { private readonly Bindable> selectedMods = new Bindable>(); - private readonly ShearedSearchTextBox searchTextBox; public DeselectAllModsButton(ModSelectOverlay modSelectOverlay) : base(ModSelectOverlay.BUTTON_WIDTH) @@ -26,8 +25,6 @@ namespace osu.Game.Overlays.Mods Text = CommonStrings.DeselectAll; Action = modSelectOverlay.DeselectAll; - searchTextBox = modSelectOverlay.SearchTextBox; - selectedMods.BindTo(modSelectOverlay.SelectedMods); } @@ -45,7 +42,7 @@ namespace osu.Game.Overlays.Mods public bool OnPressed(KeyBindingPressEvent e) { - if (e.Repeat || e.Action != GlobalAction.DeselectAllMods || searchTextBox.HasFocus) + if (e.Repeat || e.Action != GlobalAction.DeselectAllMods) return false; TriggerClick(); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ad5d571535..e3977f6ecd 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -66,17 +66,17 @@ namespace osu.Game.Overlays.Mods public string SearchTerm { - get => SearchTextBox.Current.Value; + get => searchTextBox.Current.Value; set { - if (SearchTextBox.Current.Value == value) + if (searchTextBox.Current.Value == value) return; - SearchTextBox.Current.Value = value; + searchTextBox.Current.Value = value; } } - public ShearedSearchTextBox SearchTextBox { get; private set; } = null!; + private ShearedSearchTextBox searchTextBox = null!; /// /// Whether the total score multiplier calculated from the current selected set of mods should be shown. @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Padding = new MarginPadding { Horizontal = 100 }, - Child = SearchTextBox = new ShearedSearchTextBox + Child = searchTextBox = new ShearedSearchTextBox { HoldFocus = false, Width = 300 @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Mods base.Hide(); //We want to clear search for next user interaction with mod overlay - SearchTextBox.Current.Value = string.Empty; + searchTextBox.Current.Value = string.Empty; } private ModSettingChangeTracker? modSettingChangeTracker; @@ -289,7 +289,7 @@ namespace osu.Game.Overlays.Mods customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); - SearchTextBox.Current.BindValueChanged(query => + searchTextBox.Current.BindValueChanged(query => { foreach (var column in columnFlow.Columns) column.SearchTerm = query.NewValue; @@ -789,7 +789,7 @@ namespace osu.Game.Overlays.Mods if (!Active.Value) RequestScroll?.Invoke(this); - //Kill focus on SearchTextBox + //Kill focus on searchTextBox Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null)); return true; From 474f7c2bc075202e756aa8fe1141f9fe7faab1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 16:50:58 +0200 Subject: [PATCH 1074/1400] Fix code quality inspection --- osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index 0d9f91caa1..c27e30d5bb 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -233,7 +233,7 @@ namespace osu.Game.Tests.Visual.Multiplayer QueueMode = ServerAPIRoom.QueueMode.Value, AutoStartDuration = ServerAPIRoom.AutoStartDuration.Value }, - Playlist = ServerAPIRoom.Playlist.Select(item => TestMultiplayerClient.CreateMultiplayerPlaylistItem(item)).ToList(), + Playlist = ServerAPIRoom.Playlist.Select(CreateMultiplayerPlaylistItem).ToList(), Users = { localUser }, Host = localUser }; From 602d5db3bb66e84b9ade2d99b004fbdd5e130be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 19:40:01 +0200 Subject: [PATCH 1075/1400] Simplify column dimensions code `dimensions` would always receive exactly one item, so might as well inline it. And yes, at this point the grid container is mostly a glorified `FillFlowContainer { Direction = FlowDirection.Vertical }`, but I am not touching that in this pull pending further decisions with respect to direction. --- osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs index 31dd5df27a..c36d7726dc 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticsPanel.cs @@ -147,7 +147,6 @@ namespace osu.Game.Screens.Ranking.Statistics foreach (var item in statisticItems) { var columnContent = new List(); - var dimensions = new List(); if (!hitEventsAvailable && item.RequiresHitEvents) { @@ -161,8 +160,6 @@ namespace osu.Game.Screens.Ranking.Statistics Origin = Anchor.Centre, }); - dimensions.Add(new Dimension()); - rows.Add(new GridContainer { Anchor = Anchor.TopCentre, @@ -170,7 +167,7 @@ namespace osu.Game.Screens.Ranking.Statistics RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Content = new[] { columnContent.ToArray() }, - ColumnDimensions = dimensions.ToArray(), + ColumnDimensions = new[] { new Dimension() }, RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) } }); } From a8b102ef72ef42706d870030b1935c5e3de15a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 21:32:12 +0200 Subject: [PATCH 1076/1400] Remove duplicated `zh_tw` language `zh_hant` already covers it. --- osu.Game/Localisation/Language.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index 3f0f24f45f..14dedf9a2e 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -141,9 +141,6 @@ namespace osu.Game.Localisation [Description(@"简体中文")] zh, - [Description(@"繁體中文")] - zh_tw, - // Traditional Chinese (Hong Kong) is listed in web sources but has no associated localisations, // and was wrongly falling back to Simplified Chinese. // Can be revisited if localisations ever arrive. From a8a4c02bb3ca788580eb770695c76fe13936ef4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 21:48:03 +0200 Subject: [PATCH 1077/1400] Comment out languages with no glyph support --- osu.Game/Localisation/Language.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index 14dedf9a2e..7104583f95 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -40,8 +40,9 @@ namespace osu.Game.Localisation [Description(@"español")] es, - [Description(@"فارسی")] - fa_ir, + // TODO: Requires Arabic glyphs to be added to resources (and possibly also RTL support). + // [Description(@"فارسی")] + // fa_ir, [Description(@"Suomi")] fi, @@ -52,8 +53,9 @@ namespace osu.Game.Localisation [Description(@"français")] fr, - [Description(@"עברית")] - he, + // TODO: Requires Hebrew glyphs to be added to resources (and possibly also RTL support). + // [Description(@"עברית")] + // he, [Description(@"Hrvatski")] hr_hr, @@ -103,8 +105,10 @@ namespace osu.Game.Localisation [Description(@"Русский")] ru, - [Description(@"සිංහල")] - si_lk, + // TODO: Requires Sinhala glyphs to be added to resources. + // Additionally, no translations available yet. + // [Description(@"සිංහල")] + // si_lk, [Description(@"Slovenčina")] sk, From 14309ba951f01fa49a6cfb7e0786da5499279b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 23:42:08 +0200 Subject: [PATCH 1078/1400] Comment out Tajik due to lack of support on Windows ^<10 --- osu.Game/Localisation/Language.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index 7104583f95..962734e67a 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -122,8 +122,10 @@ namespace osu.Game.Localisation [Description(@"Svenska")] sv, - [Description(@"Тоҷикӣ")] - tg_tj, + // Tajik has no associated localisations yet, and is not supported on Windows versions <10. + // TODO: update language mapping in osu-resources to redirect tg-TJ to tg-Cyrl-TJ (which is supported on earlier Windows versions) + // [Description(@"Тоҷикӣ")] + // tg_tj, [Description(@"ไทย")] th, From 4f5dfecbb850a41b532ce25b0bf24fd1772c2075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 3 Jun 2023 23:55:05 +0200 Subject: [PATCH 1079/1400] Comment out Filipino due to satellite assembly copy failure --- osu.Game/Localisation/Language.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/Language.cs b/osu.Game/Localisation/Language.cs index 962734e67a..711e95486f 100644 --- a/osu.Game/Localisation/Language.cs +++ b/osu.Game/Localisation/Language.cs @@ -47,8 +47,9 @@ namespace osu.Game.Localisation [Description(@"Suomi")] fi, - [Description(@"Filipino")] - fil, + // TODO: Doesn't work as appropriate satellite assemblies aren't copied from resources (see: https://github.com/ppy/osu/discussions/18851#discussioncomment-3042170) + // [Description(@"Filipino")] + // fil, [Description(@"français")] fr, From 3e308e4c278a01e94090a4c578fe5cf4970a1f32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Jun 2023 12:50:30 +0900 Subject: [PATCH 1080/1400] Add test coverage showing commit failure in manage collections dialog --- .../TestSceneManageCollectionsDialog.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index 1e9982f8d4..cfa45ec6ef 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -264,8 +264,9 @@ namespace osu.Game.Tests.Visual.Collections assertCollectionName(1, "First"); } - [Test] - public void TestCollectionRenamedOnTextChange() + [TestCase(false)] + [TestCase(true)] + public void TestCollectionRenamedOnTextChange(bool commitWithEnter) { BeatmapCollection first = null!; DrawableCollectionListItem firstItem = null!; @@ -293,9 +294,19 @@ namespace osu.Game.Tests.Visual.Collections AddStep("change first collection name", () => { firstItem.ChildrenOfType().First().Text = "First"; - InputManager.Key(Key.Enter); }); + if (commitWithEnter) + AddStep("commit via enter", () => InputManager.Key(Key.Enter)); + else + { + AddStep("commit via click away", () => + { + InputManager.MoveMouseTo(firstItem.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)); + InputManager.Click(MouseButton.Left); + }); + } + AddUntilStep("collection has new name", () => first.Name == "First"); } From eb7586b517dd0f4794f94edd59fcaff7bc8597cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 4 Jun 2023 12:51:03 +0900 Subject: [PATCH 1081/1400] Ensure collection edit textbox commits on focus loss As discussed in https://github.com/ppy/osu/discussions/23739 --- osu.Game/Collections/DrawableCollectionListItem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Collections/DrawableCollectionListItem.cs b/osu.Game/Collections/DrawableCollectionListItem.cs index 23156b1ad5..0ab0ff520d 100644 --- a/osu.Game/Collections/DrawableCollectionListItem.cs +++ b/osu.Game/Collections/DrawableCollectionListItem.cs @@ -86,6 +86,7 @@ namespace osu.Game.Collections RelativeSizeAxes = Axes.Both, Size = Vector2.One, CornerRadius = item_height / 2, + CommitOnFocusLost = true, PlaceholderText = collection.IsManaged ? string.Empty : "Create a new collection" }, } From 32b9e6ec8f0a5a395d2295e0510fa3c40a058e67 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 4 Jun 2023 17:02:46 +0300 Subject: [PATCH 1082/1400] Make search bar active by default --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e3977f6ecd..9d07ee1c93 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -66,17 +66,17 @@ namespace osu.Game.Overlays.Mods public string SearchTerm { - get => searchTextBox.Current.Value; + get => SearchTextBox.Current.Value; set { - if (searchTextBox.Current.Value == value) + if (SearchTextBox.Current.Value == value) return; - searchTextBox.Current.Value = value; + SearchTextBox.Current.Value = value; } } - private ShearedSearchTextBox searchTextBox = null!; + public ShearedSearchTextBox SearchTextBox { get; private set; } = null!; /// /// Whether the total score multiplier calculated from the current selected set of mods should be shown. @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Mods RelativeSizeAxes = Axes.X, Height = ModsEffectDisplay.HEIGHT, Padding = new MarginPadding { Horizontal = 100 }, - Child = searchTextBox = new ShearedSearchTextBox + Child = SearchTextBox = new ShearedSearchTextBox { HoldFocus = false, Width = 300 @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Mods base.Hide(); //We want to clear search for next user interaction with mod overlay - searchTextBox.Current.Value = string.Empty; + SearchTextBox.Current.Value = string.Empty; } private ModSettingChangeTracker? modSettingChangeTracker; @@ -289,12 +289,14 @@ namespace osu.Game.Overlays.Mods customisationVisible.BindValueChanged(_ => updateCustomisationVisualState(), true); - searchTextBox.Current.BindValueChanged(query => + SearchTextBox.Current.BindValueChanged(query => { foreach (var column in columnFlow.Columns) column.SearchTerm = query.NewValue; }, true); + SearchTextBox.TakeFocus(); + // Start scrolled slightly to the right to give the user a sense that // there is more horizontal content available. ScheduleAfterChildren(() => @@ -789,7 +791,7 @@ namespace osu.Game.Overlays.Mods if (!Active.Value) RequestScroll?.Invoke(this); - //Kill focus on searchTextBox + //Kill focus on SearchTextBox Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null)); return true; From fd554033db74781f4a40a25527c91d34d7c79cc3 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 4 Jun 2023 17:11:04 +0300 Subject: [PATCH 1083/1400] Update tests --- .../Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs | 2 ++ .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index 45f671618e..60bd88cc2b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -62,6 +62,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { createFreeModSelect(); + AddStep("kill search bar focus", () => freeModSelectOverlay.SearchTextBox.KillFocus()); + AddStep("press ctrl+a", () => InputManager.Keys(PlatformAction.SelectAll)); AddUntilStep("all mods selected", assertAllAvailableModsSelected); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index c42f9af6df..26369edeb6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -23,6 +23,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Mods; using osuTK; using osuTK.Input; @@ -569,6 +570,8 @@ namespace osu.Game.Tests.Visual.UserInterface createScreen(); changeRuleset(0); + AddStep("kill search bar focus", () => modSelectOverlay.SearchTextBox.KillFocus()); + AddStep("select DT + HD", () => SelectedMods.Value = new Mod[] { new OsuModDoubleTime(), new OsuModHidden() }); AddAssert("DT + HD selected", () => modSelectOverlay.ChildrenOfType().Count(panel => panel.Active.Value) == 2); From a46f5b90d4c4db173675e080f4aef42f508b9e48 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 4 Jun 2023 18:11:44 +0300 Subject: [PATCH 1084/1400] Move focus handling into `PopIn` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9d07ee1c93..7380c53073 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -295,8 +295,6 @@ namespace osu.Game.Overlays.Mods column.SearchTerm = query.NewValue; }, true); - SearchTextBox.TakeFocus(); - // Start scrolled slightly to the right to give the user a sense that // there is more horizontal content available. ScheduleAfterChildren(() => @@ -503,6 +501,8 @@ namespace osu.Game.Overlays.Mods base.PopIn(); + SearchTextBox.TakeFocus(); + aboveColumnsContent .FadeIn(fade_in_duration, Easing.OutQuint) .MoveToY(0, fade_in_duration, Easing.OutQuint); From 4eb0f0261ce153539329360534eda00a551561ea Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 4 Jun 2023 22:52:05 -0700 Subject: [PATCH 1085/1400] Fix song select beatmap panels not displaying correct background shown in web --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 3975bb6bb6..d544db66b1 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Select.Carousel Header.Children = new Drawable[] { - background = new DelayedLoadWrapper(() => new SetPanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) + background = new DelayedLoadWrapper(() => new SetPanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.MinBy(b => b.OnlineID))) { RelativeSizeAxes = Axes.Both, }, 300) From 3ebc8014847ed22b189ab1843ad8ae72bd31e8a3 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 5 Jun 2023 13:49:07 +0300 Subject: [PATCH 1086/1400] Move (de)select all mods hotkeys handling to `ModSelectOverlay` --- .../TestSceneModSelectOverlay.cs | 1 - .../Overlays/Mods/DeselectAllModsButton.cs | 18 +-------- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 37 ++++++++++++++++++- osu.Game/Overlays/Mods/SelectAllModsButton.cs | 18 +-------- .../OnlinePlay/FreeModSelectOverlay.cs | 14 ++++--- 5 files changed, 45 insertions(+), 43 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 26369edeb6..37b6a6d44f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -23,7 +23,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Taiko.Mods; -using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Mods; using osuTK; using osuTK.Input; diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index 3e5a3b12d1..817b6beac3 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -6,16 +6,13 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; -using osu.Game.Input.Bindings; using osu.Game.Localisation; using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { - public partial class DeselectAllModsButton : ShearedButton, IKeyBindingHandler + public partial class DeselectAllModsButton : ShearedButton { private readonly Bindable> selectedMods = new Bindable>(); @@ -39,18 +36,5 @@ namespace osu.Game.Overlays.Mods { Enabled.Value = selectedMods.Value.Any(); } - - public bool OnPressed(KeyBindingPressEvent e) - { - if (e.Repeat || e.Action != GlobalAction.DeselectAllMods) - return false; - - TriggerClick(); - return true; - } - - public void OnReleased(KeyBindingReleaseEvent e) - { - } } } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 7380c53073..51e1c33124 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -12,6 +12,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Audio; @@ -28,7 +30,7 @@ using osuTK; namespace osu.Game.Overlays.Mods { - public abstract partial class ModSelectOverlay : ShearedOverlayContainer, ISamplePlaybackDisabler + public abstract partial class ModSelectOverlay : ShearedOverlayContainer, ISamplePlaybackDisabler, IKeyBindingHandler { public const int BUTTON_WIDTH = 200; @@ -108,7 +110,7 @@ namespace osu.Game.Overlays.Mods }; } - yield return new DeselectAllModsButton(this); + yield return deselectAllModsButton = new DeselectAllModsButton(this); } private readonly Bindable>> globalAvailableMods = new Bindable>>(); @@ -121,12 +123,14 @@ namespace osu.Game.Overlays.Mods private ColumnScrollContainer columnScroll = null!; private ColumnFlowContainer columnFlow = null!; private FillFlowContainer footerButtonFlow = null!; + private DeselectAllModsButton deselectAllModsButton = null!; private Container aboveColumnsContent = null!; private DifficultyMultiplierDisplay? multiplierDisplay; protected ShearedButton BackButton { get; private set; } = null!; protected ShearedToggleButton? CustomisationButton { get; private set; } + protected SelectAllModsButton? SelectAllModsButton { get; set; } private Sample? columnAppearSample; @@ -616,6 +620,18 @@ namespace osu.Game.Overlays.Mods hideOverlay(true); return true; + //This is handled locally here to prevent search box from coupling in DeselectAllModsButton + case GlobalAction.DeselectAllMods: + { + if (!SearchTextBox.HasFocus) + { + deselectAllModsButton.TriggerClick(); + return true; + } + + break; + } + case GlobalAction.Select: { // Pressing select should select first filtered mod or completely hide the overlay in one shot if search term is empty. @@ -651,6 +667,23 @@ namespace osu.Game.Overlays.Mods } } + /// + /// + /// This is handled locally here to allow handle first + /// > + public bool OnPressed(KeyBindingPressEvent e) + { + if (e.Repeat || e.Action != PlatformAction.SelectAll || SelectAllModsButton is null) + return false; + + SelectAllModsButton.TriggerClick(); + return true; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + #endregion #region Sample playback control diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index 8a6180a7c8..83c46cfc1f 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -6,9 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; -using osu.Framework.Input; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Rulesets.Mods; @@ -16,7 +13,7 @@ using osu.Game.Screens.OnlinePlay; namespace osu.Game.Overlays.Mods { - public partial class SelectAllModsButton : ShearedButton, IKeyBindingHandler + public partial class SelectAllModsButton : ShearedButton { private readonly Bindable> selectedMods = new Bindable>(); private readonly Bindable>> availableMods = new Bindable>>(); @@ -46,18 +43,5 @@ namespace osu.Game.Overlays.Mods .SelectMany(pair => pair.Value) .Any(modState => !modState.Active.Value && modState.Visible); } - - public bool OnPressed(KeyBindingPressEvent e) - { - if (e.Repeat || e.Action != PlatformAction.SelectAll) - return false; - - TriggerClick(); - return true; - } - - public void OnReleased(KeyBindingReleaseEvent e) - { - } } } diff --git a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs index 6313d907a5..d5e57b9ec9 100644 --- a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs @@ -34,11 +34,13 @@ namespace osu.Game.Screens.OnlinePlay protected override ModColumn CreateModColumn(ModType modType) => new ModColumn(modType, true); - protected override IEnumerable CreateFooterButtons() => base.CreateFooterButtons().Prepend( - new SelectAllModsButton(this) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - }); + protected override IEnumerable CreateFooterButtons() + => base.CreateFooterButtons() + .Prepend( + SelectAllModsButton = new SelectAllModsButton(this) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); } } From 71e6f80c40e36a3b3f14f8d4ccdb38e707cf6b17 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 5 Jun 2023 15:54:19 +0300 Subject: [PATCH 1087/1400] Add hotkey for switching search bar focus --- .../TestSceneModSelectOverlay.cs | 22 +++++++++++++++---- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 14 ++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 37b6a6d44f..ffc0a0a0ad 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -546,16 +546,16 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestSearchFocusChange() + public void TestSearchFocusChangeViaClick() { createScreen(); - AddStep("click on search", navigateAndClick); - AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); - AddStep("click on mod column", navigateAndClick); AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); + AddStep("click on search", navigateAndClick); + AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); + void navigateAndClick() where T : Drawable { InputManager.MoveMouseTo(modSelectOverlay.ChildrenOfType().FirstOrDefault()); @@ -563,6 +563,20 @@ namespace osu.Game.Tests.Visual.UserInterface } } + [Test] + public void TestSearchFocusChangeViaKey() + { + createScreen(); + + const Key focus_switch_key = Key.Tab; + + AddStep("press tab", () => InputManager.Key(focus_switch_key)); + AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); + + AddStep("press tab", () => InputManager.Key(focus_switch_key)); + AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); + } + [Test] public void TestDeselectAllViaKey() { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 51e1c33124..3795ed729d 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -27,6 +27,7 @@ using osu.Game.Localisation; using osu.Game.Rulesets.Mods; using osu.Game.Utils; using osuTK; +using osuTK.Input; namespace osu.Game.Overlays.Mods { @@ -684,6 +685,19 @@ namespace osu.Game.Overlays.Mods { } + protected override bool OnKeyDown(KeyDownEvent e) + { + if (e.Repeat || e.Key != Key.Tab) + return false; + + if (SearchTextBox.HasFocus) + SearchTextBox.KillFocus(); + else + SearchTextBox.TakeFocus(); + + return true; + } + #endregion #region Sample playback control From 5c1abdc7044d57ca24f6f3f8c09ba9ad8874015c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 5 Jun 2023 21:33:08 +0200 Subject: [PATCH 1088/1400] Fix screen navigation test hijacking dummy request handler In an upcoming change, I stumbled upon a test failure mode wherein tests in `TestSceneScreenNavigation` would die on the following exception: 2023-05-07 17:58:42 [error]: System.ObjectDisposedException: Cannot access a closed Realm. 2023-05-07 17:58:42 [error]: Object name: 'Realms.Realm'. 2023-05-07 17:58:42 [error]: at Realms.Realm.ThrowIfDisposed() 2023-05-07 17:58:42 [error]: at Realms.Realm.All[T]() 2023-05-07 17:58:42 [error]: at osu.Game.Beatmaps.BeatmapManager.<>c__DisplayClass25_0.b__0(Realm r) in D:\a\osu\osu\osu.Game\Beatmaps\BeatmapManager.cs:line 282 2023-05-07 17:58:42 [error]: at osu.Game.Database.RealmAccess.Run[T](Func`2 action) in D:\a\osu\osu\osu.Game\Database\RealmAccess.cs:line 387 2023-05-07 17:58:42 [error]: at osu.Game.Beatmaps.BeatmapManager.QueryBeatmap(Expression`1 query) in D:\a\osu\osu\osu.Game\Beatmaps\BeatmapManager.cs:line 282 2023-05-07 17:58:42 [error]: at osu.Game.Tests.Visual.OnlinePlay.TestRoomRequestsHandler.g__createResponseBeatmaps|6_0(Int32[] beatmapIds, <>c__DisplayClass6_0& ) in D:\a\osu\osu\osu.Game\Tests\Visual\OnlinePlay\TestRoomRequestsHandler.cs:line 174 2023-05-07 17:58:42 [error]: at osu.Game.Tests.Visual.OnlinePlay.TestRoomRequestsHandler.HandleRequest(APIRequest request, APIUser localUser, BeatmapManager beatmapManager) in D:\a\osu\osu\osu.Game\Tests\Visual\OnlinePlay\TestRoomRequestsHandler.cs:line 140 2023-05-07 17:58:42 [error]: at osu.Game.Tests.Visual.TestMultiplayerComponents.<>c__DisplayClass18_0.b__0(APIRequest request) in D:\a\osu\osu\osu.Game.Tests\Visual\TestMultiplayerComponents.cs:line 80 2023-05-07 17:58:42 [error]: at osu.Game.Online.API.DummyAPIAccess.<>c__DisplayClass32_0.b__0() in D:\a\osu\osu\osu.Game\Online\API\DummyAPIAccess.cs:line 74 Upon closer inspection, one of the tests in the scene instantiates a `TestMultiplayerComponents` instance. `TestMultiplayerComponents` registers a custom request handler onto `DummyAPIAccess`. Normally, this is not an issue; however, because `TestSceneScreenNavigation` is an `OsuGameTestScene`, and therefore has its storage recycled after every test, this leads to the error above in the following scenario: 1. `TestPushMatchSubScreenAndPressBackButtonImmediately()` passes. 2. The test is cleaned up, and the test case's storage is recycled, including the test case's realm database. 3. In a subsequent test, a web request handled by the dummy API request handler is fired. The dummy API request handler subsequently attempts to access a realm that does not exist anymore. As the usage of `TestMultiplayerComponents` is highly unorthodox in this particular case, I'm opting for a localised fix which ensures that the request handler is cleaned up appropriately. --- .../Visual/Navigation/TestSceneScreenNavigation.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 193cec8907..18aef99ccd 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -17,6 +17,7 @@ using osu.Game.Beatmaps; using osu.Game.Collections; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Online.Leaderboards; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; @@ -539,6 +540,11 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open()); AddStep("press back button", () => Game.ChildrenOfType().First().Action()); AddWaitStep("wait two frames", 2); + + AddStep("exit lounge", () => Game.ScreenStack.Exit()); + // `TestMultiplayerComponents` registers a request handler in its BDL, but never unregisters it. + // to prevent the handler living for longer than it should be, clean up manually. + AddStep("clean up multiplayer request handler", () => ((DummyAPIAccess)API).HandleRequest = null); } [Test] From c54670aee1d715c7662517daab78ac591e8dd773 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 13:30:56 +0900 Subject: [PATCH 1089/1400] Add comment explaining implementation --- osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index d544db66b1..b97d37c854 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -108,6 +108,7 @@ namespace osu.Game.Screens.Select.Carousel Header.Children = new Drawable[] { + // Choice of background image matches BSS implementation (always uses the lowest `beatmap_id` from the set). background = new DelayedLoadWrapper(() => new SetPanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.MinBy(b => b.OnlineID))) { RelativeSizeAxes = Axes.Both, From 2f11bd5473af40d1b53b61de79912b587dd9451f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 14:42:42 +0900 Subject: [PATCH 1090/1400] Adjust animations slightly --- osu.Game/Screens/Play/ArgonKeyCounter.cs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/ArgonKeyCounter.cs b/osu.Game/Screens/Play/ArgonKeyCounter.cs index 53305901ee..2d725898d8 100644 --- a/osu.Game/Screens/Play/ArgonKeyCounter.cs +++ b/osu.Game/Screens/Play/ArgonKeyCounter.cs @@ -25,13 +25,16 @@ namespace osu.Game.Screens.Play // Make things look bigger without using Scale private const float scale_factor = 1.5f; + [Resolved] + private OsuColour colours { get; set; } = null!; + public ArgonKeyCounter(InputTrigger trigger) : base(trigger) { } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Children = new Drawable[] { @@ -76,14 +79,27 @@ namespace osu.Game.Screens.Play protected override void Activate(bool forwardPlayback = true) { base.Activate(forwardPlayback); - keyNameText.FlashColour(Colour4.White, 200); - inputIndicator.FadeIn().MoveToY(0).Then().MoveToY(3, 100, Easing.OutQuart); + + keyNameText + .FadeColour(Colour4.White, 10, Easing.OutQuint); + + inputIndicator + .FadeIn(10, Easing.OutQuint) + .MoveToY(0) + .Then() + .MoveToY(4, 60, Easing.OutQuint); } protected override void Deactivate(bool forwardPlayback = true) { base.Deactivate(forwardPlayback); - inputIndicator.MoveToY(0, 200, Easing.OutQuart).FadeTo(0.5f, 200, Easing.OutQuart); + + keyNameText + .FadeColour(colours.Blue0, 200, Easing.OutQuart); + + inputIndicator + .MoveToY(0, 250, Easing.OutQuart) + .FadeTo(0.5f, 250, Easing.OutQuart); } } } From 22f7fe1d79c325fe0c38418ca31a0dced1a5e1d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 15:11:31 +0900 Subject: [PATCH 1091/1400] Rename variable and ensure timestamp is updated even when not saving --- osu.Game/Beatmaps/BeatmapInfo.cs | 5 ++++- osu.Game/Screens/Edit/Editor.cs | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 7ca0e24913..5019d64276 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -171,7 +171,10 @@ namespace osu.Game.Beatmaps public double TimelineZoom { get; set; } = 1.0; - public double? LastEditTime { get; set; } + /// + /// The time in milliseconds when last exiting the editor with this beatmap loaded. + /// + public double? EditorTimestamp { get; set; } [Ignored] public CountdownType Countdown { get; set; } = CountdownType.Normal; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c3d72c7aec..bb052b1d22 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -28,6 +28,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Configuration; +using osu.Game.Database; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; @@ -92,6 +93,9 @@ namespace osu.Game.Screens.Edit [Resolved(canBeNull: true)] private INotificationOverlay notifications { get; set; } + [Resolved] + private RealmAccess realm { get; set; } + public readonly Bindable Mode = new Bindable(); public IBindable SamplePlaybackDisabled => samplePlaybackDisabled; @@ -441,8 +445,6 @@ namespace osu.Game.Screens.Edit try { - editorBeatmap.BeatmapInfo.LastEditTime = clock.CurrentTime; - // save the loaded beatmap's data stream. beatmapManager.Save(editorBeatmap.BeatmapInfo, editorBeatmap.PlayableBeatmap, editorBeatmap.BeatmapSkin); } @@ -702,6 +704,13 @@ namespace osu.Game.Screens.Edit } } + realm.Write(r => + { + var beatmap = r.Find(editorBeatmap.BeatmapInfo.ID); + if (beatmap != null) + beatmap.EditorTimestamp = clock.CurrentTime; + }); + ApplyToBackground(b => { b.DimWhenUserSettingsIgnored.Value = 0; @@ -835,9 +844,9 @@ namespace osu.Game.Screens.Edit { double targetTime = 0; - if (editorBeatmap.BeatmapInfo.LastEditTime != null) + if (editorBeatmap.BeatmapInfo.EditorTimestamp != null) { - targetTime = editorBeatmap.BeatmapInfo.LastEditTime.Value; + targetTime = editorBeatmap.BeatmapInfo.EditorTimestamp.Value; } else if (Beatmap.Value.Beatmap.HitObjects.Count > 0) { From 878cdb2ed34655f54dad8d59395202e850e98d30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 15:11:37 +0900 Subject: [PATCH 1092/1400] Bump schema version --- osu.Game/Database/RealmAccess.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 94108531e8..9e5f41502b 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -71,8 +71,9 @@ namespace osu.Game.Database /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. + /// 27 2023-06-06 Added EditorTimestamp to ScoreInfo. /// - private const int schema_version = 26; + private const int schema_version = 27; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. From 66b8b5192b2d2661bca537bf1e6311b3578bf3f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 15:23:59 +0900 Subject: [PATCH 1093/1400] Add test coverage of editor timestamp remembering --- .../TestSceneBeatmapEditorNavigation.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs index 1b2bb57b84..5483be5676 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneBeatmapEditorNavigation.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); - AddStep("test gameplay", () => ((Editor)Game.ScreenStack.CurrentScreen).TestGameplay()); + AddStep("test gameplay", () => getEditor().TestGameplay()); AddUntilStep("wait for player", () => { @@ -141,6 +141,37 @@ namespace osu.Game.Tests.Visual.Navigation AddUntilStep("wait for editor exit", () => Game.ScreenStack.CurrentScreen is not Editor); } - private EditorBeatmap getEditorBeatmap() => ((Editor)Game.ScreenStack.CurrentScreen).ChildrenOfType().Single(); + [Test] + public void TestLastTimestampRememberedOnExit() + { + BeatmapSetInfo beatmapSet = null!; + + AddStep("import test beatmap", () => Game.BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely()); + AddStep("retrieve beatmap", () => beatmapSet = Game.BeatmapManager.QueryBeatmapSet(set => !set.Protected).AsNonNull().Value.Detach()); + + AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet)); + AddUntilStep("wait for song select", + () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet) + && Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect + && songSelect.IsLoaded); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0))); + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + + AddStep("seek to arbitrary time", () => getEditor().ChildrenOfType().First().Seek(1234)); + AddUntilStep("time is correct", () => getEditor().ChildrenOfType().First().CurrentTime, () => Is.EqualTo(1234)); + + AddStep("exit editor", () => InputManager.Key(Key.Escape)); + AddUntilStep("wait for editor exit", () => Game.ScreenStack.CurrentScreen is not Editor); + + AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit()); + + AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse); + AddUntilStep("time is correct", () => getEditor().ChildrenOfType().First().CurrentTime, () => Is.EqualTo(1234)); + } + + private EditorBeatmap getEditorBeatmap() => getEditor().ChildrenOfType().Single(); + + private Editor getEditor() => (Editor)Game.ScreenStack.CurrentScreen; } } From a18a2e48f75e4aca729abbd34e6a7285ea8804cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 15:47:30 +0900 Subject: [PATCH 1094/1400] Colour argon osu!taiko explosions based on the object hit --- .../Skinning/Argon/ArgonHitExplosion.cs | 26 ++++++++--------- .../Skinning/Argon/ArgonInputDrum.cs | 28 ++++++++++++------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs index a47fd7e62e..cddae7f05b 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonHitExplosion.cs @@ -1,9 +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.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; @@ -18,7 +16,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon public partial class ArgonHitExplosion : CompositeDrawable, IAnimatableHitExplosion { private readonly TaikoSkinComponents component; + private readonly Circle outer; + private readonly Circle inner; public ArgonHitExplosion(TaikoSkinComponents component) { @@ -34,13 +34,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical( - new Color4(255, 227, 236, 255), - new Color4(255, 198, 211, 255) - ), Masking = true, }, - new Circle + inner = new Circle { Name = "Inner circle", Anchor = Anchor.Centre, @@ -48,12 +44,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon RelativeSizeAxes = Axes.Both, Colour = Color4.White, Size = new Vector2(0.85f), - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = new Color4(255, 132, 191, 255).Opacity(0.5f), - Radius = 45, - }, Masking = true, }, }; @@ -63,6 +53,16 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon { this.FadeOut(); + bool isRim = (drawableHitObject.HitObject as Hit)?.Type == HitType.Rim; + + outer.Colour = isRim ? ArgonInputDrum.RIM_HIT_GRADIENT : ArgonInputDrum.CENTRE_HIT_GRADIENT; + inner.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = (isRim ? ArgonInputDrum.RIM_HIT_GLOW : ArgonInputDrum.CENTRE_HIT_GLOW).Opacity(0.5f), + Radius = 45, + }; + switch (component) { case TaikoSkinComponents.TaikoExplosionGreat: diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs index e7b0a5537a..f7b7105bdc 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonInputDrum.cs @@ -19,6 +19,20 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon { public partial class ArgonInputDrum : AspectContainer { + public static readonly ColourInfo RIM_HIT_GRADIENT = ColourInfo.GradientHorizontal( + new Color4(227, 248, 255, 255), + new Color4(198, 245, 255, 255) + ); + + public static readonly Colour4 RIM_HIT_GLOW = new Color4(126, 215, 253, 255); + + public static readonly ColourInfo CENTRE_HIT_GRADIENT = ColourInfo.GradientHorizontal( + new Color4(255, 227, 236, 255), + new Color4(255, 198, 211, 255) + ); + + public static readonly Colour4 CENTRE_HIT_GLOW = new Color4(255, 147, 199, 255); + private const float rim_size = 0.3f; public ArgonInputDrum() @@ -141,14 +155,11 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon Anchor = anchor, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal( - new Color4(227, 248, 255, 255), - new Color4(198, 245, 255, 255) - ), + Colour = RIM_HIT_GRADIENT, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Colour = new Color4(126, 215, 253, 170), + Colour = RIM_HIT_GLOW.Opacity(0.66f), Radius = 50, }, Alpha = 0, @@ -166,14 +177,11 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon Anchor = anchor, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal( - new Color4(255, 227, 236, 255), - new Color4(255, 198, 211, 255) - ), + Colour = CENTRE_HIT_GRADIENT, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Colour = new Color4(255, 147, 199, 255), + Colour = CENTRE_HIT_GLOW, Radius = 50, }, Size = new Vector2(1 - rim_size), From b8d9c9ff93c3b27c6bbe832eb032401144d7c807 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:07:00 +0900 Subject: [PATCH 1095/1400] Move `ApplyGameWideClock` to extension method I don't see an issue with applying this workaround to more places, even though it is a workaround, because it marks each usage very clearly. If we design a better solution in the future it should be easy to replace the usages. --- osu.Game.Rulesets.Mania/UI/Column.cs | 17 +++-------------- osu.Game/Extensions/DrawableExtensions.cs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 6ca830a82f..7033fd6755 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Pooling; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Platform; +using osu.Game.Extensions; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -97,8 +98,8 @@ namespace osu.Game.Rulesets.Mania.UI new ColumnTouchInputArea(this) }; - applyGameWideClock(background); - applyGameWideClock(keyArea); + background.ApplyGameWideClock(host); + keyArea.ApplyGameWideClock(host); TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy()); @@ -107,18 +108,6 @@ namespace osu.Game.Rulesets.Mania.UI RegisterPool(10, 50); RegisterPool(10, 50); RegisterPool(50, 250); - - // Some elements don't handle rewind correctly and fixing them is non-trivial. - // In the future we need a better solution to this, but as a temporary work-around, give these components the game-wide - // clock so they don't need to worry about rewind. - // This only works because they handle OnPressed/OnReleased which results in a correct state while rewinding. - // - // This is kinda dodgy (and will cause weirdness when pausing gameplay) but is better than completely broken rewind. - void applyGameWideClock(Drawable drawable) - { - drawable.Clock = host.UpdateThread.Clock; - drawable.ProcessCustomClock = false; - } } private void onSourceChanged() diff --git a/osu.Game/Extensions/DrawableExtensions.cs b/osu.Game/Extensions/DrawableExtensions.cs index 915a2292a2..6553ad3886 100644 --- a/osu.Game/Extensions/DrawableExtensions.cs +++ b/osu.Game/Extensions/DrawableExtensions.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; +using osu.Framework.Platform; using osuTK; namespace osu.Game.Extensions @@ -43,5 +44,20 @@ namespace osu.Game.Extensions /// The delta vector in Parent's coordinates. public static Vector2 ScreenSpaceDeltaToParentSpace(this Drawable drawable, Vector2 delta) => drawable.Parent.ToLocalSpace(drawable.Parent.ToScreenSpace(Vector2.Zero) + delta); + + /// + /// Some elements don't handle rewind correctly and fixing them is non-trivial. + /// In the future we need a better solution to this, but as a temporary work-around, give these components the game-wide + /// clock so they don't need to worry about rewind. + /// + /// This only works if input handling components handle OnPressed/OnReleased which results in a correct state while rewinding. + /// + /// This is kinda dodgy (and will cause weirdness when pausing gameplay) but is better than completely broken rewind. + /// + public static void ApplyGameWideClock(this Drawable drawable, GameHost host) + { + drawable.Clock = host.UpdateThread.Clock; + drawable.ProcessCustomClock = false; + } } } From c0016fa5d2a837bd02cd29d83a44061f20633b75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:07:34 +0900 Subject: [PATCH 1096/1400] Fix gameplay playfield border being affected by beatmap track time Closes https://github.com/ppy/osu/issues/23470. --- osu.Game/Rulesets/UI/PlayfieldBorder.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/osu.Game/Rulesets/UI/PlayfieldBorder.cs b/osu.Game/Rulesets/UI/PlayfieldBorder.cs index 211a87de84..18bd5b9b93 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorder.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorder.cs @@ -4,10 +4,13 @@ #nullable disable using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; +using osu.Game.Extensions; using osuTK; using osuTK.Graphics; @@ -74,6 +77,12 @@ namespace osu.Game.Rulesets.UI }; } + [BackgroundDependencyLoader] + private void load(GameHost host) + { + this.ApplyGameWideClock(host); + } + protected override void LoadComplete() { base.LoadComplete(); From b096e03a57d57faf775bf2c846d34f0f9358be77 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:31:57 +0900 Subject: [PATCH 1097/1400] Fix ticks being created after the end of drum rolls in osu!taiko editor Closes https://github.com/ppy/osu/issues/23135. --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 2f4a98bd8f..987eb6625a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -1,11 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using System.Threading; using osu.Framework.Bindables; +using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; @@ -86,7 +85,10 @@ namespace osu.Game.Rulesets.Taiko.Objects bool first = true; - for (double t = StartTime; t < EndTime + tickSpacing / 2; t += tickSpacing) + // TODO: this implementation of drum roll tick does not match stable. + // Stable uses next-object intrinsics to decide whether the end of a drum roll gets a tick. + // It also changes the rate of ticks based on BPM. This is quite important. + for (double t = StartTime; Precision.AlmostBigger(EndTime, t, 1); t += tickSpacing) { cancellationToken.ThrowIfCancellationRequested(); From 7a1766e378ef251e9b30d303843e11c461509568 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:42:20 +0900 Subject: [PATCH 1098/1400] Update argon osu!mania column colours in line with latest proposal Matches https://github.com/ppy/osu/discussions/21996#discussioncomment-5516872. --- .../Argon/ManiaArgonSkinTransformer.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 007d02400a..3a15cb359f 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -139,11 +139,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case 3: switch (columnIndex) { - case 0: return colour_pink; + case 0: return colour_green; - case 1: return colour_orange; + case 1: return colour_purple; - case 2: return colour_yellow; + case 2: return colour_cyan; default: throw new ArgumentOutOfRangeException(); } @@ -185,11 +185,11 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case 1: return colour_orange; - case 2: return colour_yellow; + case 2: return colour_green; case 3: return colour_cyan; - case 4: return colour_purple; + case 4: return colour_orange; case 5: return colour_pink; @@ -201,17 +201,17 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { case 0: return colour_pink; - case 1: return colour_cyan; + case 1: return colour_orange; case 2: return colour_pink; case 3: return colour_special_column; - case 4: return colour_green; + case 4: return colour_pink; - case 5: return colour_cyan; + case 5: return colour_orange; - case 6: return colour_green; + case 6: return colour_pink; default: throw new ArgumentOutOfRangeException(); } @@ -225,9 +225,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case 2: return colour_orange; - case 3: return colour_yellow; + case 3: return colour_green; - case 4: return colour_yellow; + case 4: return colour_cyan; case 5: return colour_orange; @@ -273,9 +273,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon case 3: return colour_yellow; - case 4: return colour_cyan; + case 4: return colour_green; - case 5: return colour_green; + case 5: return colour_cyan; case 6: return colour_yellow; From 3db080fad2d8bd27f335a1a062d78e4956fd3401 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:54:33 +0900 Subject: [PATCH 1099/1400] Fix osu!taiko drum rolls not getting correct tick rate after placement in the editor --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 1 - osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index e298e313df..5226cb0794 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -133,7 +133,6 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, Duration = taikoDuration, - TickRate = beatmap.Difficulty.SliderTickRate == 3 ? 3 : 4, SliderVelocity = obj is IHasSliderVelocity velocityData ? velocityData.SliderVelocity : 1 }; } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 987eb6625a..5b77ad7f91 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -4,7 +4,6 @@ using osu.Game.Rulesets.Objects.Types; using System.Threading; using osu.Framework.Bindables; -using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; @@ -68,6 +67,8 @@ namespace osu.Game.Rulesets.Taiko.Objects double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity; Velocity = scoringDistance / timingPoint.BeatLength; + TickRate = difficulty.SliderTickRate == 3 ? 3 : 4; + tickSpacing = timingPoint.BeatLength / TickRate; } @@ -85,10 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects bool first = true; - // TODO: this implementation of drum roll tick does not match stable. - // Stable uses next-object intrinsics to decide whether the end of a drum roll gets a tick. - // It also changes the rate of ticks based on BPM. This is quite important. - for (double t = StartTime; Precision.AlmostBigger(EndTime, t, 1); t += tickSpacing) + for (double t = StartTime; t < EndTime + tickSpacing; t += tickSpacing) { cancellationToken.ThrowIfCancellationRequested(); From 56758afeed0ff662f107be0584b53261c81a8a52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 16:59:28 +0900 Subject: [PATCH 1100/1400] Add note about `lastTickHittable` requirement --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 5226cb0794..1c2e7abafe 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -92,6 +92,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps }).ToList(); } + // TODO: stable makes the last tick of a drumroll non-required when the next object is too close. + // This probably needs to be reimplemented: + // + // List hitobjects = hitObjectManager.hitObjects; + // int ind = hitobjects.IndexOf(this); + // if (i < hitobjects.Count - 1 && hitobjects[i + 1].HittableStartTime - (EndTime + (int)TickSpacing) <= (int)TickSpacing) + // lastTickHittable = false; + return converted; } From c1f23ef2119b613fc018a461f73a73c06f2c72ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 17:52:29 +0900 Subject: [PATCH 1101/1400] Add beat snap grid for osu!catch editor As discussed in https://github.com/ppy/osu/discussions/23462. --- .../Edit/CatchBeatSnapGrid.cs | 180 ++++++++++++++++++ .../Edit/CatchHitObjectComposer.cs | 27 +++ osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 7 + 3 files changed, 214 insertions(+) create mode 100644 osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs new file mode 100644 index 0000000000..a2421c2b29 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs @@ -0,0 +1,180 @@ +// 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; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Caching; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Edit +{ + /// + /// A grid which displays coloured beat divisor lines in proximity to the selection or placement cursor. + /// + /// + /// This class heavily borrows from osu!mania's implementation (ManiaBeatSnapGrid). + /// If further changes are to be made, they should also be applied there. + /// If the scale of the changes are large enough, abstracting may be a good path. + /// + public partial class CatchBeatSnapGrid : Component + { + private const double visible_range = 750; + + /// + /// The range of time values of the current selection. + /// + public (double start, double end)? SelectionTimeRange + { + set + { + if (value == selectionTimeRange) + return; + + selectionTimeRange = value; + lineCache.Invalidate(); + } + } + + [Resolved] + private EditorBeatmap beatmap { get; set; } = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } = null!; + + private readonly Cached lineCache = new Cached(); + + private (double start, double end)? selectionTimeRange; + + private ScrollingHitObjectContainer lineContainer = null!; + + [BackgroundDependencyLoader] + private void load(HitObjectComposer composer) + { + lineContainer = new ScrollingHitObjectContainer(); + + ((CatchPlayfield)composer.Playfield).UnderlayElements.Add(lineContainer); + + beatDivisor.BindValueChanged(_ => createLines(), true); + } + + protected override void Update() + { + base.Update(); + + if (!lineCache.IsValid) + { + lineCache.Validate(); + createLines(); + } + } + + private readonly Stack availableLines = new Stack(); + + private void createLines() + { + foreach (var line in lineContainer.Objects.OfType()) + availableLines.Push(line); + + lineContainer.Clear(); + + if (selectionTimeRange == null) + return; + + var range = selectionTimeRange.Value; + + var timingPoint = beatmap.ControlPointInfo.TimingPointAt(range.start - visible_range); + + double time = timingPoint.Time; + int beat = 0; + + // progress time until in the visible range. + while (time < range.start - visible_range) + { + time += timingPoint.BeatLength / beatDivisor.Value; + beat++; + } + + while (time < range.end + visible_range) + { + var nextTimingPoint = beatmap.ControlPointInfo.TimingPointAt(time); + + // switch to the next timing point if we have reached it. + if (nextTimingPoint.Time > timingPoint.Time) + { + beat = 0; + time = nextTimingPoint.Time; + timingPoint = nextTimingPoint; + } + + Color4 colour = BindableBeatDivisor.GetColourFor( + BindableBeatDivisor.GetDivisorForBeatIndex(Math.Max(1, beat), beatDivisor.Value), colours); + + if (!availableLines.TryPop(out var line)) + line = new DrawableGridLine(); + + line.HitObject.StartTime = time; + line.Colour = colour; + + lineContainer.Add(line); + + beat++; + time += timingPoint.BeatLength / beatDivisor.Value; + } + + // required to update ScrollingHitObjectContainer's cache. + lineContainer.UpdateSubTree(); + + foreach (var line in lineContainer.Objects.OfType()) + { + time = line.HitObject.StartTime; + + if (time >= range.start && time <= range.end) + line.Alpha = 1; + else + { + double timeSeparation = time < range.start ? range.start - time : time - range.end; + line.Alpha = (float)Math.Max(0, 1 - timeSeparation / visible_range); + } + } + } + + private partial class DrawableGridLine : DrawableHitObject + { + public DrawableGridLine() + : base(new HitObject()) + { + RelativeSizeAxes = Axes.X; + Height = 2; + + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); + } + + [BackgroundDependencyLoader] + private void load() + { + Origin = Anchor.BottomLeft; + Anchor = Anchor.BottomLeft; + } + + protected override void UpdateInitialTransforms() + { + // don't perform any fading – we are handling that ourselves. + LifetimeEnd = HitObject.StartTime + visible_range; + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs index 8afeca3e51..f2877572e8 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchHitObjectComposer.cs @@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Catch.Edit private InputManager inputManager = null!; + private CatchBeatSnapGrid beatSnapGrid = null!; + private readonly BindableDouble timeRangeMultiplier = new BindableDouble(1) { MinValue = 1, @@ -65,6 +67,8 @@ namespace osu.Game.Rulesets.Catch.Edit Catcher.BASE_DASH_SPEED, -Catcher.BASE_DASH_SPEED, Catcher.BASE_WALK_SPEED, -Catcher.BASE_WALK_SPEED, })); + + AddInternal(beatSnapGrid = new CatchBeatSnapGrid()); } protected override void LoadComplete() @@ -74,6 +78,29 @@ namespace osu.Game.Rulesets.Catch.Edit inputManager = GetContainingInputManager(); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (BlueprintContainer.CurrentTool is SelectTool) + { + if (EditorBeatmap.SelectedHitObjects.Any()) + { + beatSnapGrid.SelectionTimeRange = (EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); + } + else + beatSnapGrid.SelectionTimeRange = null; + } + else + { + var result = FindSnappedPositionAndTime(inputManager.CurrentState.Mouse.Position); + if (result.Time is double time) + beatSnapGrid.SelectionTimeRange = (time, time); + else + beatSnapGrid.SelectionTimeRange = null; + } + } + protected override double ReadCurrentDistanceSnap(HitObject before, HitObject after) { // osu!catch's distance snap implementation is limited, in that a custom spacing cannot be specified. diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index cf7337fd0d..f091dee845 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; @@ -41,6 +42,8 @@ namespace osu.Game.Rulesets.Catch.UI internal CatcherArea CatcherArea { get; private set; } = null!; + public Container UnderlayElements { get; private set; } = null!; + private readonly IBeatmapDifficultyInfo difficulty; public CatchPlayfield(IBeatmapDifficultyInfo difficulty) @@ -62,6 +65,10 @@ namespace osu.Game.Rulesets.Catch.UI AddRangeInternal(new[] { + UnderlayElements = new Container + { + RelativeSizeAxes = Axes.Both, + }, droppedObjectContainer, Catcher.CreateProxiedContent(), HitObjectContainer.CreateProxy(), From 6b18f2f2bb7492c0cf0208452e220dcd74d4b866 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 21:40:09 +0900 Subject: [PATCH 1102/1400] Fix osu!mania scroll speed milliseconds having too much precision Closes #23750. --- .../Configuration/ManiaRulesetConfigManager.cs | 2 +- osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs | 2 +- osu.Game/Localisation/RulesetSettingsStrings.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index b2155968ea..f975c7f1d4 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Configuration speed => new SettingDescription( rawValue: speed, name: RulesetSettingsStrings.ScrollSpeed, - value: RulesetSettingsStrings.ScrollSpeedTooltip(DrawableManiaRuleset.ComputeScrollTime(speed), speed) + value: RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(speed), speed) ) ) }; diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index a5434a36ab..065534eec4 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania private partial class ManiaScrollSlider : RoundedSliderBar { - public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value); + public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value); } } } diff --git a/osu.Game/Localisation/RulesetSettingsStrings.cs b/osu.Game/Localisation/RulesetSettingsStrings.cs index 91bbece004..3fa7656cbb 100644 --- a/osu.Game/Localisation/RulesetSettingsStrings.cs +++ b/osu.Game/Localisation/RulesetSettingsStrings.cs @@ -82,7 +82,7 @@ namespace osu.Game.Localisation /// /// "{0}ms (speed {1})" /// - public static LocalisableString ScrollSpeedTooltip(double scrollTime, int scrollSpeed) => new TranslatableString(getKey(@"ruleset"), @"{0:0}ms (speed {1})", scrollTime, scrollSpeed); + public static LocalisableString ScrollSpeedTooltip(int scrollTime, int scrollSpeed) => new TranslatableString(getKey(@"ruleset"), @"{0}ms (speed {1})", scrollTime, scrollSpeed); private static string getKey(string key) => $@"{prefix}:{key}"; } From ba7069df34b65ee70ecf9962d240c3deb05dc68a Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 6 Jun 2023 16:12:31 +0300 Subject: [PATCH 1103/1400] =?UTF-8?q?Fix=20`SelectAllModsButton`=20state?= =?UTF-8?q?=20doesn=E2=80=99t=20update=20when=20search=20term=20changed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TestSceneFreeModSelectOverlay.cs | 24 +++++++++++++++++++ osu.Game/Overlays/Mods/SelectAllModsButton.cs | 3 +++ 2 files changed, 27 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs index 60bd88cc2b..66ba908879 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneFreeModSelectOverlay.cs @@ -8,6 +8,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Testing; @@ -57,6 +58,29 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("customisation area not expanded", () => this.ChildrenOfType().Single().Height == 0); } + [Test] + public void TestSelectAllButtonUpdatesStateWhenSearchTermChanged() + { + createFreeModSelect(); + + AddStep("apply search term", () => freeModSelectOverlay.SearchTerm = "ea"); + + AddAssert("select all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + + AddStep("click select all button", navigateAndClick); + AddAssert("select all button disabled", () => !this.ChildrenOfType().Single().Enabled.Value); + + AddStep("change search term", () => freeModSelectOverlay.SearchTerm = "e"); + + AddAssert("select all button enabled", () => this.ChildrenOfType().Single().Enabled.Value); + + void navigateAndClick() where T : Drawable + { + InputManager.MoveMouseTo(this.ChildrenOfType().Single()); + InputManager.Click(MouseButton.Left); + } + } + [Test] public void TestSelectDeselectAllViaKeyboard() { diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index 83c46cfc1f..dd14514a3b 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.cs @@ -17,6 +17,7 @@ namespace osu.Game.Overlays.Mods { private readonly Bindable> selectedMods = new Bindable>(); private readonly Bindable>> availableMods = new Bindable>>(); + private readonly Bindable searchTerm = new Bindable(); public SelectAllModsButton(FreeModSelectOverlay modSelectOverlay) : base(ModSelectOverlay.BUTTON_WIDTH) @@ -26,6 +27,7 @@ namespace osu.Game.Overlays.Mods selectedMods.BindTo(modSelectOverlay.SelectedMods); availableMods.BindTo(modSelectOverlay.AvailableMods); + searchTerm.BindTo(modSelectOverlay.SearchTextBox.Current); } protected override void LoadComplete() @@ -34,6 +36,7 @@ namespace osu.Game.Overlays.Mods selectedMods.BindValueChanged(_ => Scheduler.AddOnce(updateEnabledState)); availableMods.BindValueChanged(_ => Scheduler.AddOnce(updateEnabledState)); + searchTerm.BindValueChanged(_ => Scheduler.AddOnce(updateEnabledState)); updateEnabledState(); } From e0e013cca10ef665af0647c1d914955dfb45d42e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 22:17:05 +0900 Subject: [PATCH 1104/1400] Fix incorrect realm schema comment Co-authored-by: timiimit <32331609+timiimit@users.noreply.github.com> --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 9e5f41502b..f4c6c802f1 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -71,7 +71,7 @@ namespace osu.Game.Database /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. - /// 27 2023-06-06 Added EditorTimestamp to ScoreInfo. + /// 27 2023-06-06 Added EditorTimestamp to BeatmapInfo. /// private const int schema_version = 27; From 247fa088dbc947770df1e131aae3e8e6104d3b3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 6 Jun 2023 22:22:42 +0900 Subject: [PATCH 1105/1400] Add `IHasNoTimedInputs` interface to scope change further --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 2 +- osu.Game/Rulesets/Mods/IHasNoTimedInputs.cs | 15 +++++++++++++++ .../Play/PlayerSettings/BeatmapOffsetControl.cs | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IHasNoTimedInputs.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 32ffb545e0..aaa7c70a8d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -18,7 +18,7 @@ using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IUpdatableByPlayfield, IApplicableToDrawableRuleset, IApplicableToPlayer + public class OsuModRelax : ModRelax, IUpdatableByPlayfield, IApplicableToDrawableRuleset, IApplicableToPlayer, IHasNoTimedInputs { public override LocalisableString Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; diff --git a/osu.Game/Rulesets/Mods/IHasNoTimedInputs.cs b/osu.Game/Rulesets/Mods/IHasNoTimedInputs.cs new file mode 100644 index 0000000000..c0d709ad4a --- /dev/null +++ b/osu.Game/Rulesets/Mods/IHasNoTimedInputs.cs @@ -0,0 +1,15 @@ +// 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.Rulesets.Mods +{ + /// + /// Denotes a mod which removes timed inputs from a ruleset which would usually have them. + /// + /// + /// This will be used, for instance, to omit showing offset calibration UI post-gameplay. + /// + public interface IHasNoTimedInputs + { + } +} diff --git a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs index 8d5459809e..b542707185 100644 --- a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs +++ b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Play.PlayerSettings if (score.NewValue == null) return; - if (score.NewValue.Mods.Any(m => !m.UserPlayable || m is ModRelax)) + if (score.NewValue.Mods.Any(m => !m.UserPlayable || m is IHasNoTimedInputs)) return; var hitEvents = score.NewValue.HitEvents; From be59eb11169324ec3df62629d4d5b0cabf75c775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Jun 2023 18:01:15 +0200 Subject: [PATCH 1106/1400] Fix triangles song progress bar blinking during gameplay Closes #23760. --- osu.Game/Screens/Play/HUD/DefaultSongProgress.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs index 6eed563703..202ead2d66 100644 --- a/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/DefaultSongProgress.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Utils; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Localisation.HUD; @@ -101,7 +102,12 @@ namespace osu.Game.Screens.Play.HUD protected override void Update() { base.Update(); - Height = bottom_bar_height + graph_height + handle_size.Y + info.Height - graph.Y; + + // to prevent unnecessary invalidations of the song progress graph due to changes in size, apply tolerance when updating the height. + float newHeight = bottom_bar_height + graph_height + handle_size.Y + info.Height - graph.Y; + + if (!Precision.AlmostEquals(Height, newHeight, 5f)) + Height = newHeight; } private void updateBarVisibility() From 46ec250d342721c70e54a20795f6994a31c8a12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Jun 2023 20:21:55 +0200 Subject: [PATCH 1107/1400] Fix test failures due to cross-test state pollution `TestSceneEditorTestGameplay` is not isolated from database, and one of the tests exiting editor when seeked to 60000 milliseconds (`TestClockTimeTransferIsOneDirectional()`) ended up changing `EditorTimestamp` to the same value, causing `TestSaveChangesBeforeGameplayTest()` to fail due to changing initial state. To fix, perform a direct deletion of imported beatmaps in realm to avert this scenario, contrary to the soft-deletion via `BeatmapManager` done previously. --- .../Visual/Editing/TestSceneEditorTestGameplay.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs index 2250868a39..007716bd6c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs @@ -209,10 +209,14 @@ namespace osu.Game.Tests.Visual.Editing public override void TearDownSteps() { base.TearDownSteps(); - AddStep("delete imported", () => + AddStep("delete imported", () => Realm.Write(r => { - beatmaps.Delete(importedBeatmapSet); - }); + // delete from realm directly rather than via `BeatmapManager` to avoid cross-test pollution + // (`BeatmapManager.Delete()` uses soft deletion, which can lead to beatmap reuse between test cases). + r.RemoveAll(); + r.RemoveAll(); + r.RemoveAll(); + })); } } } From 7694aa721978e88a39c8517fb3cfde27d881ca45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Jun 2023 20:36:44 +0200 Subject: [PATCH 1108/1400] Add test coverage --- .../Gameplay/TestSceneBeatmapOffsetControl.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs index 6eae795630..4b2909739d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Play.PlayerSettings; using osu.Game.Tests.Visual.Ranking; @@ -49,6 +50,21 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("No calibration button", () => !offsetControl.ChildrenOfType().Any()); } + [Test] + public void TestModRemovingTimedInputs() + { + AddStep("Set score with mod removing timed inputs", () => + { + offsetControl.ReferenceScore.Value = new ScoreInfo + { + HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(10), + Mods = new[] { new OsuModRelax() } + }; + }); + + AddAssert("No calibration button", () => !offsetControl.ChildrenOfType().Any()); + } + [Test] public void TestCalibrationFromZero() { From f51b8a6a058c53e2be50aaf7255680b7a9dbed15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 6 Jun 2023 21:11:24 +0200 Subject: [PATCH 1109/1400] Fix code quality inspection --- .../Visual/Gameplay/TestSceneBeatmapOffsetControl.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs index 4b2909739d..f3701b664c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneBeatmapOffsetControl.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Testing; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; using osu.Game.Screens.Play.PlayerSettings; @@ -58,7 +59,7 @@ namespace osu.Game.Tests.Visual.Gameplay offsetControl.ReferenceScore.Value = new ScoreInfo { HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(10), - Mods = new[] { new OsuModRelax() } + Mods = new Mod[] { new OsuModRelax() } }; }); From cdd931633defa30d99d0fb46bb34c5634b34cc38 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 12:10:30 +0900 Subject: [PATCH 1110/1400] Change 3K middle key to "special" purple colour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Skinning/Argon/ManiaArgonSkinTransformer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs index 3a15cb359f..ddd6365c25 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Argon/ManiaArgonSkinTransformer.cs @@ -141,7 +141,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon { case 0: return colour_green; - case 1: return colour_purple; + case 1: return colour_special_column; case 2: return colour_cyan; From 6d446d3e97dd6f936753e8fb0427929ccab541a7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 12:25:34 +0900 Subject: [PATCH 1111/1400] Fix incorrect colouring of beat snap grids (mania and catch) --- osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs b/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs index a2421c2b29..6862696b3a 100644 --- a/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Catch/Edit/CatchBeatSnapGrid.cs @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Edit } Color4 colour = BindableBeatDivisor.GetColourFor( - BindableBeatDivisor.GetDivisorForBeatIndex(Math.Max(1, beat), beatDivisor.Value), colours); + BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value), colours); if (!availableLines.TryPop(out var line)) line = new DrawableGridLine(); diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index d1d5492b7a..2d4b5f718c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -129,7 +129,7 @@ namespace osu.Game.Rulesets.Mania.Edit } Color4 colour = BindableBeatDivisor.GetColourFor( - BindableBeatDivisor.GetDivisorForBeatIndex(Math.Max(1, beat), beatDivisor.Value), colours); + BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value), colours); foreach (var grid in grids) { From c276b728ecee7dc7ef471464445c69e4a729d570 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 13:30:04 +0900 Subject: [PATCH 1112/1400] Clean up `TestSceneDrumRollJudgements` --- .../Judgements/TestSceneDrumRollJudgements.cs | 67 ++++--------------- 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs index a9231b4783..bccede38b3 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs @@ -15,8 +15,6 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitAllDrumRoll() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), @@ -24,11 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(1001), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000 - })); + }, CreateBeatmap(createDrumRoll(false))); AssertJudgementCount(3); AssertResult(0, HitResult.SmallBonus); @@ -39,18 +33,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitSomeDrumRoll() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000 - })); + }, CreateBeatmap(createDrumRoll(false))); AssertJudgementCount(3); AssertResult(0, HitResult.IgnoreMiss); @@ -61,16 +49,10 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitNoneDrumRoll() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000 - })); + }, CreateBeatmap(createDrumRoll(false))); AssertJudgementCount(3); AssertResult(0, HitResult.IgnoreMiss); @@ -81,8 +63,6 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitAllStrongDrumRollWithOneKey() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), @@ -90,12 +70,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(1001), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000, - IsStrong = true - })); + }, CreateBeatmap(createDrumRoll(true))); AssertJudgementCount(6); @@ -112,19 +87,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitSomeStrongDrumRollWithOneKey() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000, - IsStrong = true - })); + }, CreateBeatmap(createDrumRoll(true))); AssertJudgementCount(6); @@ -141,8 +109,6 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitAllStrongDrumRollWithBothKeys() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), @@ -150,12 +116,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(1001), new TaikoReplayFrame(2000, TaikoAction.LeftCentre, TaikoAction.RightCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000, - IsStrong = true - })); + }, CreateBeatmap(createDrumRoll(true))); AssertJudgementCount(6); @@ -172,19 +133,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements [Test] public void TestHitSomeStrongDrumRollWithBothKeys() { - const double hit_time = 1000; - PerformTest(new List { new TaikoReplayFrame(0), new TaikoReplayFrame(2000, TaikoAction.LeftCentre, TaikoAction.RightCentre), new TaikoReplayFrame(2001), - }, CreateBeatmap(new DrumRoll - { - StartTime = hit_time, - Duration = 1000, - IsStrong = true - })); + }, CreateBeatmap(createDrumRoll(true))); AssertJudgementCount(6); @@ -197,5 +151,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements AssertResult(0, HitResult.IgnoreHit); AssertResult(2, HitResult.IgnoreHit); } + + private DrumRoll createDrumRoll(bool strong) => new DrumRoll + { + StartTime = 1000, + Duration = 1000, + IsStrong = strong + }; } } From 2fca81492663c57039bad6dab6635a37be0c87b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 13:44:01 +0900 Subject: [PATCH 1113/1400] Update drum roll judgement tests to work correctly with more correct tick rate applied --- .../Judgements/TestSceneDrumRollJudgements.cs | 79 +++++++++++++------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs index bccede38b3..21f2b8f1be 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Judgements/TestSceneDrumRollJudgements.cs @@ -20,13 +20,22 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(0), new TaikoReplayFrame(1000, TaikoAction.LeftCentre), new TaikoReplayFrame(1001), + new TaikoReplayFrame(1250, TaikoAction.LeftCentre), + new TaikoReplayFrame(1251), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre), + new TaikoReplayFrame(1501), + new TaikoReplayFrame(1750, TaikoAction.LeftCentre), + new TaikoReplayFrame(1751), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(false))); - AssertJudgementCount(3); + AssertJudgementCount(6); AssertResult(0, HitResult.SmallBonus); AssertResult(1, HitResult.SmallBonus); + AssertResult(2, HitResult.SmallBonus); + AssertResult(3, HitResult.SmallBonus); + AssertResult(4, HitResult.SmallBonus); AssertResult(0, HitResult.IgnoreHit); } @@ -40,9 +49,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(false))); - AssertJudgementCount(3); + AssertJudgementCount(6); AssertResult(0, HitResult.IgnoreMiss); - AssertResult(1, HitResult.SmallBonus); + AssertResult(1, HitResult.IgnoreMiss); + AssertResult(2, HitResult.IgnoreMiss); + AssertResult(3, HitResult.IgnoreMiss); + AssertResult(4, HitResult.SmallBonus); AssertResult(0, HitResult.IgnoreHit); } @@ -54,9 +66,12 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(0), }, CreateBeatmap(createDrumRoll(false))); - AssertJudgementCount(3); + AssertJudgementCount(6); AssertResult(0, HitResult.IgnoreMiss); AssertResult(1, HitResult.IgnoreMiss); + AssertResult(2, HitResult.IgnoreMiss); + AssertResult(3, HitResult.IgnoreMiss); + AssertResult(4, HitResult.IgnoreMiss); AssertResult(0, HitResult.IgnoreHit); } @@ -68,20 +83,26 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(0), new TaikoReplayFrame(1000, TaikoAction.LeftCentre), new TaikoReplayFrame(1001), + new TaikoReplayFrame(1250, TaikoAction.LeftCentre), + new TaikoReplayFrame(1251), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre), + new TaikoReplayFrame(1501), + new TaikoReplayFrame(1750, TaikoAction.LeftCentre), + new TaikoReplayFrame(1751), new TaikoReplayFrame(2000, TaikoAction.LeftCentre), new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(true))); - AssertJudgementCount(6); + AssertJudgementCount(12); - AssertResult(0, HitResult.SmallBonus); - AssertResult(0, HitResult.LargeBonus); - - AssertResult(1, HitResult.SmallBonus); - AssertResult(1, HitResult.LargeBonus); + for (int i = 0; i < 5; i++) + { + AssertResult(i, HitResult.SmallBonus); + AssertResult(i, HitResult.LargeBonus); + } AssertResult(0, HitResult.IgnoreHit); - AssertResult(2, HitResult.IgnoreHit); + AssertResult(5, HitResult.IgnoreHit); } [Test] @@ -94,16 +115,16 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(true))); - AssertJudgementCount(6); + AssertJudgementCount(12); AssertResult(0, HitResult.IgnoreMiss); AssertResult(0, HitResult.IgnoreMiss); - AssertResult(1, HitResult.SmallBonus); - AssertResult(1, HitResult.LargeBonus); + AssertResult(4, HitResult.SmallBonus); + AssertResult(4, HitResult.LargeBonus); AssertResult(0, HitResult.IgnoreHit); - AssertResult(2, HitResult.IgnoreHit); + AssertResult(5, HitResult.IgnoreHit); } [Test] @@ -114,20 +135,26 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(0), new TaikoReplayFrame(1000, TaikoAction.LeftCentre, TaikoAction.RightCentre), new TaikoReplayFrame(1001), + new TaikoReplayFrame(1250, TaikoAction.LeftCentre, TaikoAction.RightCentre), + new TaikoReplayFrame(1251), + new TaikoReplayFrame(1500, TaikoAction.LeftCentre, TaikoAction.RightCentre), + new TaikoReplayFrame(1501), + new TaikoReplayFrame(1750, TaikoAction.LeftCentre, TaikoAction.RightCentre), + new TaikoReplayFrame(1751), new TaikoReplayFrame(2000, TaikoAction.LeftCentre, TaikoAction.RightCentre), new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(true))); - AssertJudgementCount(6); + AssertJudgementCount(12); - AssertResult(0, HitResult.SmallBonus); - AssertResult(0, HitResult.LargeBonus); - - AssertResult(1, HitResult.SmallBonus); - AssertResult(1, HitResult.LargeBonus); + for (int i = 0; i < 5; i++) + { + AssertResult(i, HitResult.SmallBonus); + AssertResult(i, HitResult.LargeBonus); + } AssertResult(0, HitResult.IgnoreHit); - AssertResult(2, HitResult.IgnoreHit); + AssertResult(5, HitResult.IgnoreHit); } [Test] @@ -140,16 +167,16 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements new TaikoReplayFrame(2001), }, CreateBeatmap(createDrumRoll(true))); - AssertJudgementCount(6); + AssertJudgementCount(12); AssertResult(0, HitResult.IgnoreMiss); AssertResult(0, HitResult.IgnoreMiss); - AssertResult(1, HitResult.SmallBonus); - AssertResult(1, HitResult.LargeBonus); + AssertResult(4, HitResult.SmallBonus); + AssertResult(4, HitResult.LargeBonus); AssertResult(0, HitResult.IgnoreHit); - AssertResult(2, HitResult.IgnoreHit); + AssertResult(5, HitResult.IgnoreHit); } private DrumRoll createDrumRoll(bool strong) => new DrumRoll From 30f17d586986f6dc97a6cd110694272cdea9483b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 14:03:04 +0900 Subject: [PATCH 1114/1400] Disabling reporting users from in-game chat Addresses #23684. Safer alternative to #23698. --- osu.Game/Overlays/Chat/ChatLine.cs | 33 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 2f4c175ac4..c85206d5f7 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -56,11 +56,11 @@ namespace osu.Game.Overlays.Chat [Resolved] private OverlayColourProvider? colourProvider { get; set; } - private readonly OsuSpriteText drawableTimestamp; + private OsuSpriteText drawableTimestamp = null!; - private readonly DrawableChatUsername drawableUsername; + private DrawableChatUsername drawableUsername = null!; - private readonly LinkFlowContainer drawableContentFlow; + private LinkFlowContainer drawableContentFlow = null!; private readonly Bindable prefer24HourTime = new Bindable(); @@ -69,8 +69,16 @@ namespace osu.Game.Overlays.Chat public ChatLine(Message message) { Message = message; + RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager configManager) + { + configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); + prefer24HourTime.BindValueChanged(_ => updateTimestamp()); InternalChild = new GridContainer { @@ -103,7 +111,6 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Margin = new MarginPadding { Horizontal = Spacing }, - ReportRequested = this.ShowPopover, }, drawableContentFlow = new LinkFlowContainer(styleMessageContent) { @@ -115,13 +122,6 @@ namespace osu.Game.Overlays.Chat }; } - [BackgroundDependencyLoader] - private void load(OsuConfigManager configManager) - { - configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); - prefer24HourTime.BindValueChanged(_ => updateTimestamp()); - } - protected override void LoadComplete() { base.LoadComplete(); @@ -130,6 +130,17 @@ namespace osu.Game.Overlays.Chat updateMessageContent(); FinishTransforms(true); + + if (this.FindClosestParent() != null) + { + // This guards against cases like in-game chat where there's no available popover container. + // There may be a future where a global one becomes available, at which point this code may be unnecessary. + // + // See: + // https://github.com/ppy/osu/pull/23698 + // https://github.com/ppy/osu/pull/14554 + drawableUsername.ReportRequested = this.ShowPopover; + } } public Popover GetPopover() => new ReportChatPopover(message); From 62cb6a98cae4856c6a3ef3b75cd5065d4ad173a0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 7 Jun 2023 08:20:38 +0300 Subject: [PATCH 1115/1400] Remove redundant nullable suppression directives --- osu.Game.Rulesets.Mania/Objects/HeadNote.cs | 2 -- osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs | 2 -- osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs | 2 -- osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/HitType.cs | 2 -- osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs | 2 -- osu.Game.Tournament/IPC/TourneyState.cs | 2 -- .../Screens/Ladder/Components/ConditionalTournamentMatch.cs | 2 -- osu.Game/Beatmaps/DifficultyRating.cs | 2 -- osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs | 2 -- osu.Game/Beatmaps/Legacy/LegacyOrigins.cs | 2 -- osu.Game/Configuration/IntroSequence.cs | 2 -- osu.Game/Configuration/ReleaseStream.cs | 2 -- osu.Game/Configuration/ToolbarClockDisplayMode.cs | 2 -- osu.Game/Database/ISoftDelete.cs | 2 -- osu.Game/Graphics/UserInterface/MenuItemType.cs | 2 -- osu.Game/Graphics/UserInterface/SelectionState.cs | 2 -- osu.Game/Graphics/UserInterface/TernaryState.cs | 2 -- osu.Game/Online/API/APIRequestCompletionState.cs | 2 -- osu.Game/Online/Chat/ChannelType.cs | 2 -- osu.Game/Online/Leaderboards/LeaderboardState.cs | 2 -- osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs | 2 -- osu.Game/Online/Multiplayer/IMultiplayerServer.cs | 2 -- osu.Game/Online/Multiplayer/MultiplayerUserState.cs | 2 -- osu.Game/Online/Spectator/SpectatedUserState.cs | 2 -- osu.Game/Overlays/OverlayActivation.cs | 2 -- osu.Game/Overlays/SortDirection.cs | 2 -- osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs | 2 -- osu.Game/Rulesets/Objects/Drawables/ArmedState.cs | 2 -- osu.Game/Rulesets/Objects/IBarLine.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs | 2 -- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasColumn.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasCombo.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasDistance.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasDuration.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasHold.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasXPosition.cs | 2 -- osu.Game/Rulesets/Objects/Types/IHasYPosition.cs | 2 -- osu.Game/Rulesets/Objects/Types/PathType.cs | 2 -- osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs | 2 -- osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs | 2 -- .../Match/Playlist/MultiplayerPlaylistDisplayMode.cs | 2 -- .../Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs | 2 -- osu.Game/Screens/Ranking/PanelState.cs | 2 -- osu.Game/Screens/ScorePresentType.cs | 2 -- osu.Game/Screens/Select/Filter/Operator.cs | 2 -- 51 files changed, 102 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/HeadNote.cs b/osu.Game.Rulesets.Mania/Objects/HeadNote.cs index fb5c7b4ddd..e69cc62aed 100644 --- a/osu.Game.Rulesets.Mania/Objects/HeadNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HeadNote.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. -#nullable disable - namespace osu.Game.Rulesets.Mania.Objects { public class HeadNote : Note diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs index 92071d4a57..616bb17e05 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.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. -#nullable disable - namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public enum SliderPosition diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs index 55de5a0e8d..b1815b23c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.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. -#nullable disable - namespace osu.Game.Rulesets.Osu.Objects.Drawables { public interface IRequireTracking diff --git a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs index eddd251bda..7594f7c2e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs +++ b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.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. -#nullable disable - namespace osu.Game.Rulesets.Osu.Objects { public interface ISliderProgress diff --git a/osu.Game.Rulesets.Taiko/Objects/HitType.cs b/osu.Game.Rulesets.Taiko/Objects/HitType.cs index eae7fa683a..17b3fdbd04 100644 --- a/osu.Game.Rulesets.Taiko/Objects/HitType.cs +++ b/osu.Game.Rulesets.Taiko/Objects/HitType.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. -#nullable disable - namespace osu.Game.Rulesets.Taiko.Objects { /// diff --git a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs index c3a6b7c474..dac6beea65 100644 --- a/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs +++ b/osu.Game.Tests/Rulesets/TestSceneBrokenRulesetHandling.cs @@ -73,7 +73,5 @@ namespace osu.Game.Tests.Rulesets public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null; public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null; } - -#nullable enable } } diff --git a/osu.Game.Tournament/IPC/TourneyState.cs b/osu.Game.Tournament/IPC/TourneyState.cs index 2c7253dc10..ef1c612a53 100644 --- a/osu.Game.Tournament/IPC/TourneyState.cs +++ b/osu.Game.Tournament/IPC/TourneyState.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. -#nullable disable - namespace osu.Game.Tournament.IPC { public enum TourneyState diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs index 04155fcb89..16224a7fb4 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ConditionalTournamentMatch.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. -#nullable disable - using osu.Game.Tournament.Models; namespace osu.Game.Tournament.Screens.Ladder.Components diff --git a/osu.Game/Beatmaps/DifficultyRating.cs b/osu.Game/Beatmaps/DifficultyRating.cs index 478c0e36df..f0ee0ad705 100644 --- a/osu.Game/Beatmaps/DifficultyRating.cs +++ b/osu.Game/Beatmaps/DifficultyRating.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. -#nullable disable - namespace osu.Game.Beatmaps { public enum DifficultyRating diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs index 1f6538a890..098265506d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardSize.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. -#nullable disable - namespace osu.Game.Beatmaps.Drawables.Cards { /// diff --git a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs b/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs index 62b0edc384..31f67d6dfd 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyOrigins.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyOrigins.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. -#nullable disable - namespace osu.Game.Beatmaps.Legacy { internal enum LegacyOrigins diff --git a/osu.Game/Configuration/IntroSequence.cs b/osu.Game/Configuration/IntroSequence.cs index 8327ea2f57..5672c44bbe 100644 --- a/osu.Game/Configuration/IntroSequence.cs +++ b/osu.Game/Configuration/IntroSequence.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. -#nullable disable - namespace osu.Game.Configuration { public enum IntroSequence diff --git a/osu.Game/Configuration/ReleaseStream.cs b/osu.Game/Configuration/ReleaseStream.cs index 9cdd91bfd0..ed0bee1dd8 100644 --- a/osu.Game/Configuration/ReleaseStream.cs +++ b/osu.Game/Configuration/ReleaseStream.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. -#nullable disable - namespace osu.Game.Configuration { public enum ReleaseStream diff --git a/osu.Game/Configuration/ToolbarClockDisplayMode.cs b/osu.Game/Configuration/ToolbarClockDisplayMode.cs index 682e221ef8..2f42f7a9b5 100644 --- a/osu.Game/Configuration/ToolbarClockDisplayMode.cs +++ b/osu.Game/Configuration/ToolbarClockDisplayMode.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. -#nullable disable - namespace osu.Game.Configuration { public enum ToolbarClockDisplayMode diff --git a/osu.Game/Database/ISoftDelete.cs b/osu.Game/Database/ISoftDelete.cs index b07c8db2de..afa42c2002 100644 --- a/osu.Game/Database/ISoftDelete.cs +++ b/osu.Game/Database/ISoftDelete.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. -#nullable disable - namespace osu.Game.Database { /// diff --git a/osu.Game/Graphics/UserInterface/MenuItemType.cs b/osu.Game/Graphics/UserInterface/MenuItemType.cs index 1eb45d6b1c..0269f2cb57 100644 --- a/osu.Game/Graphics/UserInterface/MenuItemType.cs +++ b/osu.Game/Graphics/UserInterface/MenuItemType.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. -#nullable disable - namespace osu.Game.Graphics.UserInterface { public enum MenuItemType diff --git a/osu.Game/Graphics/UserInterface/SelectionState.cs b/osu.Game/Graphics/UserInterface/SelectionState.cs index edabf0547b..c85b2ad3ab 100644 --- a/osu.Game/Graphics/UserInterface/SelectionState.cs +++ b/osu.Game/Graphics/UserInterface/SelectionState.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. -#nullable disable - namespace osu.Game.Graphics.UserInterface { public enum SelectionState diff --git a/osu.Game/Graphics/UserInterface/TernaryState.cs b/osu.Game/Graphics/UserInterface/TernaryState.cs index effbe624c3..d4de28044f 100644 --- a/osu.Game/Graphics/UserInterface/TernaryState.cs +++ b/osu.Game/Graphics/UserInterface/TernaryState.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. -#nullable disable - namespace osu.Game.Graphics.UserInterface { /// diff --git a/osu.Game/Online/API/APIRequestCompletionState.cs b/osu.Game/Online/API/APIRequestCompletionState.cs index 52eb669a7d..84c9974dd8 100644 --- a/osu.Game/Online/API/APIRequestCompletionState.cs +++ b/osu.Game/Online/API/APIRequestCompletionState.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. -#nullable disable - namespace osu.Game.Online.API { public enum APIRequestCompletionState diff --git a/osu.Game/Online/Chat/ChannelType.cs b/osu.Game/Online/Chat/ChannelType.cs index a864e20830..bd628e90c4 100644 --- a/osu.Game/Online/Chat/ChannelType.cs +++ b/osu.Game/Online/Chat/ChannelType.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. -#nullable disable - namespace osu.Game.Online.Chat { public enum ChannelType diff --git a/osu.Game/Online/Leaderboards/LeaderboardState.cs b/osu.Game/Online/Leaderboards/LeaderboardState.cs index abc0ef4f19..6b07500a98 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardState.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardState.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. -#nullable disable - namespace osu.Game.Online.Leaderboards { public enum LeaderboardState diff --git a/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs b/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs index bbfc5a02c6..c497601e37 100644 --- a/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.cs +++ b/osu.Game/Online/Multiplayer/ForceGameplayStartCountdown.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. -#nullable disable - using MessagePack; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/IMultiplayerServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerServer.cs index cc7a474ce7..d3a070af6d 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerServer.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. -#nullable disable - namespace osu.Game.Online.Multiplayer { /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerUserState.cs b/osu.Game/Online/Multiplayer/MultiplayerUserState.cs index 0f7dc6b8cd..d1369a7970 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerUserState.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerUserState.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. -#nullable disable - namespace osu.Game.Online.Multiplayer { public enum MultiplayerUserState diff --git a/osu.Game/Online/Spectator/SpectatedUserState.cs b/osu.Game/Online/Spectator/SpectatedUserState.cs index edf0859a33..0f0a3068b8 100644 --- a/osu.Game/Online/Spectator/SpectatedUserState.cs +++ b/osu.Game/Online/Spectator/SpectatedUserState.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. -#nullable disable - namespace osu.Game.Online.Spectator { public enum SpectatedUserState diff --git a/osu.Game/Overlays/OverlayActivation.cs b/osu.Game/Overlays/OverlayActivation.cs index 354153734e..68d7ee8ea9 100644 --- a/osu.Game/Overlays/OverlayActivation.cs +++ b/osu.Game/Overlays/OverlayActivation.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. -#nullable disable - namespace osu.Game.Overlays { public enum OverlayActivation diff --git a/osu.Game/Overlays/SortDirection.cs b/osu.Game/Overlays/SortDirection.cs index 98ac31103f..3af9614972 100644 --- a/osu.Game/Overlays/SortDirection.cs +++ b/osu.Game/Overlays/SortDirection.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. -#nullable disable - namespace osu.Game.Overlays { public enum SortDirection diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs index af315bfb28..5a3ad5e786 100644 --- a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.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. -#nullable disable - using System; using osu.Framework.Configuration.Tracking; diff --git a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs index 4faf0920d1..b2d9f50602 100644 --- a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs +++ b/osu.Game/Rulesets/Objects/Drawables/ArmedState.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Drawables { public enum ArmedState diff --git a/osu.Game/Rulesets/Objects/IBarLine.cs b/osu.Game/Rulesets/Objects/IBarLine.cs index 8cdead6776..14df80e3b9 100644 --- a/osu.Game/Rulesets/Objects/IBarLine.cs +++ b/osu.Game/Rulesets/Objects/IBarLine.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. -#nullable disable - namespace osu.Game.Rulesets.Objects { /// diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index d9738ecd0a..8eda2a8f61 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -586,7 +586,5 @@ namespace osu.Game.Rulesets.Objects.Legacy public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Filename); } - -#nullable disable } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 639cacb128..0b69817c13 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 330ebf72c7..84cde5fa95 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 980d37ccd5..cb5178ce48 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index a391c8cb43..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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs b/osu.Game/Rulesets/Objects/Types/IHasColumn.cs index 3978a7e765..dc07cfbb6a 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasColumn.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs index d02b97a3e4..d1a4683a1d 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs index 549abc046a..b497ca5da3 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDistance.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasDuration.cs b/osu.Game/Rulesets/Objects/Types/IHasDuration.cs index 06ed8eba76..ca734da5ad 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDuration.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDuration.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasHold.cs b/osu.Game/Rulesets/Objects/Types/IHasHold.cs index 91b05dc3fd..469b8b7892 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasHold.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasHold.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs b/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs index dfc526383a..caf22c3023 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs index f688c783e1..7e55b21050 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs index 3c0cc595fb..d2561b10a7 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/PathType.cs b/osu.Game/Rulesets/Objects/Types/PathType.cs index 266a3de6ec..923ce9eba4 100644 --- a/osu.Game/Rulesets/Objects/Types/PathType.cs +++ b/osu.Game/Rulesets/Objects/Types/PathType.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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { public enum PathType diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index 58bb80accd..81e1a6c916 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.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. -#nullable disable - namespace osu.Game.Rulesets.UI.Scrolling { public enum ScrollingDirection diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs index ebdb030e76..4a25144881 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorType.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. -#nullable disable - namespace osu.Game.Screens.Edit.Compose.Components { public enum BeatDivisorType diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs index 1672f98637..cc3dca6a34 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistDisplayMode.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. -#nullable disable - namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist { /// diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs index 92dbde9f08..8982d1669d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MasterClockState.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. -#nullable disable - namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate { public enum MasterClockState diff --git a/osu.Game/Screens/Ranking/PanelState.cs b/osu.Game/Screens/Ranking/PanelState.cs index 3af74fe0f3..94e2c7cef4 100644 --- a/osu.Game/Screens/Ranking/PanelState.cs +++ b/osu.Game/Screens/Ranking/PanelState.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. -#nullable disable - namespace osu.Game.Screens.Ranking { public enum PanelState diff --git a/osu.Game/Screens/ScorePresentType.cs b/osu.Game/Screens/ScorePresentType.cs index 24105467f1..3216f92091 100644 --- a/osu.Game/Screens/ScorePresentType.cs +++ b/osu.Game/Screens/ScorePresentType.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. -#nullable disable - namespace osu.Game.Screens { public enum ScorePresentType diff --git a/osu.Game/Screens/Select/Filter/Operator.cs b/osu.Game/Screens/Select/Filter/Operator.cs index a6a53f0c3e..706daf631f 100644 --- a/osu.Game/Screens/Select/Filter/Operator.cs +++ b/osu.Game/Screens/Select/Filter/Operator.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. -#nullable disable - namespace osu.Game.Screens.Select.Filter { /// From d57c2ab7e48de5cd5cb9486dee2a95b582467a20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 14:23:23 +0900 Subject: [PATCH 1116/1400] Fix osu!mania barlines showing in front of notes Closes #23412. --- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 2 -- osu.Game.Rulesets.Mania/UI/Column.cs | 22 +++++++++++++--------- osu.Game.Rulesets.Mania/UI/Stage.cs | 14 ++++++++++++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 3f04a4fafe..09a746042b 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 7033fd6755..659b63b640 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -40,7 +40,11 @@ namespace osu.Game.Rulesets.Mania.UI public readonly Bindable Action = new Bindable(); public readonly ColumnHitObjectArea HitObjectArea; + + internal readonly Container BackgroundContainer = new Container { RelativeSizeAxes = Axes.Both }; + internal readonly Container TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both }; + private DrawablePool hitExplosionPool; private readonly OrderedHitPolicy hitPolicy; public Container UnderlayElements => HitObjectArea.UnderlayElements; @@ -77,30 +81,30 @@ namespace osu.Game.Rulesets.Mania.UI skin.SourceChanged += onSourceChanged; onSourceChanged(); - Drawable background = new SkinnableDrawable(new ManiaSkinComponentLookup(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground()) - { - RelativeSizeAxes = Axes.Both, - }; - - InternalChildren = new[] + InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(5), sampleTriggerSource = new GameplaySampleTriggerSource(HitObjectContainer), - // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements - background.CreateProxy(), HitObjectArea, keyArea = new SkinnableDrawable(new ManiaSkinComponentLookup(ManiaSkinComponents.KeyArea), _ => new DefaultKeyArea()) { RelativeSizeAxes = Axes.Both, }, - background, + // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements externally. + BackgroundContainer, TopLevelContainer, new ColumnTouchInputArea(this) }; + var background = new SkinnableDrawable(new ManiaSkinComponentLookup(ManiaSkinComponents.ColumnBackground), _ => new DefaultColumnBackground()) + { + RelativeSizeAxes = Axes.Both, + }; + background.ApplyGameWideClock(host); keyArea.ApplyGameWideClock(host); + BackgroundContainer.Add(background); TopLevelContainer.Add(HitObjectArea.Explosions.CreateProxy()); RegisterPool(10, 50); diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index c1d3e85bf1..215d81b64a 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -60,6 +60,7 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; + Container columnBackgrounds; Container topLevelContainer; InternalChildren = new Drawable[] @@ -77,9 +78,13 @@ namespace osu.Game.Rulesets.Mania.UI { RelativeSizeAxes = Axes.Both }, - columnFlow = new ColumnFlow(definition) + columnBackgrounds = new Container { - RelativeSizeAxes = Axes.Y, + Name = "Column backgrounds", + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + } }, new Container { @@ -98,6 +103,10 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Y, } }, + columnFlow = new ColumnFlow(definition) + { + RelativeSizeAxes = Axes.Y, + }, new SkinnableDrawable(new ManiaSkinComponentLookup(ManiaSkinComponents.StageForeground), _ => null) { RelativeSizeAxes = Axes.Both @@ -126,6 +135,7 @@ namespace osu.Game.Rulesets.Mania.UI }; topLevelContainer.Add(column.TopLevelContainer.CreateProxy()); + columnBackgrounds.Add(column.BackgroundContainer.CreateProxy()); columnFlow.SetContentForColumn(i, column); AddNested(column); } From 7d49f5d7c6b8cd329335e18500c08e6589c979a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 14:53:37 +0900 Subject: [PATCH 1117/1400] Apply NRT to `SectionsContainer` --- .../Graphics/Containers/SectionsContainer.cs | 62 ++++++++++--------- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- .../Screens/Edit/Setup/SetupScreenHeader.cs | 2 +- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 8dd6eac7bb..01e1af06c0 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -23,11 +20,35 @@ namespace osu.Game.Graphics.Containers public partial class SectionsContainer : Container where T : Drawable { - public Bindable SelectedSection { get; } = new Bindable(); + public Bindable SelectedSection { get; } = new Bindable(); - private T lastClickedSection; + private T? lastClickedSection; - public Drawable ExpandableHeader + protected override Container Content => scrollContentContainer; + + private readonly UserTrackingScrollContainer scrollContainer; + private readonly Container headerBackgroundContainer; + private readonly MarginPadding originalSectionsMargin; + + private Drawable? fixedHeader; + + private Drawable? footer; + private Drawable? headerBackground; + + private FlowContainer scrollContentContainer = null!; + + private float? headerHeight, footerHeight; + + private float? lastKnownScroll; + + /// + /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). + /// + private const float scroll_y_centre = 0.1f; + + private Drawable? expandableHeader; + + public Drawable? ExpandableHeader { get => expandableHeader; set @@ -42,11 +63,12 @@ namespace osu.Game.Graphics.Containers if (value == null) return; AddInternal(expandableHeader); + lastKnownScroll = null; } } - public Drawable FixedHeader + public Drawable? FixedHeader { get => fixedHeader; set @@ -63,7 +85,7 @@ namespace osu.Game.Graphics.Containers } } - public Drawable Footer + public Drawable? Footer { get => footer; set @@ -75,16 +97,17 @@ namespace osu.Game.Graphics.Containers footer = value; - if (value == null) return; + if (footer == null) return; footer.Anchor |= Anchor.y2; footer.Origin |= Anchor.y2; + scrollContainer.Add(footer); lastKnownScroll = null; } } - public Drawable HeaderBackground + public Drawable? HeaderBackground { get => headerBackground; set @@ -102,23 +125,6 @@ namespace osu.Game.Graphics.Containers } } - protected override Container Content => scrollContentContainer; - - private readonly UserTrackingScrollContainer scrollContainer; - private readonly Container headerBackgroundContainer; - private readonly MarginPadding originalSectionsMargin; - private Drawable expandableHeader, fixedHeader, footer, headerBackground; - private FlowContainer scrollContentContainer; - - private float? headerHeight, footerHeight; - - private float? lastKnownScroll; - - /// - /// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section). - /// - private const float scroll_y_centre = 0.1f; - public SectionsContainer() { AddRangeInternal(new Drawable[] @@ -171,10 +177,8 @@ namespace osu.Game.Graphics.Containers public void ScrollToTop() => scrollContainer.ScrollTo(0); - [NotNull] protected virtual UserTrackingScrollContainer CreateScrollContainer() => new UserTrackingScrollContainer(); - [NotNull] protected virtual FlowContainer CreateScrollContentContainer() => new FillFlowContainer { diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index ab4f07b982..0ab842c907 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -120,7 +120,7 @@ namespace osu.Game.Overlays if (lastSection != section.NewValue) { lastSection = section.NewValue; - tabs.Current.Value = lastSection; + tabs.Current.Value = lastSection!; } }; diff --git a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs index 1d66830adf..788beba9d9 100644 --- a/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs +++ b/osu.Game/Screens/Edit/Setup/SetupScreenHeader.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Edit.Setup { base.LoadComplete(); - sections.SelectedSection.BindValueChanged(section => tabControl.Current.Value = section.NewValue); + sections.SelectedSection.BindValueChanged(section => tabControl.Current.Value = section.NewValue!); tabControl.Current.BindValueChanged(section => { if (section.NewValue != sections.SelectedSection.Value) From 67e952150f8670888389aba1ec96e3b8e0fb9981 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 15:24:12 +0900 Subject: [PATCH 1118/1400] Fix scroll operations in `SectionsContainer` failing if target moves due to loaded content --- .../Graphics/Containers/SectionsContainer.cs | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 01e1af06c0..27ff6b851d 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -9,6 +9,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Layout; +using osu.Framework.Logging; +using osu.Framework.Threading; using osu.Framework.Utils; namespace osu.Game.Graphics.Containers @@ -156,23 +158,57 @@ namespace osu.Game.Graphics.Containers footerHeight = null; } + private ScheduledDelegate? scrollToTargetDelegate; + public void ScrollTo(Drawable target) { + Logger.Log($"Scrolling to {target}.."); + lastKnownScroll = null; - // implementation similar to ScrollIntoView but a bit more nuanced. - float top = scrollContainer.GetChildPosInContent(target); + float scrollTarget = getScrollTargetForDrawable(target); - float bottomScrollExtent = scrollContainer.ScrollableExtent; - float scrollTarget = top - scrollContainer.DisplayableContent * scroll_y_centre; - - if (scrollTarget > bottomScrollExtent) + if (scrollTarget > scrollContainer.ScrollableExtent) scrollContainer.ScrollToEnd(); else scrollContainer.ScrollTo(scrollTarget); if (target is T section) lastClickedSection = section; + + // Content may load in as a scroll occurs, changing the scroll target we need to aim for. + // This scheduled operation ensures that we keep trying until actually arriving at the target. + scrollToTargetDelegate?.Cancel(); + scrollToTargetDelegate = Scheduler.AddDelayed(() => + { + if (scrollContainer.UserScrolling) + { + Logger.Log("Scroll operation interrupted by user scroll"); + scrollToTargetDelegate?.Cancel(); + scrollToTargetDelegate = null; + return; + } + + if (Precision.AlmostEquals(scrollContainer.Current, scrollTarget, 1)) + { + Logger.Log($"Finished scrolling to {target}!"); + scrollToTargetDelegate?.Cancel(); + scrollToTargetDelegate = null; + return; + } + + if (!Precision.AlmostEquals(getScrollTargetForDrawable(target), scrollTarget, 1)) + { + Logger.Log($"Reattempting scroll to {target} due to change in position"); + ScrollTo(target); + } + }, 50, true); + } + + private float getScrollTargetForDrawable(Drawable target) + { + // implementation similar to ScrollIntoView but a bit more nuanced. + return scrollContainer.GetChildPosInContent(target) - scrollContainer.DisplayableContent * scroll_y_centre; } public void ScrollToTop() => scrollContainer.ScrollTo(0); From 757596fffa5eb98b09dcdaad6245297843b8d50d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 15:48:04 +0900 Subject: [PATCH 1119/1400] Add test coverage of scroll failing --- .../TestSceneSectionsContainer.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs index 05fffc903d..3a1eb554ab 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSectionsContainer.cs @@ -80,6 +80,24 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestCorrectScrollToWhenContentLoads() + { + AddRepeatStep("add many sections", () => append(1f), 3); + + AddStep("add section with delayed load content", () => + { + container.Add(new TestDelayedLoadSection("delayed")); + }); + + AddStep("add final section", () => append(0.5f)); + + AddStep("scroll to final section", () => container.ScrollTo(container.Children.Last())); + + AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children.Last()); + AddUntilStep("wait for scroll to section", () => container.ScreenSpaceDrawQuad.AABBFloat.Contains(container.Children.Last().ScreenSpaceDrawQuad.AABBFloat)); + } + [Test] public void TestSelection() { @@ -196,6 +214,33 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.ScrollVerticalBy(direction); } + private partial class TestDelayedLoadSection : TestSection + { + public TestDelayedLoadSection(string label) + : base(label) + { + BackgroundColour = default_colour; + Width = 300; + AutoSizeAxes = Axes.Y; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Box box; + + Add(box = new Box + { + Alpha = 0.01f, + RelativeSizeAxes = Axes.X, + }); + + // Emulate an operation that will be inhibited by IsMaskedAway. + box.ResizeHeightTo(2000, 50); + } + } + private partial class TestSection : TestBox { public bool Selected From 2c89af608ac5c136f81ed90a97ccf702a4f0c021 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 17:15:13 +0900 Subject: [PATCH 1120/1400] Add ability to cycle beat snap divisor using hotkeys Defaults to Ctrl+Shift+Wheel (as per stable). Closes #23785. --- .../Input/Bindings/GlobalActionContainer.cs | 10 +++++- .../GlobalActionKeyBindingStrings.cs | 10 ++++++ .../Compose/Components/BeatDivisorControl.cs | 34 ++++++++++++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index d580eea248..e84663db5e 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -101,6 +101,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.J }, GlobalAction.EditorFlipVertically), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.MouseWheelDown }, GlobalAction.EditorDecreaseDistanceSpacing), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.MouseWheelUp }, GlobalAction.EditorIncreaseDistanceSpacing), + new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelDown }, GlobalAction.EditorCyclePreviousBeatSnapDivisor), + new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelUp }, GlobalAction.EditorCycleNextBeatSnapDivisor), }; public IEnumerable InGameKeyBindings => new[] @@ -355,6 +357,12 @@ namespace osu.Game.Input.Bindings ToggleProfile, [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCloneSelection))] - EditorCloneSelection + EditorCloneSelection, + + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCyclePreviousBeatSnapDivisor))] + EditorCyclePreviousBeatSnapDivisor, + + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCycleNextBeatSnapDivisor))] + EditorCycleNextBeatSnapDivisor, } } diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs index 303dbb6f46..423fea6793 100644 --- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -279,6 +279,16 @@ namespace osu.Game.Localisation /// public static LocalisableString EditorDecreaseDistanceSpacing => new TranslatableString(getKey(@"editor_decrease_distance_spacing"), @"Decrease distance spacing"); + /// + /// "Cycle previous beat snap divisor" + /// + public static LocalisableString EditorCyclePreviousBeatSnapDivisor => new TranslatableString(getKey(@"editor_decrease_distance_spacing"), @"Cycle previous beat snap divisor"); + + /// + /// "Cycle next beat snap divisor" + /// + public static LocalisableString EditorCycleNextBeatSnapDivisor => new TranslatableString(getKey(@"editor_increase_distance_spacing"), @"Cycle next beat snap divisor"); + /// /// "Toggle skin editor" /// diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 432c5ea280..e96039ce16 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -16,12 +16,14 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Input.Bindings; using osu.Game.Overlays; using osuTK; using osuTK.Graphics; @@ -29,7 +31,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { - public partial class BeatDivisorControl : CompositeDrawable + public partial class BeatDivisorControl : CompositeDrawable, IKeyBindingHandler { private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); @@ -220,6 +222,36 @@ namespace osu.Game.Screens.Edit.Compose.Components return base.OnKeyDown(e); } + public virtual bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case GlobalAction.EditorCycleNextBeatSnapDivisor: + cycle(1); + return true; + + case GlobalAction.EditorCyclePreviousBeatSnapDivisor: + cycle(-1); + return true; + } + + return false; + } + + private void cycle(int direction) + { + var presets = beatDivisor.ValidDivisors.Value.Presets; + + int selectedIndex = presets.Count(e => e < beatDivisor.Value); + int newIndex = Math.Clamp(selectedIndex + direction, 0, presets.Count - 1); + + beatDivisor.Value = presets[newIndex]; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + internal partial class DivisorDisplay : OsuAnimatedButton, IHasPopover { public BindableBeatDivisor BeatDivisor { get; } = new BindableBeatDivisor(); From 15725fb18611925b70ed82396675bd419b848d70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 7 Jun 2023 18:07:56 +0900 Subject: [PATCH 1121/1400] Change default bindings to account for mouse wheel rotation --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index e84663db5e..fdd96d3890 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -101,8 +101,10 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.J }, GlobalAction.EditorFlipVertically), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.MouseWheelDown }, GlobalAction.EditorDecreaseDistanceSpacing), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.MouseWheelUp }, GlobalAction.EditorIncreaseDistanceSpacing), - new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelDown }, GlobalAction.EditorCyclePreviousBeatSnapDivisor), - new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelUp }, GlobalAction.EditorCycleNextBeatSnapDivisor), + // Framework automatically converts wheel up/down to left/right when shift is held. + // See https://github.com/ppy/osu-framework/blob/master/osu.Framework/Input/StateChanges/MouseScrollRelativeInput.cs#L37-L38. + new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelRight }, GlobalAction.EditorCyclePreviousBeatSnapDivisor), + new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.MouseWheelLeft }, GlobalAction.EditorCycleNextBeatSnapDivisor), }; public IEnumerable InGameKeyBindings => new[] From f8a3be24c8f1923671da7159b05a0e88b735d85e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 00:22:06 +0900 Subject: [PATCH 1122/1400] Update config.yml to mention "performance" in the discussion link --- .github/ISSUE_TEMPLATE/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 47a6a4c3d3..ec57232126 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,7 +2,7 @@ blank_issues_enabled: false contact_links: - name: Help url: https://github.com/ppy/osu/discussions/categories/q-a - about: osu! not working as you'd expect? Not sure it's a bug? Check the Q&A section! + about: osu! not working or performing as you'd expect? Not sure it's a bug? Check the Q&A section! - name: Suggestions or feature request url: https://github.com/ppy/osu/discussions/categories/ideas about: Got something you think should change or be added? Search for or start a new discussion! From 3a014987895681911b6a7ee8a8f3a3bf2e96e4f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 00:53:58 +0900 Subject: [PATCH 1123/1400] Use existing next/previous methods (and remove looping behaviour) --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 11 +++++++---- osu.Game/Screens/Edit/BindableBeatDivisor.cs | 10 ++++++---- .../Edit/Compose/Components/BeatDivisorControl.cs | 12 ++++++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 353acfa4ba..59fa331abe 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -51,9 +51,9 @@ namespace osu.Game.Tests.Visual.Editing [Test] public void TestBindableBeatDivisor() { - AddRepeatStep("move previous", () => bindableBeatDivisor.Previous(), 2); + AddRepeatStep("move previous", () => bindableBeatDivisor.SelectPrevious(), 2); AddAssert("divisor is 4", () => bindableBeatDivisor.Value == 4); - AddRepeatStep("move next", () => bindableBeatDivisor.Next(), 1); + AddRepeatStep("move next", () => bindableBeatDivisor.SelectNext(), 1); AddAssert("divisor is 12", () => bindableBeatDivisor.Value == 8); } @@ -101,6 +101,9 @@ namespace osu.Game.Tests.Visual.Editing public void TestBeatChevronNavigation() { switchBeatSnap(1); + assertBeatSnap(16); + + switchBeatSnap(-4); assertBeatSnap(1); switchBeatSnap(3); @@ -110,7 +113,7 @@ namespace osu.Game.Tests.Visual.Editing assertBeatSnap(4); switchBeatSnap(-3); - assertBeatSnap(16); + assertBeatSnap(1); } [Test] @@ -207,7 +210,7 @@ namespace osu.Game.Tests.Visual.Editing }, Math.Abs(direction)); private void assertBeatSnap(int expected) => AddAssert($"beat snap is {expected}", - () => bindableBeatDivisor.Value == expected); + () => bindableBeatDivisor.Value, () => Is.EqualTo(expected)); private void switchPresets(int direction) => AddRepeatStep($"move presets {(direction > 0 ? "forward" : "backward")}", () => { diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 1da224d850..ffa4f01e75 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -59,16 +59,18 @@ namespace osu.Game.Screens.Edit Value = 1; } - public void Next() + public void SelectNext() { var presets = ValidDivisors.Value.Presets; - Value = presets.Cast().SkipWhile(preset => preset != Value).ElementAtOrDefault(1) ?? presets[0]; + if (presets.Cast().SkipWhile(preset => preset != Value).ElementAtOrDefault(1) is int newValue) + Value = newValue; } - public void Previous() + public void SelectPrevious() { var presets = ValidDivisors.Value.Presets; - Value = presets.Cast().TakeWhile(preset => preset != Value).LastOrDefault() ?? presets[^1]; + if (presets.Cast().TakeWhile(preset => preset != Value).LastOrDefault() is int newValue) + Value = newValue; } protected override int DefaultPrecision => 1; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index e96039ce16..9b47990c57 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -103,13 +103,13 @@ namespace osu.Game.Screens.Edit.Compose.Components new ChevronButton { Icon = FontAwesome.Solid.ChevronLeft, - Action = beatDivisor.Previous + Action = beatDivisor.SelectPrevious }, new DivisorDisplay { BeatDivisor = { BindTarget = beatDivisor } }, new ChevronButton { Icon = FontAwesome.Solid.ChevronRight, - Action = beatDivisor.Next + Action = beatDivisor.SelectNext } }, }, @@ -227,11 +227,11 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (e.Action) { case GlobalAction.EditorCycleNextBeatSnapDivisor: - cycle(1); + beatDivisor.SelectNext(); return true; case GlobalAction.EditorCyclePreviousBeatSnapDivisor: - cycle(-1); + beatDivisor.SelectPrevious(); return true; } @@ -474,12 +474,12 @@ namespace osu.Game.Screens.Edit.Compose.Components switch (e.Key) { case Key.Right: - beatDivisor.Next(); + beatDivisor.SelectNext(); OnUserChange(Current.Value); return true; case Key.Left: - beatDivisor.Previous(); + beatDivisor.SelectPrevious(); OnUserChange(Current.Value); return true; From 8463f5c7ddab3867818996d22f3a86fd2e08eb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 21:50:16 +0200 Subject: [PATCH 1124/1400] Spell out location of external proxy explicitly --- osu.Game.Rulesets.Mania/UI/Column.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 659b63b640..f38571a6d3 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -90,7 +90,8 @@ namespace osu.Game.Rulesets.Mania.UI { RelativeSizeAxes = Axes.Both, }, - // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements externally. + // For input purposes, the background is added at the highest depth, but is then proxied back below all other elements externally + // (see `Stage.columnBackgrounds`). BackgroundContainer, TopLevelContainer, new ColumnTouchInputArea(this) From c8507837d156c3b6f30506e1382252d215ef484a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 21:51:35 +0200 Subject: [PATCH 1125/1400] Remove redundant initialisation of `Children` to empty array --- osu.Game.Rulesets.Mania/UI/Stage.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index 215d81b64a..879c704450 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -82,9 +82,6 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Column backgrounds", RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - } }, new Container { From d9281ac8c75475fb79ff70efc76f0fc6a5924bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 23:28:27 +0200 Subject: [PATCH 1126/1400] Remove unused `virtual` spec --- osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 9b47990c57..cbe4830e40 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Edit.Compose.Components return base.OnKeyDown(e); } - public virtual bool OnPressed(KeyBindingPressEvent e) + public bool OnPressed(KeyBindingPressEvent e) { switch (e.Action) { From 3c8f387a6c9ba41bdf9c87431df33d94626142cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 23:28:36 +0200 Subject: [PATCH 1127/1400] Remove unused method --- .../Edit/Compose/Components/BeatDivisorControl.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index cbe4830e40..5a1fbbee1e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -238,16 +238,6 @@ namespace osu.Game.Screens.Edit.Compose.Components return false; } - private void cycle(int direction) - { - var presets = beatDivisor.ValidDivisors.Value.Presets; - - int selectedIndex = presets.Count(e => e < beatDivisor.Value); - int newIndex = Math.Clamp(selectedIndex + direction, 0, presets.Count - 1); - - beatDivisor.Value = presets[newIndex]; - } - public void OnReleased(KeyBindingReleaseEvent e) { } From 35e41d816ae6750f36555d86f0c7c99119c308cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 23:31:46 +0200 Subject: [PATCH 1128/1400] Cover clamping to max beat divisor in test --- osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 59fa331abe..c7b6d984ed 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -109,7 +109,10 @@ namespace osu.Game.Tests.Visual.Editing switchBeatSnap(3); assertBeatSnap(8); - switchBeatSnap(-1); + switchBeatSnap(3); + assertBeatSnap(16); + + switchBeatSnap(-2); assertBeatSnap(4); switchBeatSnap(-3); From f416b3a226844e951bbd6b75e7a488927b0a4cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 7 Jun 2023 23:43:21 +0200 Subject: [PATCH 1129/1400] Fix new localisations using lookup keys of existing ones --- osu.Game/Localisation/GlobalActionKeyBindingStrings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs index 423fea6793..aa608a603b 100644 --- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -282,12 +282,12 @@ namespace osu.Game.Localisation /// /// "Cycle previous beat snap divisor" /// - public static LocalisableString EditorCyclePreviousBeatSnapDivisor => new TranslatableString(getKey(@"editor_decrease_distance_spacing"), @"Cycle previous beat snap divisor"); + public static LocalisableString EditorCyclePreviousBeatSnapDivisor => new TranslatableString(getKey(@"editor_cycle_previous_beat_snap_divisor"), @"Cycle previous beat snap divisor"); /// /// "Cycle next beat snap divisor" /// - public static LocalisableString EditorCycleNextBeatSnapDivisor => new TranslatableString(getKey(@"editor_increase_distance_spacing"), @"Cycle next beat snap divisor"); + public static LocalisableString EditorCycleNextBeatSnapDivisor => new TranslatableString(getKey(@"editor_cycle_next_snap_divisor"), @"Cycle next beat snap divisor"); /// /// "Toggle skin editor" From 1a90f71540fc4a0bab3ef257cd8b0a6690d0a2eb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 8 Jun 2023 02:47:07 +0300 Subject: [PATCH 1130/1400] Centralise game language update logic --- osu.Game/OsuGameBase.cs | 25 +++++++++++++- .../Overlays/FirstRunSetup/ScreenWelcome.cs | 33 +++++++------------ .../Sections/General/LanguageSettings.cs | 22 ++----------- 3 files changed, 39 insertions(+), 41 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c55b6c249f..ed954f609e 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Bindables; +using osu.Framework.Configuration; using osu.Framework.Development; using osu.Framework.Extensions; using osu.Framework.Graphics; @@ -27,6 +28,7 @@ using osu.Framework.Input.Handlers.Mouse; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Input.Handlers.Touch; using osu.Framework.IO.Stores; +using osu.Framework.Localisation; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Timing; @@ -36,11 +38,13 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.Formats; using osu.Game.Configuration; using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; +using osu.Game.Localisation; using osu.Game.Online; using osu.Game.Online.API; using osu.Game.Online.Chat; @@ -157,6 +161,11 @@ namespace osu.Game protected Storage Storage { get; set; } + /// + /// The language in which the game is currently displayed in. + /// + public Bindable CurrentLanguage { get; } = new Bindable(); + protected Bindable Beatmap { get; private set; } // cached via load() method /// @@ -216,6 +225,10 @@ namespace osu.Game private readonly BindableNumber globalTrackVolumeAdjust = new BindableNumber(global_track_volume_adjust); + private Bindable frameworkLocale = null!; + + private IBindable localisationParameters = null!; + /// /// Number of unhandled exceptions to allow before aborting execution. /// @@ -238,7 +251,7 @@ namespace osu.Game } [BackgroundDependencyLoader] - private void load(ReadableKeyCombinationProvider keyCombinationProvider) + private void load(ReadableKeyCombinationProvider keyCombinationProvider, FrameworkConfigManager frameworkConfig) { try { @@ -284,6 +297,14 @@ namespace osu.Game MessageFormatter.WebsiteRootUrl = endpoints.WebsiteRootUrl; dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints, VersionHash)); + frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); + frameworkLocale.BindValueChanged(_ => updateLanguage()); + + localisationParameters = Localisation.CurrentParameters.GetBoundCopy(); + localisationParameters.BindValueChanged(_ => updateLanguage(), true); + + CurrentLanguage.BindValueChanged(val => frameworkLocale.Value = val.NewValue.ToCultureCode()); + var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); @@ -394,6 +415,8 @@ namespace osu.Game Beatmap.BindValueChanged(onBeatmapChanged); } + private void updateLanguage() => CurrentLanguage.Value = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value); + private void addFilesWarning() { var realmStore = new RealmFileStore(realm, Storage); diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs index b8d802ad4b..68c6c78986 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenWelcome.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Threading; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -68,13 +67,12 @@ namespace osu.Game.Overlays.FirstRunSetup private partial class LanguageSelectionFlow : FillFlowContainer { - private Bindable frameworkLocale = null!; - private IBindable localisationParameters = null!; + private Bindable language = null!; private ScheduledDelegate? updateSelectedDelegate; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig, LocalisationManager localisation) + private void load(OsuGameBase game) { Direction = FillDirection.Full; Spacing = new Vector2(5); @@ -82,25 +80,18 @@ namespace osu.Game.Overlays.FirstRunSetup ChildrenEnumerable = Enum.GetValues() .Select(l => new LanguageButton(l) { - Action = () => frameworkLocale.Value = l.ToCultureCode() + Action = () => language.Value = l, }); - frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); - frameworkLocale.BindValueChanged(_ => onLanguageChange()); - - localisationParameters = localisation.CurrentParameters.GetBoundCopy(); - localisationParameters.BindValueChanged(_ => onLanguageChange(), true); - } - - private void onLanguageChange() - { - var language = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value); - - // Changing language may cause a short period of blocking the UI thread while the new glyphs are loaded. - // Scheduling ensures the button animation plays smoothly after any blocking operation completes. - // Note that a delay is required (the alternative would be a double-schedule; delay feels better). - updateSelectedDelegate?.Cancel(); - updateSelectedDelegate = Scheduler.AddDelayed(() => updateSelectedStates(language), 50); + language = game.CurrentLanguage.GetBoundCopy(); + language.BindValueChanged(v => + { + // Changing language may cause a short period of blocking the UI thread while the new glyphs are loaded. + // Scheduling ensures the button animation plays smoothly after any blocking operation completes. + // Note that a delay is required (the alternative would be a double-schedule; delay feels better). + updateSelectedDelegate?.Cancel(); + updateSelectedDelegate = Scheduler.AddDelayed(() => updateSelectedStates(v.NewValue), 50); + }, true); } private void updateSelectedStates(Language language) diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index 982cbec376..d3b657b5be 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -2,35 +2,27 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Configuration; -using osu.Game.Extensions; using osu.Game.Localisation; namespace osu.Game.Overlays.Settings.Sections.General { public partial class LanguageSettings : SettingsSubsection { - private SettingsDropdown languageSelection = null!; - private Bindable frameworkLocale = null!; - private IBindable localisationParameters = null!; - protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager config, LocalisationManager localisation) + private void load(OsuGame game, OsuConfigManager config, FrameworkConfigManager frameworkConfig) { - frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); - localisationParameters = localisation.CurrentParameters.GetBoundCopy(); - Children = new Drawable[] { - languageSelection = new SettingsEnumDropdown + new SettingsEnumDropdown { LabelText = GeneralSettingsStrings.LanguageDropdown, + Current = game.CurrentLanguage, }, new SettingsCheckbox { @@ -43,14 +35,6 @@ namespace osu.Game.Overlays.Settings.Sections.General Current = config.GetBindable(OsuSetting.Prefer24HourTime) }, }; - - frameworkLocale.BindValueChanged(_ => updateSelection()); - localisationParameters.BindValueChanged(_ => updateSelection(), true); - - languageSelection.Current.BindValueChanged(val => frameworkLocale.Value = val.NewValue.ToCultureCode()); } - - private void updateSelection() => - languageSelection.Current.Value = LanguageExtensions.GetLanguageFor(frameworkLocale.Value, localisationParameters.Value); } } From ab790ec96a30c296d6ac255b990c7736c27557ee Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 8 Jun 2023 02:50:14 +0300 Subject: [PATCH 1131/1400] Expose currently selected language from `IAPIProvider` --- osu.Game/Online/API/APIAccess.cs | 7 ++++++- osu.Game/Online/API/DummyAPIAccess.cs | 3 +++ osu.Game/Online/API/IAPIProvider.cs | 6 ++++++ osu.Game/OsuGameBase.cs | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 94bb77d6ec..4f586c8fff 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -18,6 +18,7 @@ using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Configuration; +using osu.Game.Localisation; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Notifications; @@ -28,6 +29,7 @@ namespace osu.Game.Online.API { public partial class APIAccess : Component, IAPIProvider { + private readonly OsuGameBase game; private readonly OsuConfigManager config; private readonly string versionHash; @@ -52,6 +54,8 @@ namespace osu.Game.Online.API public IBindableList Friends => friends; public IBindable Activity => activity; + public Language Language => game.CurrentLanguage.Value; + private Bindable localUser { get; } = new Bindable(createGuestUser()); private BindableList friends { get; } = new BindableList(); @@ -64,8 +68,9 @@ namespace osu.Game.Online.API private readonly Logger log; - public APIAccess(OsuConfigManager config, EndpointConfiguration endpointConfiguration, string versionHash) + public APIAccess(OsuGameBase game, OsuConfigManager config, EndpointConfiguration endpointConfiguration, string versionHash) { + this.game = game; this.config = config; this.versionHash = versionHash; diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index abe2755654..16afef8e30 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Notifications; using osu.Game.Tests; @@ -29,6 +30,8 @@ namespace osu.Game.Online.API public Bindable Activity { get; } = new Bindable(); + public Language Language => Language.en; + public string AccessToken => "token"; public bool IsLoggedIn => State.Value == APIState.Online; diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index 6054effaa1..a1d7006c8c 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using osu.Framework.Bindables; +using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Notifications; using osu.Game.Users; @@ -27,6 +28,11 @@ namespace osu.Game.Online.API /// IBindable Activity { get; } + /// + /// The language supplied by this provider to API requests. + /// + Language Language { get; } + /// /// Retrieve the OAuth access token. /// diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index ed954f609e..63efe0e2c8 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -296,7 +296,6 @@ namespace osu.Game MessageFormatter.WebsiteRootUrl = endpoints.WebsiteRootUrl; - dependencies.CacheAs(API ??= new APIAccess(LocalConfig, endpoints, VersionHash)); frameworkLocale = frameworkConfig.GetBindable(FrameworkSetting.Locale); frameworkLocale.BindValueChanged(_ => updateLanguage()); @@ -305,6 +304,7 @@ namespace osu.Game CurrentLanguage.BindValueChanged(val => frameworkLocale.Value = val.NewValue.ToCultureCode()); + dependencies.CacheAs(API ??= new APIAccess(this, LocalConfig, endpoints, VersionHash)); var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures); From 9f842ccdc057e6c6ec60def1ac607f1ea00f02e1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 8 Jun 2023 02:50:29 +0300 Subject: [PATCH 1132/1400] Supply `Accept-Language` header in API requests --- osu.Game/Online/API/APIRequest.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index dc6a3fe3d5..cd6e8df754 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -9,6 +9,7 @@ using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.IO.Network; using osu.Framework.Logging; +using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API @@ -116,10 +117,11 @@ namespace osu.Game.Online.API WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; - WebRequest.AddHeader("x-api-version", API.APIVersion.ToString(CultureInfo.InvariantCulture)); + WebRequest.AddHeader(@"Accept-Language", API.Language.ToCultureCode()); + WebRequest.AddHeader(@"x-api-version", API.APIVersion.ToString(CultureInfo.InvariantCulture)); if (!string.IsNullOrEmpty(API.AccessToken)) - WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); + WebRequest.AddHeader(@"Authorization", $@"Bearer {API.AccessToken}"); if (isFailing) return; From 251f23b2c2e85c70d08803c911ec3e4fe4cb0791 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 8 Jun 2023 03:27:03 +0300 Subject: [PATCH 1133/1400] Handle culture code differences of Traditional Chinese --- osu.Game/Extensions/LanguageExtensions.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/osu.Game/Extensions/LanguageExtensions.cs b/osu.Game/Extensions/LanguageExtensions.cs index 04231c384c..44932cf3c8 100644 --- a/osu.Game/Extensions/LanguageExtensions.cs +++ b/osu.Game/Extensions/LanguageExtensions.cs @@ -21,7 +21,12 @@ namespace osu.Game.Extensions /// This is required as enum member names are not allowed to contain hyphens. /// public static string ToCultureCode(this Language language) - => language.ToString().Replace("_", "-"); + { + if (language == Language.zh_hant) + return @"zh-tw"; + + return language.ToString().Replace("_", "-"); + } /// /// Attempts to parse the supplied to a value. @@ -30,7 +35,15 @@ namespace osu.Game.Extensions /// The parsed . Valid only if the return value of the method is . /// Whether the parsing succeeded. public static bool TryParseCultureCode(string cultureCode, out Language language) - => Enum.TryParse(cultureCode.Replace("-", "_"), out language); + { + if (cultureCode == @"zh-tw") + { + language = Language.zh_hant; + return true; + } + + return Enum.TryParse(cultureCode.Replace("-", "_"), out language); + } /// /// Parses the that is specified in , From d523785bfc34192a695ac0b8136272fe50b05ad8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 8 Jun 2023 03:27:23 +0300 Subject: [PATCH 1134/1400] Fix `LanguageSettings` requiring `OsuGame` as dependency --- osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index d3b657b5be..cf7f63211e 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Settings.Sections.General protected override LocalisableString Header => GeneralSettingsStrings.LanguageHeader; [BackgroundDependencyLoader] - private void load(OsuGame game, OsuConfigManager config, FrameworkConfigManager frameworkConfig) + private void load(OsuGameBase game, OsuConfigManager config, FrameworkConfigManager frameworkConfig) { Children = new Drawable[] { From a842f79ad49cc98afaef897c85f2f5657ca32029 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 16:17:44 +0900 Subject: [PATCH 1135/1400] Refactor `IWorkingBeatmap.Background` to `GetBackground()` --- osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs | 2 +- osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs | 2 +- .../Visual/Background/TestSceneBackgroundScreenDefault.cs | 2 +- osu.Game.Tests/WaveformTestBeatmap.cs | 2 +- osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs | 5 +++-- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 4 +--- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 +- osu.Game/Graphics/Backgrounds/BeatmapBackground.cs | 2 +- osu.Game/Overlays/NowPlayingOverlay.cs | 2 +- osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs | 2 +- osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs | 2 +- .../Screens/OnlinePlay/Components/PlaylistItemBackground.cs | 2 +- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 2 +- osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs | 2 +- osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 2 +- osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 2 +- 19 files changed, 21 insertions(+), 22 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index 09130ac57d..fac5e098b9 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -231,7 +231,7 @@ namespace osu.Game.Tests.Beatmaps.Formats protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture GetBackground() => throw new NotImplementedException(); + public override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index 295a10ba5b..3092966a7e 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -131,7 +131,7 @@ namespace osu.Game.Tests.Editing.Checks var mock = new Mock(); mock.SetupGet(w => w.Beatmap).Returns(beatmap); - mock.SetupGet(w => w.Background).Returns(background); + mock.SetupGet(w => w.GetBackground()).Returns(background); mock.Setup(w => w.GetStream(It.IsAny())).Returns(stream); return mock; diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs index 8f4250799e..1523ae7027 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs @@ -286,7 +286,7 @@ namespace osu.Game.Tests.Visual.Background this.renderer = renderer; } - protected override Texture GetBackground() => renderer.CreateTexture(1, 1); + public override Texture GetBackground() => renderer.CreateTexture(1, 1); } private partial class TestWorkingBeatmapWithStoryboard : TestWorkingBeatmap diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 5e41392560..12660ed2e1 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -51,7 +51,7 @@ namespace osu.Game.Tests protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture GetBackground() => null; + public override Texture GetBackground() => null; protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index 767504fcb1..5b9cf6846c 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -23,8 +23,9 @@ namespace osu.Game.Beatmaps.Drawables [BackgroundDependencyLoader] private void load() { - if (working.Background != null) - Texture = working.Background; + var background = working.GetBackground(); + if (background != null) + Texture = background; } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 0b390a2ab5..8089d789c1 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => new Beatmap(); - protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); + public override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); protected override Track GetBeatmapTrack() => GetVirtualTrack(); diff --git a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs index 02fcde5257..0b53278ab3 100644 --- a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps } protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture GetBackground() => throw new NotImplementedException(); + public override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); protected internal override ISkin GetSkin() => throw new NotImplementedException(); public override Stream GetStream(string storagePath) => throw new NotImplementedException(); diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 0f0e72b0ac..4b0a498a56 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -47,7 +47,7 @@ namespace osu.Game.Beatmaps /// /// Retrieves the background for this . /// - Texture Background { get; } + Texture GetBackground(); /// /// Retrieves the for the of this . diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 59a71fd80c..a69859f724 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -34,8 +34,6 @@ namespace osu.Game.Beatmaps public Storyboard Storyboard => storyboard.Value; - public Texture Background => GetBackground(); // Texture uses ref counting, so we want to return a new instance every usage. - public ISkin Skin => skin.Value; private AudioManager audioManager { get; } @@ -67,7 +65,7 @@ namespace osu.Game.Beatmaps protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; protected abstract IBeatmap GetBeatmap(); - protected abstract Texture GetBackground(); + public abstract Texture GetBackground(); protected abstract Track GetBeatmapTrack(); /// diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index ef843909d8..94865ed8d0 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -160,7 +160,7 @@ namespace osu.Game.Beatmaps } } - protected override Texture GetBackground() + public override Texture GetBackground() { if (string.IsNullOrEmpty(Metadata?.BackgroundFile)) return null; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index b79eb4927f..3ace67f410 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.Backgrounds [BackgroundDependencyLoader] private void load(LargeTextureStore textures) { - Sprite.Texture = Beatmap?.Background ?? textures.Get(fallbackTextureName); + Sprite.Texture = Beatmap?.GetBackground() ?? textures.Get(fallbackTextureName); } public override bool Equals(Background other) diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index 66fb3571ba..e3e3b4bd80 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -415,7 +415,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(LargeTextureStore textures) { - sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); + sprite.Texture = beatmap?.GetBackground() ?? textures.Get(@"Backgrounds/bg4"); } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 23fa28e7bc..8c3a5c026d 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Edit.Checks if (backgroundFile == null) yield break; - var texture = context.WorkingBeatmap.Background; + var texture = context.WorkingBeatmap.GetBackground(); if (texture == null) yield break; diff --git a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs index 2cf823ca0c..565379f391 100644 --- a/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs +++ b/osu.Game/Screens/Edit/LegacyEditorBeatmapPatcher.cs @@ -204,7 +204,7 @@ namespace osu.Game.Screens.Edit protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture GetBackground() => throw new NotImplementedException(); + public override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index 997ba6b639..6b06eaee1e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.OnlinePlay.Components if (Beatmap?.BeatmapSet is IBeatmapSetOnlineInfo online) texture = textures.Get(online.Covers.Cover); - Sprite.Texture = texture ?? beatmaps.DefaultBeatmap.Background; + Sprite.Texture = texture ?? beatmaps.DefaultBeatmap.GetBackground(); } public override bool Equals(Background? other) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index a152f4be19..66aa3d9cc0 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play new Sprite { RelativeSizeAxes = Axes.Both, - Texture = beatmap.Background, + Texture = beatmap.GetBackground(), Origin = Anchor.Centre, Anchor = Anchor.Centre, FillMode = FillMode.Fill, diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 4f37c215e9..82f116b4ae 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Play.HUD protected override IBeatmap GetBeatmap() => gameplayBeatmap; - protected override Texture GetBackground() => throw new NotImplementedException(); + public override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index 79f629ce49..b57b0daa1b 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -232,7 +232,7 @@ namespace osu.Game.Tests.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; - protected override Texture GetBackground() => throw new NotImplementedException(); + public override Texture GetBackground() => throw new NotImplementedException(); protected override Track GetBeatmapTrack() => throw new NotImplementedException(); diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 7d2aa99dbe..ba6d9ca8b5 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Beatmaps public override Stream? GetStream(string storagePath) => null; - protected override Texture? GetBackground() => null; + public override Texture? GetBackground() => null; protected override Track? GetBeatmapTrack() => null; } From 5162f5c3d8d18bee824fddf63ac65fa036d0723e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 09:20:43 +0200 Subject: [PATCH 1136/1400] Fix code quality inspections --- osu.Game/Overlays/SettingsPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index d571557993..1681187f82 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -328,7 +328,7 @@ namespace osu.Game.Overlays base.UpdateAfterChildren(); // no null check because the usage of this class is strict - HeaderBackground.Alpha = -ExpandableHeader.Y / ExpandableHeader.LayoutSize.Y; + HeaderBackground!.Alpha = -ExpandableHeader!.Y / ExpandableHeader.LayoutSize.Y; } } } From 3978d4babb86917150c7bfb5a19ce3c72830b885 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 16:30:14 +0900 Subject: [PATCH 1137/1400] Crop and disable mipmaps on beatmap panel backgrounds This is an effort to improve general performance at song select. At least on the metal renderer, I can notice very high draw frame overheads related to texture uploads. By reducing the size of the texture uploads to roughly match what is actually being displayed on screen (using a relatively inexpensive crop operation), we can bastly reduce stuttering both during initial load and carousel scroll. You might ask if it's safe to disable mipmapping, but I've tested with lower resolutions and bilinear filtering seems to handle just fine. Bilinear without mipmaps only falls apart when you scale below 50% and we're not going too far past that at minimum game scale, if at all. --- ...eatmapPanelBackgroundTextureLoaderStore.cs | 88 +++++++++++++++++++ osu.Game/Beatmaps/IBeatmapResourceProvider.cs | 5 ++ osu.Game/Beatmaps/IWorkingBeatmap.cs | 5 ++ osu.Game/Beatmaps/WorkingBeatmap.cs | 1 + osu.Game/Beatmaps/WorkingBeatmapCache.cs | 11 ++- .../Select/Carousel/SetPanelBackground.cs | 24 ++++- 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs new file mode 100644 index 0000000000..0ee516a912 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -0,0 +1,88 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Processing; + +namespace osu.Game.Beatmaps +{ + // Implementation of this class is based off of `MaxDimensionLimitedTextureLoaderStore`. + // If issues are found it's worth checking to make sure similar issues exist there. + public class BeatmapPanelBackgroundTextureLoaderStore : IResourceStore + { + // These numbers are taken from the draw visualiser size requirements for song select panel textures at extreme aspect ratios. + private const int height = 130; + private const int max_width = 1280; + + private readonly IResourceStore? textureStore; + + public BeatmapPanelBackgroundTextureLoaderStore(IResourceStore? textureStore) + { + this.textureStore = textureStore; + } + + public void Dispose() + { + textureStore?.Dispose(); + } + + public TextureUpload Get(string name) + { + var textureUpload = textureStore?.Get(name); + + // NRT not enabled on framework side classes (IResourceStore / TextureLoaderStore), welp. + if (textureUpload == null) + return null!; + + return limitTextureUploadSize(textureUpload); + } + + public async Task GetAsync(string name, CancellationToken cancellationToken = new CancellationToken()) + { + // NRT not enabled on framework side classes (IResourceStore / TextureLoaderStore), welp. + if (textureStore == null) + return null!; + + var textureUpload = await textureStore.GetAsync(name, cancellationToken).ConfigureAwait(false); + + if (textureUpload == null) + return null!; + + return await Task.Run(() => limitTextureUploadSize(textureUpload), cancellationToken).ConfigureAwait(false); + } + + private TextureUpload limitTextureUploadSize(TextureUpload textureUpload) + { + var image = Image.LoadPixelData(textureUpload.Data.ToArray(), textureUpload.Width, textureUpload.Height); + + // The original texture upload will no longer be returned or used. + textureUpload.Dispose(); + + Size size = image.Size(); + int usableWidth = Math.Min(max_width, size.Width); + + // Crop the centre region of the background for now. + Rectangle cropRectangle = new Rectangle( + (size.Width - usableWidth) / 2, + size.Height / 2 - height / 2, + usableWidth, + height + ); + + image.Mutate(i => i.Crop(cropRectangle)); + + return new TextureUpload(image); + } + + public Stream? GetStream(string name) => textureStore?.GetStream(name); + + public IEnumerable GetAvailableResources() => textureStore?.GetAvailableResources() ?? Array.Empty(); + } +} diff --git a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs index 22ff7ce8c8..d033608c95 100644 --- a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs +++ b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs @@ -16,6 +16,11 @@ namespace osu.Game.Beatmaps /// TextureStore LargeTextureStore { get; } + /// + /// Retrieve a global large texture store, used specifically for retrieving cropped beatmap panel backgrounds. + /// + TextureStore BeatmapPanelTextureStore { get; } + /// /// Access a global track store for retrieving beatmap tracks from. /// diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 4b0a498a56..905bca45b3 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -49,6 +49,11 @@ namespace osu.Game.Beatmaps /// Texture GetBackground(); + /// + /// Retrieves a cropped background for this used for display on panels. + /// + Texture GetPanelBackground(); + /// /// Retrieves the for the of this . /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index a69859f724..25159996f3 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -66,6 +66,7 @@ namespace osu.Game.Beatmaps protected abstract IBeatmap GetBeatmap(); public abstract Texture GetBackground(); + public virtual Texture GetPanelBackground() => GetBackground(); protected abstract Track GetBeatmapTrack(); /// diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 94865ed8d0..0f3d61f527 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -42,6 +42,7 @@ namespace osu.Game.Beatmaps private readonly AudioManager audioManager; private readonly IResourceStore resources; private readonly LargeTextureStore largeTextureStore; + private readonly LargeTextureStore beatmapPanelTextureStore; private readonly ITrackStore trackStore; private readonly IResourceStore files; @@ -58,6 +59,7 @@ namespace osu.Game.Beatmaps this.host = host; this.files = files; largeTextureStore = new LargeTextureStore(host?.Renderer ?? new DummyRenderer(), host?.CreateTextureLoaderStore(files)); + beatmapPanelTextureStore = new LargeTextureStore(host?.Renderer ?? new DummyRenderer(), new BeatmapPanelBackgroundTextureLoaderStore(host?.CreateTextureLoaderStore(files))); this.trackStore = trackStore; } @@ -110,6 +112,7 @@ namespace osu.Game.Beatmaps #region IResourceStorageProvider TextureStore IBeatmapResourceProvider.LargeTextureStore => largeTextureStore; + TextureStore IBeatmapResourceProvider.BeatmapPanelTextureStore => beatmapPanelTextureStore; ITrackStore IBeatmapResourceProvider.Tracks => trackStore; IRenderer IStorageResourceProvider.Renderer => host?.Renderer ?? new DummyRenderer(); AudioManager IStorageResourceProvider.AudioManager => audioManager; @@ -160,7 +163,11 @@ namespace osu.Game.Beatmaps } } - public override Texture GetBackground() + public override Texture GetPanelBackground() => getBackgroundFromStore(resources.BeatmapPanelTextureStore); + + public override Texture GetBackground() => getBackgroundFromStore(resources.LargeTextureStore); + + private Texture getBackgroundFromStore(TextureStore store) { if (string.IsNullOrEmpty(Metadata?.BackgroundFile)) return null; @@ -168,7 +175,7 @@ namespace osu.Game.Beatmaps try { string fileStorePath = BeatmapSetInfo.GetPathForFile(Metadata.BackgroundFile); - var texture = resources.LargeTextureStore.Get(fileStorePath); + var texture = store.Get(fileStorePath); if (texture == null) { diff --git a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs index 6f13a34bfc..b8729b7174 100644 --- a/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs +++ b/osu.Game/Screens/Select/Carousel/SetPanelBackground.cs @@ -1,12 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osuTK; using osuTK.Graphics; @@ -21,7 +23,7 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { - new BeatmapBackgroundSprite(working) + new PanelBeatmapBackground(working) { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, @@ -68,5 +70,23 @@ namespace osu.Game.Screens.Select.Carousel }, }; } + + public partial class PanelBeatmapBackground : Sprite + { + private readonly IWorkingBeatmap working; + + public PanelBeatmapBackground(IWorkingBeatmap working) + { + ArgumentNullException.ThrowIfNull(working); + + this.working = working; + } + + [BackgroundDependencyLoader] + private void load() + { + Texture = working.GetPanelBackground(); + } + } } } From d07437f81066604178fca0748abd83eb34df2e8e Mon Sep 17 00:00:00 2001 From: John Biddle Date: Thu, 8 Jun 2023 00:52:28 -0700 Subject: [PATCH 1138/1400] Added recommendations from bdach: Fixed null checking in ApplyToDrawableHitObject Renamed mod to "Synesthesia" Moved to the "Fun" mod category --- .../Mods/{OsuModSnapColour.cs => OsuModSynesthesia.cs} | 5 ++--- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- .../Rulesets/Mods/{ModSnapColour.cs => ModSynesthesia.cs} | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) rename osu.Game.Rulesets.Osu/Mods/{OsuModSnapColour.cs => OsuModSynesthesia.cs} (84%) rename osu.Game/Rulesets/Mods/{ModSnapColour.cs => ModSynesthesia.cs} (71%) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs similarity index 84% rename from osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs rename to osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs index f6fffaf736..2aec416867 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSnapColour.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; @@ -14,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods /// /// Mod that colours s based on the musical division they are on /// - public class OsuModSnapColour : ModSnapColour, IApplicableToBeatmap, IApplicableToDrawableHitObject + public class OsuModSynesthesia : ModSynesthesia, IApplicableToBeatmap, IApplicableToDrawableHitObject { private readonly OsuColour colours = new OsuColour(); @@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - if (currentBeatmap.IsNull() || drawable.IsNull()) return; + if (currentBeatmap == null) return; drawable.OnUpdate += _ => drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor( diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 23eea0e488..c05e640022 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -176,7 +176,6 @@ namespace osu.Game.Rulesets.Osu new OsuModClassic(), new OsuModRandom(), new OsuModMirror(), - new OsuModSnapColour(), new MultiMod(new OsuModAlternate(), new OsuModSingleTap()) }; @@ -205,7 +204,8 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new OsuModMagnetised(), new OsuModRepel()), new ModAdaptiveSpeed(), new OsuModFreezeFrame(), - new OsuModBubbles() + new OsuModBubbles(), + new OsuModSynesthesia() }; case ModType.System: diff --git a/osu.Game/Rulesets/Mods/ModSnapColour.cs b/osu.Game/Rulesets/Mods/ModSynesthesia.cs similarity index 71% rename from osu.Game/Rulesets/Mods/ModSnapColour.cs rename to osu.Game/Rulesets/Mods/ModSynesthesia.cs index d7e51d8cf6..23cb135c50 100644 --- a/osu.Game/Rulesets/Mods/ModSnapColour.cs +++ b/osu.Game/Rulesets/Mods/ModSynesthesia.cs @@ -8,12 +8,12 @@ namespace osu.Game.Rulesets.Mods /// /// Mod that colours hitobjects based on the musical division they are on /// - public class ModSnapColour : Mod + public class ModSynesthesia : Mod { - public override string Name => "Snap Colour"; - public override string Acronym => "SC"; + public override string Name => "Synesthesia"; + public override string Acronym => "SY"; public override LocalisableString Description => "Colours hit objects based on the rhythm."; public override double ScoreMultiplier => 1; - public override ModType Type => ModType.Conversion; + public override ModType Type => ModType.Fun; } } From 7acd186a3d78a6e2ae99446eaf8d8dd89c2dbb8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 09:56:39 +0200 Subject: [PATCH 1139/1400] Revert to previous bound in drum roll tick generation While `EndTime + tickSpacing` _was_ closer to what stable was using, it could cause undesirable edge cases wherein a tick would be spawned outside of the drum roll's duration (see https://github.com/ppy/osu/pull/23768/files#r1222073027). For this reason, stick with the old code for now, as it is not as susceptible to that sort of breakage. --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 5b77ad7f91..79d17b4a1f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects bool first = true; - for (double t = StartTime; t < EndTime + tickSpacing; t += tickSpacing) + for (double t = StartTime; t < EndTime + tickSpacing / 2; t += tickSpacing) { cancellationToken.ThrowIfCancellationRequested(); From 079e687bee87b39fdd104a78661e893ef2ac6c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 10:09:27 +0200 Subject: [PATCH 1140/1400] Fix incorrect mock setup after refactor --- osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs index 3092966a7e..3d1f7c5b17 100644 --- a/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs +++ b/osu.Game.Tests/Editing/Checks/CheckBackgroundQualityTest.cs @@ -131,7 +131,7 @@ namespace osu.Game.Tests.Editing.Checks var mock = new Mock(); mock.SetupGet(w => w.Beatmap).Returns(beatmap); - mock.SetupGet(w => w.GetBackground()).Returns(background); + mock.Setup(w => w.GetBackground()).Returns(background); mock.Setup(w => w.GetStream(It.IsAny())).Returns(stream); return mock; From 10c43d22739b6c83006977c0d9aa92fb98372cb5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 17:27:00 +0900 Subject: [PATCH 1141/1400] Reduce delays and fades for carousel panels to improve song select initial display performance Entering song select has seen a hit since the new renderer implementations. The underlying cause is large numbers of vertex buffer uploads (the counter hits >200k for me during the transition). Song select is in the process of being redesigned, and we are probably going to make improvements to the renderer to alleviate this, but in the mean time we can greatly improve the user experience by reducing how long the initial fade in delays take on panels. Visually this doesn't look too jarring, and gives a more immediate feeling when scrolling. It's also more feasible to load elements sooner with https://github.com/ppy/osu/pull/23809 applied. --- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index b97d37c854..4234184ad1 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -112,11 +112,11 @@ namespace osu.Game.Screens.Select.Carousel background = new DelayedLoadWrapper(() => new SetPanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.MinBy(b => b.OnlineID))) { RelativeSizeAxes = Axes.Both, - }, 300) + }, 200) { RelativeSizeAxes = Axes.Both }, - mainFlow = new DelayedLoadWrapper(() => new SetPanelContent((CarouselBeatmapSet)Item), 100) + mainFlow = new DelayedLoadWrapper(() => new SetPanelContent((CarouselBeatmapSet)Item), 50) { RelativeSizeAxes = Axes.Both }, @@ -126,7 +126,7 @@ namespace osu.Game.Screens.Select.Carousel mainFlow.DelayedLoadComplete += fadeContentIn; } - private void fadeContentIn(Drawable d) => d.FadeInFromZero(750, Easing.OutQuint); + private void fadeContentIn(Drawable d) => d.FadeInFromZero(150); protected override void Deselected() { From 95ad18ed2ea65cf312ec098c5f79be921beec3bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 17:44:32 +0900 Subject: [PATCH 1142/1400] Reduce the radius of note-to-note snapping in osu! editor Stable uses `0.15f`, but for whatever reason that feels too large still. I've ballparked this. Addresses https://github.com/ppy/osu/discussions/23806. --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index ad6af6d74e..aac5f6ffb1 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -187,7 +187,7 @@ namespace osu.Game.Rulesets.Osu.Edit var playfield = PlayfieldAtScreenSpacePosition(screenSpacePosition); float snapRadius = - playfield.GamefieldToScreenSpace(new Vector2(OsuHitObject.OBJECT_RADIUS / 5)).X - + playfield.GamefieldToScreenSpace(new Vector2(OsuHitObject.OBJECT_RADIUS * 0.10f)).X - playfield.GamefieldToScreenSpace(Vector2.Zero).X; foreach (var b in blueprints) From 2958ce35be318ddec498e3c430f0725231291985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 13:19:47 +0200 Subject: [PATCH 1143/1400] Adjust object snapping test cases to pass with new radius --- .../Editor/TestSceneObjectObjectSnap.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs index 3b8a5a90a5..9af1855167 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneObjectObjectSnap.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("place first object", () => InputManager.Click(MouseButton.Left)); - AddStep("move mouse slightly", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.02f, 0))); + AddStep("move mouse slightly", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.01f, 0))); AddStep("place second object", () => InputManager.Click(MouseButton.Left)); @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("enter circle placement mode", () => InputManager.Key(Key.Number2)); - AddStep("move mouse slightly", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.235f, 0))); + AddStep("move mouse slightly", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.205f, 0))); AddStep("place second object", () => InputManager.Click(MouseButton.Left)); @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddStep("begin drag", () => InputManager.PressButton(MouseButton.Left)); - AddStep("move mouse slightly off centre", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.02f, 0))); + AddStep("move mouse slightly off centre", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * 0.01f, 0))); AddAssert("object 3 snapped to 1", () => { @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor return Precision.AlmostEquals(first.EndPosition, third.Position); }); - AddStep("move mouse slightly off centre", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * -0.22f, playfield.ScreenSpaceDrawQuad.Width * 0.21f))); + AddStep("move mouse slightly off centre", () => InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre + new Vector2(playfield.ScreenSpaceDrawQuad.Width * -0.21f, playfield.ScreenSpaceDrawQuad.Width * 0.205f))); AddAssert("object 2 snapped to 1", () => { From dbb7ddac5238e667a1a1ba99268e41b3d80af0e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 20:55:09 +0900 Subject: [PATCH 1144/1400] Change osu!mania scoring ratio to 99% acc (to match previous lazer scoring) --- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 3341f834dd..6292ed75cd 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -18,8 +18,8 @@ namespace osu.Game.Rulesets.Mania.Scoring protected override double ComputeTotalScore(double comboProgress, double accuracyProgress, double bonusPortion) { - return 200000 * comboProgress - + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyProgress + return 10000 * comboProgress + + 990000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyProgress + bonusPortion; } From ff4d376c84871b7b2307e7fe6d1c40bbbc17acbf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 21:01:05 +0900 Subject: [PATCH 1145/1400] Mark relevant components as `internal` --- osu.Game/Beatmaps/IBeatmapResourceProvider.cs | 2 +- osu.Game/Beatmaps/IWorkingBeatmap.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs index d033608c95..9e79e03785 100644 --- a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs +++ b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs @@ -9,7 +9,7 @@ using osu.Game.IO; namespace osu.Game.Beatmaps { - public interface IBeatmapResourceProvider : IStorageResourceProvider + internal interface IBeatmapResourceProvider : IStorageResourceProvider { /// /// Retrieve a global large texture store, used for loading beatmap backgrounds. diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 905bca45b3..dc69a7f776 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -32,12 +32,12 @@ namespace osu.Game.Beatmaps /// /// Whether the Beatmap has finished loading. /// - public bool BeatmapLoaded { get; } + bool BeatmapLoaded { get; } /// /// Whether the Track has finished loading. /// - public bool TrackLoaded { get; } + bool TrackLoaded { get; } /// /// Retrieves the which this represents. @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps /// /// Retrieves a cropped background for this used for display on panels. /// - Texture GetPanelBackground(); + internal Texture GetPanelBackground(); /// /// Retrieves the for the of this . @@ -129,12 +129,12 @@ namespace osu.Game.Beatmaps /// /// Beings loading the contents of this asynchronously. /// - public void BeginAsyncLoad(); + void BeginAsyncLoad(); /// /// Cancels the asynchronous loading of the contents of this . /// - public void CancelAsyncLoad(); + void CancelAsyncLoad(); /// /// Reads the correct track restart point from beatmap metadata and sets looping to enabled. From cccc06de4873afd0522bea33687c259b385cf8d4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 8 Jun 2023 21:10:40 +0900 Subject: [PATCH 1146/1400] Fix potential failure if beatmap background isn't tall enough --- .../Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index 0ee516a912..ef5de4d9b2 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -18,7 +18,7 @@ namespace osu.Game.Beatmaps public class BeatmapPanelBackgroundTextureLoaderStore : IResourceStore { // These numbers are taken from the draw visualiser size requirements for song select panel textures at extreme aspect ratios. - private const int height = 130; + private const int max_height = 130; private const int max_width = 1280; private readonly IResourceStore? textureStore; @@ -67,13 +67,14 @@ namespace osu.Game.Beatmaps Size size = image.Size(); int usableWidth = Math.Min(max_width, size.Width); + int usableHeight = Math.Min(max_height, size.Height); // Crop the centre region of the background for now. Rectangle cropRectangle = new Rectangle( (size.Width - usableWidth) / 2, - size.Height / 2 - height / 2, + (size.Height - usableHeight) / 3, usableWidth, - height + usableHeight ); image.Mutate(i => i.Crop(cropRectangle)); From 6dbf02454f0f7c2dee97aea8c01ea5120e676cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 14:19:34 +0200 Subject: [PATCH 1147/1400] Fix bad math --- osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index ef5de4d9b2..6d5b90521e 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -72,7 +72,7 @@ namespace osu.Game.Beatmaps // Crop the centre region of the background for now. Rectangle cropRectangle = new Rectangle( (size.Width - usableWidth) / 2, - (size.Height - usableHeight) / 3, + (size.Height - usableHeight) / 2, usableWidth, usableHeight ); From facf7de053a63b4155bff561b8ffede50573c561 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 8 Jun 2023 21:24:40 +0900 Subject: [PATCH 1148/1400] Parse ScoreInfo.IsLegacyScore from replays --- osu.Game/Database/RealmAccess.cs | 49 ++++++++++++++++++- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 3 ++ osu.Game/Scoring/ScoreInfo.cs | 3 +- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index f4c6c802f1..21e025c79d 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -22,12 +22,15 @@ using osu.Framework.Statistics; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Input.Bindings; +using osu.Game.IO.Legacy; using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; +using osu.Game.Scoring.Legacy; using osu.Game.Skinning; using Realms; using Realms.Exceptions; @@ -72,8 +75,9 @@ namespace osu.Game.Database /// 25 2022-09-18 Remove skins to add with new naming. /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. /// 27 2023-06-06 Added EditorTimestamp to BeatmapInfo. + /// 28 2023-06-08 Added IsLegacyScore to ScoreInfo, parsed from replay files. /// - private const int schema_version = 27; + private const int schema_version = 28; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. @@ -880,6 +884,7 @@ namespace osu.Game.Database break; case 26: + { // Add ScoreInfo.BeatmapHash property to ensure scores correspond to the correct version of beatmap. var scores = migration.NewRealm.All(); @@ -887,6 +892,33 @@ namespace osu.Game.Database score.BeatmapHash = score.BeatmapInfo.Hash; break; + } + + case 28: + { + var files = new RealmFileStore(this, storage); + var scores = migration.NewRealm.All(); + + foreach (var score in scores) + { + string? replayFilename = score.Files.FirstOrDefault(f => f.Filename.EndsWith(@".osr", StringComparison.InvariantCultureIgnoreCase))?.File.GetStoragePath(); + + if (replayFilename == null) + continue; + + using (var stream = files.Store.GetStream(replayFilename)) + { + if (stream == null) + continue; + + int version = new ReplayVersionParser().Parse(stream); + if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) + score.IsLegacyScore = true; + } + } + + break; + } } } @@ -1107,5 +1139,20 @@ namespace osu.Game.Database isDisposed = true; } } + + /// + /// A trimmed down specialised to extract the version from replays. + /// + private class ReplayVersionParser + { + public int Parse(Stream stream) + { + using (SerializationReader sr = new SerializationReader(stream)) + { + sr.ReadByte(); // Ruleset. + return sr.ReadInt32(); + } + } + } } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 9b145ad56e..c6461840aa 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -46,6 +46,9 @@ namespace osu.Game.Scoring.Legacy score.ScoreInfo = scoreInfo; int version = sr.ReadInt32(); + + scoreInfo.IsLegacyScore = version < LegacyScoreEncoder.FIRST_LAZER_VERSION; + string beatmapHash = sr.ReadString(); workingBeatmap = GetBeatmap(beatmapHash); diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index e084c45de0..d56338c6a4 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -181,8 +181,7 @@ namespace osu.Game.Scoring /// /// Whether this represents a legacy (osu!stable) score. /// - [Ignored] - public bool IsLegacyScore => Mods.OfType().Any(); + public bool IsLegacyScore { get; set; } private Dictionary? statistics; From 76df11c39843f92b4bc305b07a8ee77a08b9067a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 8 Jun 2023 21:26:32 +0900 Subject: [PATCH 1149/1400] Don't scale stable scores with the classic scoring mode --- osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index 84bf6d15f6..52dec20b32 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -16,7 +16,13 @@ namespace osu.Game.Scoring.Legacy => getDisplayScore(scoreProcessor.Ruleset.RulesetInfo.OnlineID, scoreProcessor.TotalScore.Value, mode, scoreProcessor.MaximumStatistics); public static long GetDisplayScore(this ScoreInfo scoreInfo, ScoringMode mode) - => getDisplayScore(scoreInfo.Ruleset.OnlineID, scoreInfo.TotalScore, mode, scoreInfo.MaximumStatistics); + { + // Temporary to not scale stable scores that are already in the XX-millions with the classic scoring mode. + if (scoreInfo.IsLegacyScore) + return scoreInfo.TotalScore; + + return getDisplayScore(scoreInfo.Ruleset.OnlineID, scoreInfo.TotalScore, mode, scoreInfo.MaximumStatistics); + } private static long getDisplayScore(int rulesetId, long score, ScoringMode mode, IReadOnlyDictionary maximumStatistics) { From 05bd912a21c3b18159199fdf0ac5e4038f0f69a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 15:18:31 +0200 Subject: [PATCH 1150/1400] Revert `internal` access modifier application Unfortunately breaks a few classes (which is fixable), and also breaks Moq/Castle dynamic proxies (which is unfortunate). Relevant error: System.TypeLoadException : Method 'GetPanelBackground' in type 'Castle.Proxies.IWorkingBeatmapProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation. Stack Trace: at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() at System.Reflection.Emit.TypeBuilder.CreateTypeInfo() at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType() at Castle.DynamicProxy.Generators.BaseInterfaceProxyGenerator.GenerateType(String typeName, INamingScope namingScope) at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass13_0.b__0(CacheKey cacheKey) at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Castle.DynamicProxy.Generators.BaseProxyGenerator.GetProxyType() at Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors) at Moq.CastleProxyFactory.CreateProxy(Type mockType, IInterceptor interceptor, Type[] interfaces, Object[] arguments) in C:\projects\moq4\src\Moq\Interception\CastleProxyFactory.cs:line 50 In theory it would be possible to fix this via application of [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] onto the `osu.Game` assembly, but I think this would be bad precedent. --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index dc69a7f776..bdfa6bdf6d 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -52,7 +52,7 @@ namespace osu.Game.Beatmaps /// /// Retrieves a cropped background for this used for display on panels. /// - internal Texture GetPanelBackground(); + Texture GetPanelBackground(); /// /// Retrieves the for the of this . From 46dc47b0b4254a9b90f00ab2b68c540b7ee94685 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 01:22:29 +0900 Subject: [PATCH 1151/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c88bea8265..f4d08e443c 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8a941ca6c1..b2faa7dfc2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 1dcece7741..9aafec6c50 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 0875fc6233475969d1bb72dbc4f3fb5bcfa98be6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 17:12:00 +0900 Subject: [PATCH 1152/1400] Update tests in line with new behaviour --- .../Visual/Editing/TestSceneBeatDivisorControl.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs index 3ee5ea79db..17cb3c1449 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBeatDivisorControl.cs @@ -161,9 +161,11 @@ namespace osu.Game.Tests.Visual.Editing switchPresets(1); assertPreset(BeatDivisorType.Triplets); + assertBeatSnap(6); switchPresets(1); assertPreset(BeatDivisorType.Common); + assertBeatSnap(4); switchPresets(-1); assertPreset(BeatDivisorType.Triplets); @@ -179,6 +181,7 @@ namespace osu.Game.Tests.Visual.Editing setDivisorViaInput(15); assertPreset(BeatDivisorType.Custom, 15); + assertBeatSnap(15); switchBeatSnap(-1); assertBeatSnap(5); @@ -188,12 +191,14 @@ namespace osu.Game.Tests.Visual.Editing setDivisorViaInput(5); assertPreset(BeatDivisorType.Custom, 15); + assertBeatSnap(5); switchPresets(1); assertPreset(BeatDivisorType.Common); switchPresets(-1); - assertPreset(BeatDivisorType.Triplets); + assertPreset(BeatDivisorType.Custom, 15); + assertBeatSnap(15); } private void switchBeatSnap(int direction) => AddRepeatStep($"move snap {(direction > 0 ? "forward" : "backward")}", () => @@ -217,7 +222,7 @@ namespace osu.Game.Tests.Visual.Editing private void assertPreset(BeatDivisorType type, int? maxDivisor = null) { - AddAssert($"preset is {type}", () => bindableBeatDivisor.ValidDivisors.Value.Type == type); + AddAssert($"preset is {type}", () => bindableBeatDivisor.ValidDivisors.Value.Type, () => Is.EqualTo(type)); if (type == BeatDivisorType.Custom) { From b66d1aa33d08539cdbb0e859d8d2c2d3380be2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 8 Jun 2023 20:32:16 +0200 Subject: [PATCH 1153/1400] Fix code quality inspection --- osu.Game/Screens/Edit/EditorScreenWithTimeline.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 84cfac8f65..b8cbff047e 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -82,7 +82,7 @@ namespace osu.Game.Screens.Edit AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Right = 5 }, }, - new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } + new BeatDivisorControl(this.beatDivisor) { RelativeSizeAxes = Axes.Both } }, }, RowDimensions = new[] From 519923e843ea2fd2e98a9f2afa88106a48b83568 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 8 Jun 2023 17:09:20 -0700 Subject: [PATCH 1154/1400] Remove redundant `EllipsisString` assign --- osu.Game/Overlays/Chat/DrawableChatUsername.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 4b4afc204c..46e3ff5b37 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -87,7 +87,6 @@ namespace osu.Game.Overlays.Chat { Shadow = false, Truncate = true, - EllipsisString = "…", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }; From 85fedbd02555618be2892688d2b121ae7e0c1843 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Thu, 8 Jun 2023 17:11:17 -0700 Subject: [PATCH 1155/1400] Add tooltips to truncated text --- .../Drawables/Cards/BeatmapCardExtra.cs | 9 +++------ .../Drawables/Cards/BeatmapCardNormal.cs | 6 ++---- .../Graphics/Sprites/TruncatingSpriteText.cs | 20 +++++++++++++++++++ .../Graphics/UserInterface/OsuDropdown.cs | 3 +-- .../Chat/ChannelList/ChannelListItem.cs | 3 +-- osu.Game/Overlays/Chat/ChatTextBar.cs | 3 +-- .../Overlays/Chat/DrawableChatUsername.cs | 3 +-- .../Dashboard/Home/DashboardBeatmapPanel.cs | 6 ++---- .../Play/HUD/GameplayLeaderboardScore.cs | 3 +-- .../Expanded/ExpandedPanelMiddleContent.cs | 9 +++------ osu.Game/Screens/Select/BeatmapInfoWedge.cs | 9 +++------ 11 files changed, 38 insertions(+), 36 deletions(-) create mode 100644 osu.Game/Graphics/Sprites/TruncatingSpriteText.cs diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 5c6f0c4ee1..175c15ea7b 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -106,12 +106,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new Drawable[] { - new OsuSpriteText + new TruncatingSpriteText { Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title), Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true }, titleBadgeArea = new FillFlowContainer { @@ -140,21 +139,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new[] { - new OsuSpriteText + new TruncatingSpriteText { Text = createArtistText(), Font = OsuFont.Default.With(size: 17.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true }, Empty() }, } }, - new OsuSpriteText + new TruncatingSpriteText { RelativeSizeAxes = Axes.X, - Truncate = true, Text = BeatmapSet.Source, Shadow = false, Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs index 720d892495..18e1584a98 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs @@ -107,12 +107,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new Drawable[] { - new OsuSpriteText + new TruncatingSpriteText { Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title), Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true }, titleBadgeArea = new FillFlowContainer { @@ -141,12 +140,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new[] { - new OsuSpriteText + new TruncatingSpriteText { Text = createArtistText(), Font = OsuFont.Default.With(size: 17.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true }, Empty() }, diff --git a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs new file mode 100644 index 0000000000..da0dbd49d2 --- /dev/null +++ b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Cursor; +using osu.Framework.Localisation; + +namespace osu.Game.Graphics.Sprites +{ + public sealed partial class TruncatingSpriteText : OsuSpriteText, IHasTooltip + { + public LocalisableString TooltipText => Text; + + public override bool HandlePositionalInput => IsTruncated; + + public TruncatingSpriteText() + { + Truncate = true; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 3230bb0569..b530172f3e 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -335,12 +335,11 @@ namespace osu.Game.Graphics.UserInterface { new Drawable[] { - Text = new OsuSpriteText + Text = new TruncatingSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, RelativeSizeAxes = Axes.X, - Truncate = true, }, Icon = new SpriteIcon { diff --git a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs index 57b6f6268c..21b6147113 100644 --- a/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelList/ChannelListItem.cs @@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Chat.ChannelList new Drawable?[] { createIcon(), - text = new OsuSpriteText + text = new TruncatingSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -94,7 +94,6 @@ namespace osu.Game.Overlays.Chat.ChannelList Colour = colourProvider.Light3, Margin = new MarginPadding { Bottom = 2 }, RelativeSizeAxes = Axes.X, - Truncate = true, }, createMentionPill(), close = createCloseButton(), diff --git a/osu.Game/Overlays/Chat/ChatTextBar.cs b/osu.Game/Overlays/Chat/ChatTextBar.cs index fd5e0e9836..87e787fcb8 100644 --- a/osu.Game/Overlays/Chat/ChatTextBar.cs +++ b/osu.Game/Overlays/Chat/ChatTextBar.cs @@ -73,14 +73,13 @@ namespace osu.Game.Overlays.Chat Width = chatting_text_width, Masking = true, Padding = new MarginPadding { Horizontal = padding }, - Child = chattingText = new OsuSpriteText + Child = chattingText = new TruncatingSpriteText { MaxWidth = chatting_text_width - padding * 2, Font = OsuFont.Torus.With(size: 20), Colour = colourProvider.Background1, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Truncate = true, }, }, searchIconContainer = new Container diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 46e3ff5b37..18632aa4af 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -83,10 +83,9 @@ namespace osu.Game.Overlays.Chat Action = openUserProfile; - drawableText = new OsuSpriteText + drawableText = new TruncatingSpriteText { Shadow = false, - Truncate = true, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs index 792d6cc785..f36e6b49bb 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapPanel.cs @@ -100,17 +100,15 @@ namespace osu.Game.Overlays.Dashboard.Home Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuSpriteText + new TruncatingSpriteText { RelativeSizeAxes = Axes.X, - Truncate = true, Font = OsuFont.GetFont(weight: FontWeight.Regular), Text = BeatmapSet.Title }, - new OsuSpriteText + new TruncatingSpriteText { RelativeSizeAxes = Axes.X, - Truncate = true, Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Text = BeatmapSet.Artist }, diff --git a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs index 4ac2f1afda..dcb2c1071e 100644 --- a/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs +++ b/osu.Game/Screens/Play/HUD/GameplayLeaderboardScore.cs @@ -235,7 +235,7 @@ namespace osu.Game.Screens.Play.HUD } } }, - usernameText = new OsuSpriteText + usernameText = new TruncatingSpriteText { RelativeSizeAxes = Axes.X, Width = 0.6f, @@ -244,7 +244,6 @@ namespace osu.Game.Screens.Play.HUD Colour = Color4.White, Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), Text = User?.Username ?? string.Empty, - Truncate = true, Shadow = false, } } diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index f23b469f5c..fe74c1ba0d 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -101,23 +101,21 @@ namespace osu.Game.Screens.Ranking.Expanded Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuSpriteText + new TruncatingSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new RomanisableString(metadata.TitleUnicode, metadata.Title), Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, - Truncate = true, }, - new OsuSpriteText + new TruncatingSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = new RomanisableString(metadata.ArtistUnicode, metadata.Artist), Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, - Truncate = true, }, new Container { @@ -156,14 +154,13 @@ namespace osu.Game.Screens.Ranking.Expanded AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new OsuSpriteText + new TruncatingSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = beatmap.DifficultyName, Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold), MaxWidth = ScorePanel.EXPANDED_WIDTH - padding * 2, - Truncate = true, }, new OsuTextFlowContainer(s => s.Font = OsuFont.Torus.With(size: 12)) { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 2102df1022..961f8684ce 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -233,12 +233,11 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Children = new Drawable[] { - VersionLabel = new OsuSpriteText + VersionLabel = new TruncatingSpriteText { Text = beatmapInfo.DifficultyName, Font = OsuFont.GetFont(size: 24, italics: true), RelativeSizeAxes = Axes.X, - Truncate = true, }, } }, @@ -286,19 +285,17 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Children = new Drawable[] { - TitleLabel = new OsuSpriteText + TitleLabel = new TruncatingSpriteText { Current = { BindTarget = titleBinding }, Font = OsuFont.GetFont(size: 28, italics: true), RelativeSizeAxes = Axes.X, - Truncate = true, }, - ArtistLabel = new OsuSpriteText + ArtistLabel = new TruncatingSpriteText { Current = { BindTarget = artistBinding }, Font = OsuFont.GetFont(size: 17, italics: true), RelativeSizeAxes = Axes.X, - Truncate = true, }, MapperContainer = new FillFlowContainer { From 67562a38568ff7ded79ec7bacaa4faedea31de97 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 9 Jun 2023 14:35:29 +0900 Subject: [PATCH 1156/1400] Catch errors during score parsing --- osu.Game/Database/RealmAccess.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 21e025c79d..493987733b 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -911,9 +911,16 @@ namespace osu.Game.Database if (stream == null) continue; - int version = new ReplayVersionParser().Parse(stream); - if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) - score.IsLegacyScore = true; + try + { + int version = new ReplayVersionParser().Parse(stream); + if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) + score.IsLegacyScore = true; + } + catch (Exception e) + { + Logger.Error(e, $"Failed to read replay {replayFilename}", LoggingTarget.Database); + } } } From 1ab3b43b593fdc06e1d8b987636047824fffa128 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 14:36:17 +0900 Subject: [PATCH 1157/1400] Fix weird right-toolbox distance snapping display in osu!catch editor --- .../Edit/DistancedHitObjectComposer.cs | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs index a8972775de..817e8bd5fe 100644 --- a/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/DistancedHitObjectComposer.cs @@ -125,6 +125,7 @@ namespace osu.Game.Rulesets.Edit if (currentSnap > DistanceSpacingMultiplier.MinValue) { currentDistanceSpacingButton.Enabled.Value = currentDistanceSpacingButton.Expanded.Value + && !DistanceSpacingMultiplier.Disabled && !Precision.AlmostEquals(currentSnap, DistanceSpacingMultiplier.Value, DistanceSpacingMultiplier.Precision / 2); currentDistanceSpacingButton.ContractedLabelText = $"current {currentSnap:N2}x"; currentDistanceSpacingButton.ExpandedLabelText = $"Use current ({currentSnap:N2}x)"; @@ -141,28 +142,31 @@ namespace osu.Game.Rulesets.Edit { base.LoadComplete(); - if (!DistanceSpacingMultiplier.Disabled) + if (DistanceSpacingMultiplier.Disabled) { - DistanceSpacingMultiplier.Value = EditorBeatmap.BeatmapInfo.DistanceSpacing; - DistanceSpacingMultiplier.BindValueChanged(multiplier => - { - distanceSpacingSlider.ContractedLabelText = $"D. S. ({multiplier.NewValue:0.##x})"; - distanceSpacingSlider.ExpandedLabelText = $"Distance Spacing ({multiplier.NewValue:0.##x})"; - - if (multiplier.NewValue != multiplier.OldValue) - onScreenDisplay?.Display(new DistanceSpacingToast(multiplier.NewValue.ToLocalisableString(@"0.##x"), multiplier)); - - EditorBeatmap.BeatmapInfo.DistanceSpacing = multiplier.NewValue; - }, true); - - // Manual binding to handle enabling distance spacing when the slider is interacted with. - distanceSpacingSlider.Current.BindValueChanged(spacing => - { - DistanceSpacingMultiplier.Value = spacing.NewValue; - DistanceSnapToggle.Value = TernaryState.True; - }); - DistanceSpacingMultiplier.BindValueChanged(spacing => distanceSpacingSlider.Current.Value = spacing.NewValue); + distanceSpacingSlider.Hide(); + return; } + + DistanceSpacingMultiplier.Value = EditorBeatmap.BeatmapInfo.DistanceSpacing; + DistanceSpacingMultiplier.BindValueChanged(multiplier => + { + distanceSpacingSlider.ContractedLabelText = $"D. S. ({multiplier.NewValue:0.##x})"; + distanceSpacingSlider.ExpandedLabelText = $"Distance Spacing ({multiplier.NewValue:0.##x})"; + + if (multiplier.NewValue != multiplier.OldValue) + onScreenDisplay?.Display(new DistanceSpacingToast(multiplier.NewValue.ToLocalisableString(@"0.##x"), multiplier)); + + EditorBeatmap.BeatmapInfo.DistanceSpacing = multiplier.NewValue; + }, true); + + // Manual binding to handle enabling distance spacing when the slider is interacted with. + distanceSpacingSlider.Current.BindValueChanged(spacing => + { + DistanceSpacingMultiplier.Value = spacing.NewValue; + DistanceSnapToggle.Value = TernaryState.True; + }); + DistanceSpacingMultiplier.BindValueChanged(spacing => distanceSpacingSlider.Current.Value = spacing.NewValue); } protected override IEnumerable CreateTernaryButtons() => base.CreateTernaryButtons().Concat(new[] From df874b9ae8445c8daea597918c058e6fc784faa6 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 9 Jun 2023 09:16:05 +0300 Subject: [PATCH 1158/1400] Fix beatmap panel background looking different than usual --- .../Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index 6d5b90521e..8f70f8a04f 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -66,7 +66,10 @@ namespace osu.Game.Beatmaps textureUpload.Dispose(); Size size = image.Size(); - int usableWidth = Math.Min(max_width, size.Width); + + float aspectRatio = (float)size.Width / size.Height; + + int usableWidth = Math.Min((int)(max_width * aspectRatio), size.Width); int usableHeight = Math.Min(max_height, size.Height); // Crop the centre region of the background for now. From 78b2e6f3df1a95c83e800258594eae71862f1821 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 15:54:22 +0900 Subject: [PATCH 1159/1400] Add setting to limit distance snapping to current time As discussed in https://github.com/ppy/osu/discussions/23815#discussioncomment-6124116. --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Localisation/EditorStrings.cs | 5 +++++ .../Compose/Components/CircularDistanceSnapGrid.cs | 7 +++++++ .../Edit/Compose/Components/DistanceSnapGrid.cs | 13 +++++++++++++ osu.Game/Screens/Edit/Editor.cs | 6 ++++++ 5 files changed, 33 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 365ad37f4c..193068193a 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -178,6 +178,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.EditorWaveformOpacity, 0.25f, 0f, 1f, 0.25f); SetDefault(OsuSetting.EditorShowHitMarkers, true); SetDefault(OsuSetting.EditorAutoSeekOnPlacement, true); + SetDefault(OsuSetting.EditorLimitedDistanceSnap, false); SetDefault(OsuSetting.LastProcessedMetadataId, -1); @@ -383,5 +384,6 @@ namespace osu.Game.Configuration SafeAreaConsiderations, ComboColourNormalisationAmount, ProfileCoverExpanded, + EditorLimitedDistanceSnap } } diff --git a/osu.Game/Localisation/EditorStrings.cs b/osu.Game/Localisation/EditorStrings.cs index 20258b9c35..077bd92d4f 100644 --- a/osu.Game/Localisation/EditorStrings.cs +++ b/osu.Game/Localisation/EditorStrings.cs @@ -109,6 +109,11 @@ namespace osu.Game.Localisation /// public static LocalisableString RotationSnapped(float newRotation) => new TranslatableString(getKey(@"rotation_snapped"), @"{0:0}° (snapped)", newRotation); + /// + /// "Limit distance snap placement to current time" + /// + public static LocalisableString LimitedDistanceSnap => new TranslatableString(getKey(@"limited_distance_snap_grid"), @"Limit distance snap placement to current time"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index d6e4e1f030..2eec833832 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -18,6 +18,9 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract partial class CircularDistanceSnapGrid : DistanceSnapGrid { + [Resolved] + private EditorClock editorClock { get; set; } + protected CircularDistanceSnapGrid(HitObject referenceObject, Vector2 startPosition, double startTime, double? endTime = null) : base(referenceObject, startPosition, startTime, endTime) { @@ -98,9 +101,13 @@ namespace osu.Game.Screens.Edit.Compose.Components if (travelLength < DistanceBetweenTicks) travelLength = DistanceBetweenTicks; + if (LimitedDistanceSnap.Value) + travelLength = SnapProvider.DurationToDistance(ReferenceObject, editorClock.CurrentTime - ReferenceObject.GetEndTime()); + // When interacting with the resolved snap provider, the distance spacing multiplier should first be removed // to allow for snapping at a non-multiplied ratio. float snappedDistance = SnapProvider.FindSnappedDistance(ReferenceObject, travelLength / distanceSpacingMultiplier); + double snappedTime = StartTime + SnapProvider.DistanceToDuration(ReferenceObject, snappedDistance); if (snappedTime > LatestEndTime) diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 6092ebc08f..9882f6596f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -10,6 +10,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Layout; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -60,6 +61,18 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private BindableBeatDivisor beatDivisor { get; set; } + /// + /// When enabled, distance snap should only snap to the current time (as per the editor clock). + /// This is to emulate stable behaviour. + /// + protected Bindable LimitedDistanceSnap; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + LimitedDistanceSnap = config.GetBindable(OsuSetting.EditorLimitedDistanceSnap); + } + private readonly LayoutValue gridCache = new LayoutValue(Invalidation.RequiredParentSizeToFit); protected readonly HitObject ReferenceObject; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index bb052b1d22..a5097916cc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -185,6 +185,7 @@ namespace osu.Game.Screens.Edit private Bindable editorBackgroundDim; private Bindable editorHitMarkers; private Bindable editorAutoSeekOnPlacement; + private Bindable editorLimitedDistanceSnap; public Editor(EditorLoader loader = null) { @@ -276,6 +277,7 @@ namespace osu.Game.Screens.Edit editorBackgroundDim = config.GetBindable(OsuSetting.EditorDim); editorHitMarkers = config.GetBindable(OsuSetting.EditorShowHitMarkers); editorAutoSeekOnPlacement = config.GetBindable(OsuSetting.EditorAutoSeekOnPlacement); + editorLimitedDistanceSnap = config.GetBindable(OsuSetting.EditorLimitedDistanceSnap); AddInternal(new OsuContextMenuContainer { @@ -337,6 +339,10 @@ namespace osu.Game.Screens.Edit new ToggleMenuItem(EditorStrings.AutoSeekOnPlacement) { State = { BindTarget = editorAutoSeekOnPlacement }, + }, + new ToggleMenuItem(EditorStrings.LimitedDistanceSnap) + { + State = { BindTarget = editorLimitedDistanceSnap }, } } }, From a9071e7afd554c6e1c25fe606277e3f188700b25 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 17:33:59 +0900 Subject: [PATCH 1160/1400] try-catch more --- osu.Game/Database/RealmAccess.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 493987733b..048ff43f0a 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -902,25 +902,24 @@ namespace osu.Game.Database foreach (var score in scores) { string? replayFilename = score.Files.FirstOrDefault(f => f.Filename.EndsWith(@".osr", StringComparison.InvariantCultureIgnoreCase))?.File.GetStoragePath(); - if (replayFilename == null) continue; - using (var stream = files.Store.GetStream(replayFilename)) + try { - if (stream == null) - continue; - - try + using (var stream = files.Store.GetStream(replayFilename)) { + if (stream == null) + continue; + int version = new ReplayVersionParser().Parse(stream); if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) score.IsLegacyScore = true; } - catch (Exception e) - { - Logger.Error(e, $"Failed to read replay {replayFilename}", LoggingTarget.Database); - } + } + catch (Exception e) + { + Logger.Error(e, $"Failed to read replay {replayFilename}", LoggingTarget.Database); } } From 53f935714ea69df4e9114427939286665b22f1c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 17:34:27 +0900 Subject: [PATCH 1161/1400] Inline binary reading to avoid polluting `RealmAccess` with nested class --- osu.Game/Database/RealmAccess.cs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 048ff43f0a..50044cb8d9 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -912,9 +912,14 @@ namespace osu.Game.Database if (stream == null) continue; - int version = new ReplayVersionParser().Parse(stream); - if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) - score.IsLegacyScore = true; + // Trimmed down logic from LegacyScoreDecoder to extract the version from replays. + using (SerializationReader sr = new SerializationReader(stream)) + { + sr.ReadByte(); // Ruleset. + int version = sr.ReadInt32(); + if (version < LegacyScoreEncoder.FIRST_LAZER_VERSION) + score.IsLegacyScore = true; + } } } catch (Exception e) @@ -1145,20 +1150,5 @@ namespace osu.Game.Database isDisposed = true; } } - - /// - /// A trimmed down specialised to extract the version from replays. - /// - private class ReplayVersionParser - { - public int Parse(Stream stream) - { - using (SerializationReader sr = new SerializationReader(stream)) - { - sr.ReadByte(); // Ruleset. - return sr.ReadInt32(); - } - } - } } } From c2663f27a1bf742ef637a59346c018ace18126d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 17:58:44 +0900 Subject: [PATCH 1162/1400] Fix audio settings not displaying while watching a replay --- osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index 45b2c1b13c..064d2071ce 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -42,7 +42,8 @@ namespace osu.Game.Screens.Play.HUD //CollectionSettings = new CollectionSettings(), //DiscussionSettings = new DiscussionSettings(), PlaybackSettings = new PlaybackSettings { Expanded = { Value = false } }, - VisualSettings = new VisualSettings { Expanded = { Value = false } } + VisualSettings = new VisualSettings { Expanded = { Value = false } }, + new AudioSettings { Expanded = { Value = false } } } }; } From ca25ac446b76d7be944c7815c26ba74994bc5209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Jun 2023 11:20:12 +0200 Subject: [PATCH 1163/1400] Be slightly more specific with error message --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 50044cb8d9..63ab18db8c 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -924,7 +924,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, $"Failed to read replay {replayFilename}", LoggingTarget.Database); + Logger.Error(e, $"Failed to read replay {replayFilename} during score migration", LoggingTarget.Database); } } From 4685ba83e1da43d2251f0da670f8a9ba85f7a55f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 18:24:38 +0900 Subject: [PATCH 1164/1400] Apply NRT to `MemoryCachingComponent` classes --- osu.Game/Database/MemoryCachingComponent.cs | 17 +++++----- osu.Game/Database/OnlineLookupCache.cs | 31 ++++++++----------- osu.Game/Database/UserLookupCache.cs | 10 ++---- .../Online/API/Requests/GetUsersRequest.cs | 2 -- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/osu.Game/Database/MemoryCachingComponent.cs b/osu.Game/Database/MemoryCachingComponent.cs index 5d1a381f09..e98475efae 100644 --- a/osu.Game/Database/MemoryCachingComponent.cs +++ b/osu.Game/Database/MemoryCachingComponent.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Statistics; @@ -19,8 +17,9 @@ namespace osu.Game.Database /// Currently not persisted between game sessions. /// public abstract partial class MemoryCachingComponent : Component + where TLookup : notnull { - private readonly ConcurrentDictionary cache = new ConcurrentDictionary(); + private readonly ConcurrentDictionary cache = new ConcurrentDictionary(); private readonly GlobalStatistic statistics; @@ -37,12 +36,12 @@ namespace osu.Game.Database /// /// The lookup to retrieve. /// An optional to cancel the operation. - protected async Task GetAsync([NotNull] TLookup lookup, CancellationToken token = default) + protected async Task GetAsync(TLookup lookup, CancellationToken token = default) { - if (CheckExists(lookup, out TValue performance)) + if (CheckExists(lookup, out TValue? existing)) { statistics.Value.HitCount++; - return performance; + return existing; } var computed = await ComputeValueAsync(lookup, token).ConfigureAwait(false); @@ -73,7 +72,7 @@ namespace osu.Game.Database statistics.Value.Usage = cache.Count; } - protected bool CheckExists([NotNull] TLookup lookup, out TValue value) => + protected bool CheckExists(TLookup lookup, [MaybeNullWhen(false)] out TValue value) => cache.TryGetValue(lookup, out value); /// @@ -82,7 +81,7 @@ namespace osu.Game.Database /// The lookup to retrieve. /// An optional to cancel the operation. /// The computed value. - protected abstract Task ComputeValueAsync(TLookup lookup, CancellationToken token = default); + protected abstract Task ComputeValueAsync(TLookup lookup, CancellationToken token = default); private class MemoryCachingStatistics { diff --git a/osu.Game/Database/OnlineLookupCache.cs b/osu.Game/Database/OnlineLookupCache.cs index d9b37e2f29..3b54804fec 100644 --- a/osu.Game/Database/OnlineLookupCache.cs +++ b/osu.Game/Database/OnlineLookupCache.cs @@ -1,14 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Game.Online.API; @@ -21,7 +18,7 @@ namespace osu.Game.Database where TRequest : APIRequest { [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; /// /// Creates an to retrieve the values for a given collection of s. @@ -32,8 +29,7 @@ namespace osu.Game.Database /// /// Retrieves a list of s from a successful created by . /// - [CanBeNull] - protected abstract IEnumerable RetrieveResults(TRequest request); + protected abstract IEnumerable? RetrieveResults(TRequest request); /// /// Perform a lookup using the specified , populating a . @@ -41,8 +37,7 @@ namespace osu.Game.Database /// The ID to lookup. /// An optional cancellation token. /// The populated , or null if the value does not exist or the request could not be satisfied. - [ItemCanBeNull] - protected Task LookupAsync(TLookup id, CancellationToken token = default) => GetAsync(id, token); + protected Task LookupAsync(TLookup id, CancellationToken token = default) => GetAsync(id, token); /// /// Perform an API lookup on the specified , populating a . @@ -50,9 +45,9 @@ namespace osu.Game.Database /// The IDs to lookup. /// An optional cancellation token. /// The populated values. May include null results for failed retrievals. - protected Task LookupAsync(TLookup[] ids, CancellationToken token = default) + protected Task LookupAsync(TLookup[] ids, CancellationToken token = default) { - var lookupTasks = new List>(); + var lookupTasks = new List>(); foreach (var id in ids) { @@ -69,18 +64,18 @@ namespace osu.Game.Database } // cannot be sealed due to test usages (see TestUserLookupCache). - protected override async Task ComputeValueAsync(TLookup lookup, CancellationToken token = default) + protected override async Task ComputeValueAsync(TLookup lookup, CancellationToken token = default) => await queryValue(lookup).ConfigureAwait(false); - private readonly Queue<(TLookup id, TaskCompletionSource)> pendingTasks = new Queue<(TLookup, TaskCompletionSource)>(); - private Task pendingRequestTask; + private readonly Queue<(TLookup id, TaskCompletionSource)> pendingTasks = new Queue<(TLookup, TaskCompletionSource)>(); + private Task? pendingRequestTask; private readonly object taskAssignmentLock = new object(); - private Task queryValue(TLookup id) + private Task queryValue(TLookup id) { lock (taskAssignmentLock) { - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(); // Add to the queue. pendingTasks.Enqueue((id, tcs)); @@ -96,14 +91,14 @@ namespace osu.Game.Database private async Task performLookup() { // contains at most 50 unique IDs from tasks, which is used to perform the lookup. - var nextTaskBatch = new Dictionary>>(); + var nextTaskBatch = new Dictionary>>(); // Grab at most 50 unique IDs from the queue. lock (taskAssignmentLock) { while (pendingTasks.Count > 0 && nextTaskBatch.Count < 50) { - (TLookup id, TaskCompletionSource task) next = pendingTasks.Dequeue(); + (TLookup id, TaskCompletionSource task) next = pendingTasks.Dequeue(); // Perform a secondary check for existence, in case the value was queried in a previous batch. if (CheckExists(next.id, out var existing)) @@ -113,7 +108,7 @@ namespace osu.Game.Database if (nextTaskBatch.TryGetValue(next.id, out var tasks)) tasks.Add(next.task); else - nextTaskBatch[next.id] = new List> { next.task }; + nextTaskBatch[next.id] = new List> { next.task }; } } } diff --git a/osu.Game/Database/UserLookupCache.cs b/osu.Game/Database/UserLookupCache.cs index b1609fbf7b..e581d5ce82 100644 --- a/osu.Game/Database/UserLookupCache.cs +++ b/osu.Game/Database/UserLookupCache.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -21,8 +18,7 @@ namespace osu.Game.Database /// The user to lookup. /// An optional cancellation token. /// The populated user, or null if the user does not exist or the request could not be satisfied. - [ItemCanBeNull] - public Task GetUserAsync(int userId, CancellationToken token = default) => LookupAsync(userId, token); + public Task GetUserAsync(int userId, CancellationToken token = default) => LookupAsync(userId, token); /// /// Perform an API lookup on the specified users, populating a model. @@ -30,10 +26,10 @@ namespace osu.Game.Database /// The users to lookup. /// An optional cancellation token. /// The populated users. May include null results for failed retrievals. - public Task GetUsersAsync(int[] userIds, CancellationToken token = default) => LookupAsync(userIds, token); + public Task GetUsersAsync(int[] userIds, CancellationToken token = default) => LookupAsync(userIds, token); protected override GetUsersRequest CreateRequest(IEnumerable ids) => new GetUsersRequest(ids.ToArray()); - protected override IEnumerable RetrieveResults(GetUsersRequest request) => request.Response?.Users; + protected override IEnumerable? RetrieveResults(GetUsersRequest request) => request.Response?.Users; } } diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index b57bb215aa..6f7e9c07d2 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.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. -#nullable disable - using System; namespace osu.Game.Online.API.Requests From c5e77e13de1c81017459dc3e14306f4fe81bd7f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 19:03:02 +0900 Subject: [PATCH 1165/1400] Add a very simple user cache to `ScoreImporter` --- osu.Game/Scoring/ScoreImporter.cs | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreImporter.cs b/osu.Game/Scoring/ScoreImporter.cs index f69c1b9385..1c24cfbc85 100644 --- a/osu.Game/Scoring/ScoreImporter.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -146,16 +146,48 @@ namespace osu.Game.Scoring #pragma warning restore CS0618 } + // Very naive local caching to improve performance of large score imports (where the username is usually the same for most or all scores). + private readonly Dictionary usernameLookupCache = new Dictionary(); + protected override void PostImport(ScoreInfo model, Realm realm, ImportParameters parameters) { base.PostImport(model, realm, parameters); - var userRequest = new GetUserRequest(model.RealmUser.Username); + populateUserDetails(model); + } + + /// + /// Legacy replays only store a username. + /// This will populate a user ID during import. + /// + private void populateUserDetails(ScoreInfo model) + { + string username = model.RealmUser.Username; + + if (usernameLookupCache.TryGetValue(username, out var existing)) + { + model.User = existing; + return; + } + + var userRequest = new GetUserRequest(username); api.Perform(userRequest); if (userRequest.Response is APIUser user) + { + usernameLookupCache.TryAdd(username, new APIUser + { + // Because this is a permanent cache, let's only store the pieces we're interested in, + // rather than the full API response. If we start to store more than these three fields + // in realm, this should be undone. + Id = user.Id, + Username = user.Username, + CountryCode = user.CountryCode, + }); + model.User = user; + } } } } From 49c77a64efeb5886abe5de78aa820c7ded8a5558 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 9 Jun 2023 19:30:28 +0900 Subject: [PATCH 1166/1400] Apply more correct fix, factoring in minimum display ratio --- ...eatmapPanelBackgroundTextureLoaderStore.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index 8f70f8a04f..110cebbe0e 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -17,9 +17,8 @@ namespace osu.Game.Beatmaps // If issues are found it's worth checking to make sure similar issues exist there. public class BeatmapPanelBackgroundTextureLoaderStore : IResourceStore { - // These numbers are taken from the draw visualiser size requirements for song select panel textures at extreme aspect ratios. - private const int max_height = 130; - private const int max_width = 1280; + // The aspect ratio of SetPanelBackground at its maximum size (very tall window). + private const float minimum_display_ratio = 512 / 80f; private readonly IResourceStore? textureStore; @@ -67,16 +66,18 @@ namespace osu.Game.Beatmaps Size size = image.Size(); - float aspectRatio = (float)size.Width / size.Height; - - int usableWidth = Math.Min((int)(max_width * aspectRatio), size.Width); - int usableHeight = Math.Min(max_height, size.Height); + // Assume that panel backgrounds are always displayed using `FillMode.Fill`. + // Also assume that all backgrounds are wider than they are tall, so the + // fill is always going to be based on width. + // + // We need to include enough height to make this work for all ratio panels are displayed at. + int usableHeight = (int)Math.Ceiling(size.Width * 1 / minimum_display_ratio); // Crop the centre region of the background for now. Rectangle cropRectangle = new Rectangle( - (size.Width - usableWidth) / 2, + 0, (size.Height - usableHeight) / 2, - usableWidth, + size.Width, usableHeight ); From 11694f35fe5f475e6321121c1708add60983eb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Jun 2023 13:47:35 +0200 Subject: [PATCH 1167/1400] Apply NRT in `MemoryCachingComponent` subclasses too --- osu.Game/Database/BeatmapLookupCache.cs | 10 +++------- osu.Game/Scoring/ScorePerformanceCache.cs | 9 +++------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game/Database/BeatmapLookupCache.cs b/osu.Game/Database/BeatmapLookupCache.cs index d9bf0138dc..973c25ec4f 100644 --- a/osu.Game/Database/BeatmapLookupCache.cs +++ b/osu.Game/Database/BeatmapLookupCache.cs @@ -1,13 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -21,8 +18,7 @@ namespace osu.Game.Database /// The beatmap to lookup. /// An optional cancellation token. /// The populated beatmap, or null if the beatmap does not exist or the request could not be satisfied. - [ItemCanBeNull] - public Task GetBeatmapAsync(int beatmapId, CancellationToken token = default) => LookupAsync(beatmapId, token); + public Task GetBeatmapAsync(int beatmapId, CancellationToken token = default) => LookupAsync(beatmapId, token); /// /// Perform an API lookup on the specified beatmaps, populating a model. @@ -30,10 +26,10 @@ namespace osu.Game.Database /// The beatmaps to lookup. /// An optional cancellation token. /// The populated beatmaps. May include null results for failed retrievals. - public Task GetBeatmapsAsync(int[] beatmapIds, CancellationToken token = default) => LookupAsync(beatmapIds, token); + public Task GetBeatmapsAsync(int[] beatmapIds, CancellationToken token = default) => LookupAsync(beatmapIds, token); protected override GetBeatmapsRequest CreateRequest(IEnumerable ids) => new GetBeatmapsRequest(ids.ToArray()); - protected override IEnumerable RetrieveResults(GetBeatmapsRequest request) => request.Response?.Beatmaps; + protected override IEnumerable? RetrieveResults(GetBeatmapsRequest request) => request.Response?.Beatmaps; } } diff --git a/osu.Game/Scoring/ScorePerformanceCache.cs b/osu.Game/Scoring/ScorePerformanceCache.cs index 17a0c0ea6a..bdbcfe4efe 100644 --- a/osu.Game/Scoring/ScorePerformanceCache.cs +++ b/osu.Game/Scoring/ScorePerformanceCache.cs @@ -1,12 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Database; @@ -21,7 +18,7 @@ namespace osu.Game.Scoring public partial class ScorePerformanceCache : MemoryCachingComponent { [Resolved] - private BeatmapDifficultyCache difficultyCache { get; set; } + private BeatmapDifficultyCache difficultyCache { get; set; } = null!; protected override bool CacheNullValues => false; @@ -30,10 +27,10 @@ namespace osu.Game.Scoring /// /// The score to do the calculation on. /// An optional to cancel the operation. - public Task CalculatePerformanceAsync([NotNull] ScoreInfo score, CancellationToken token = default) => + public Task CalculatePerformanceAsync(ScoreInfo score, CancellationToken token = default) => GetAsync(new PerformanceCacheLookup(score), token); - protected override async Task ComputeValueAsync(PerformanceCacheLookup lookup, CancellationToken token = default) + protected override async Task ComputeValueAsync(PerformanceCacheLookup lookup, CancellationToken token = default) { var score = lookup.ScoreInfo; From 58507291b9c213e94c6ca2337f379ecc01f68899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Jun 2023 13:47:50 +0200 Subject: [PATCH 1168/1400] Apply NRT in `MemoryCachingComponent` test-only subclasses --- .../Online/TestSceneCurrentlyPlayingDisplay.cs | 12 +++++------- .../SongSelect/TestSceneBeatmapMetadataDisplay.cs | 14 ++++++++------ osu.Game/Tests/Visual/TestUserLookupCache.cs | 8 +++----- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index 4f825e1191..885c00be80 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.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. -#nullable disable - using System; using System.Linq; using System.Threading; @@ -24,8 +22,8 @@ namespace osu.Game.Tests.Visual.Online { private readonly APIUser streamingUser = new APIUser { Id = 2, Username = "Test user" }; - private TestSpectatorClient spectatorClient; - private CurrentlyPlayingDisplay currentlyPlaying; + private TestSpectatorClient spectatorClient = null!; + private CurrentlyPlayingDisplay currentlyPlaying = null!; [SetUpSteps] public void SetUpSteps() @@ -88,13 +86,13 @@ namespace osu.Game.Tests.Visual.Online "pishifat" }; - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) + protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) { // tests against failed lookups if (lookup == 13) - return Task.FromResult(null); + return Task.FromResult(null); - return Task.FromResult(new APIUser + return Task.FromResult(new APIUser { Id = lookup, Username = usernames[lookup % usernames.Length], diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs index c2537cff79..379bd838cd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapMetadataDisplay.cs @@ -1,10 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -24,10 +23,10 @@ namespace osu.Game.Tests.Visual.SongSelect { public partial class TestSceneBeatmapMetadataDisplay : OsuTestScene { - private BeatmapMetadataDisplay display; + private BeatmapMetadataDisplay display = null!; [Resolved] - private BeatmapManager manager { get; set; } + private BeatmapManager manager { get; set; } = null!; [Cached(typeof(BeatmapDifficultyCache))] private readonly TestBeatmapDifficultyCache testDifficultyCache = new TestBeatmapDifficultyCache(); @@ -121,7 +120,7 @@ namespace osu.Game.Tests.Visual.SongSelect private partial class TestBeatmapDifficultyCache : BeatmapDifficultyCache { - private TaskCompletionSource calculationBlocker; + private TaskCompletionSource? calculationBlocker; private bool blockCalculation; @@ -142,10 +141,13 @@ namespace osu.Game.Tests.Visual.SongSelect } } - public override async Task GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo rulesetInfo = null, IEnumerable mods = null, CancellationToken cancellationToken = default) + public override async Task GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, IEnumerable? mods = null, CancellationToken cancellationToken = default) { if (blockCalculation) + { + Debug.Assert(calculationBlocker != null); await calculationBlocker.Task.ConfigureAwait(false); + } return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken).ConfigureAwait(false); } diff --git a/osu.Game/Tests/Visual/TestUserLookupCache.cs b/osu.Game/Tests/Visual/TestUserLookupCache.cs index a3028f1a34..261e0fa75c 100644 --- a/osu.Game/Tests/Visual/TestUserLookupCache.cs +++ b/osu.Game/Tests/Visual/TestUserLookupCache.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. -#nullable disable - using System.Threading; using System.Threading.Tasks; using osu.Game.Database; @@ -18,12 +16,12 @@ namespace osu.Game.Tests.Visual /// public const int UNRESOLVED_USER_ID = -1; - protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) + protected override Task ComputeValueAsync(int lookup, CancellationToken token = default) { if (lookup == UNRESOLVED_USER_ID) - return Task.FromResult((APIUser)null); + return Task.FromResult(null); - return Task.FromResult(new APIUser + return Task.FromResult(new APIUser { Id = lookup, Username = $"User {lookup}" From 287229efd5f2f0633510daa691b11eb982742124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Jun 2023 14:25:53 +0200 Subject: [PATCH 1169/1400] Fix code quality inspection --- osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 1d496cc636..cce633d46a 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -67,7 +67,7 @@ namespace osu.Game.Online.Rooms { var beatmap = task.GetResultSafely(); - if (SelectedItem.Value?.Beatmap.OnlineID == beatmap.OnlineID) + if (beatmap != null && SelectedItem.Value?.Beatmap.OnlineID == beatmap.OnlineID) { selectedBeatmap = beatmap; beginTracking(); From 2823a62b5fe82c2232951198b73ac4253d7835f0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 9 Jun 2023 15:27:53 +0300 Subject: [PATCH 1170/1400] Avoid potential cropping error on very tall backgrounds --- osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs index 110cebbe0e..acd60b664d 100644 --- a/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs +++ b/osu.Game/Beatmaps/BeatmapPanelBackgroundTextureLoaderStore.cs @@ -73,6 +73,8 @@ namespace osu.Game.Beatmaps // We need to include enough height to make this work for all ratio panels are displayed at. int usableHeight = (int)Math.Ceiling(size.Width * 1 / minimum_display_ratio); + usableHeight = Math.Min(size.Height, usableHeight); + // Crop the centre region of the background for now. Rectangle cropRectangle = new Rectangle( 0, From 52412c673d45eb9bb1cbef5d6e54644082907b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 9 Jun 2023 14:47:34 +0200 Subject: [PATCH 1171/1400] Bump replay version in encoder after Score V2 changes One release too late, but this may help in the future if we need to discern replays set with Score V2 from older lazer replays. --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index a78ae24da2..87e1e79f87 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -28,9 +28,10 @@ namespace osu.Game.Scoring.Legacy /// /// /// 30000001: Appends to the end of scores. + /// 30000002: Score stored to replay calculated using the Score V2 algorithm. /// /// - public const int LATEST_VERSION = 30000001; + public const int LATEST_VERSION = 30000002; /// /// The first stable-compatible YYYYMMDD format version given to lazer usage of replays. From c3b50e130997cd36fa440e4116c66276b5f2685d Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 9 Jun 2023 16:25:04 +0300 Subject: [PATCH 1172/1400] Move the multiplier back to `TopRight` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 3795ed729d..6345916e63 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -219,8 +219,8 @@ namespace osu.Game.Overlays.Mods { aboveColumnsContent.Add(multiplierDisplay = new DifficultyMultiplierDisplay { - Anchor = Anchor.Centre, - Origin = Anchor.Centre + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight }); } From 7697dbe4b3aec9ebe5788d55e0f4027f3bf4e4af Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 9 Jun 2023 16:55:19 +0300 Subject: [PATCH 1173/1400] Mod panel don't play sound when hidden --- osu.Game/Overlays/Mods/ModColumn.cs | 4 ++-- osu.Game/Overlays/Mods/ModSelectPanel.cs | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 9146cd7abe..363f5c5d0f 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -212,8 +212,8 @@ namespace osu.Game.Overlays.Mods foreach (var button in availableMods.Where(b => b.Active.Value)) { - if (Alpha == 0f) - button.Active.Value = false; //If column is hidden change state manually without any animation + if (!button.Visible) + button.Active.Value = false; //If mod panel is hidden change state manually without any animation else pendingSelectionOperations.Enqueue(() => button.Active.Value = false); } diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 90663d083c..9d87e1da90 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -193,6 +193,9 @@ namespace osu.Game.Overlays.Mods if (samplePlaybackDisabled.Value) return; + if (!IsPresent) + return; + if (Active.Value) sampleOn?.Play(); else From d219b5f77f33b443a3a57d91368bae74f658c7a7 Mon Sep 17 00:00:00 2001 From: Cootz Date: Fri, 9 Jun 2023 17:10:13 +0300 Subject: [PATCH 1174/1400] Reword change focus comment --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 6345916e63..574d18de0e 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -838,7 +838,8 @@ namespace osu.Game.Overlays.Mods if (!Active.Value) RequestScroll?.Invoke(this); - //Kill focus on SearchTextBox + //By doing this we kill the focus on SearchTextBox. + //Killing focus is done here because it's the only feasible place on ModSelectOverlay you can click on without triggering any action. Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null)); return true; From 4b8c4bd503075fa76a375ee90fc42838338eeb69 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 10 Jun 2023 01:51:53 +0900 Subject: [PATCH 1175/1400] Fix black jaggies around argon hitcircles --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs index 1c5cf49625..83de50184f 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs @@ -62,7 +62,10 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon { outerFill = new Circle // renders white outer border and dark fill { - Size = Size, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + // Slightly inset to prevent bleeding outside the ring + Size = Size - new Vector2(0.5f), Alpha = withOuterFill ? 1 : 0, }, outerGradient = new Circle // renders the outer bright gradient From 7bf73463f1ae711066074ec704e25b711738ff4f Mon Sep 17 00:00:00 2001 From: Xinnoh <30382015+Xinnoh@users.noreply.github.com> Date: Fri, 9 Jun 2023 22:46:07 -0700 Subject: [PATCH 1176/1400] reduce argon kiai flashing --- osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs index d7e37899ce..e67417c384 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon private const double pre_beat_transition_time = 80; - private const float flash_opacity = 0.3f; + private const float flash_opacity = 0.15f; private ColourInfo accentColour; From 0c42aa7f3b19d810d2eac06803697060b179922b Mon Sep 17 00:00:00 2001 From: Xinnoh <30382015+Xinnoh@users.noreply.github.com> Date: Fri, 9 Jun 2023 22:51:45 -0700 Subject: [PATCH 1177/1400] lower kiai pulse brightness --- osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs index bde502bbed..776996fdd2 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default private const double pre_beat_transition_time = 80; - private const float flash_opacity = 0.3f; + private const float flash_opacity = 0.15f; [Resolved] private DrawableHitObject drawableHitObject { get; set; } = null!; From 9224486ec7b5c4f868438b395458b5c5328ca69a Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 10 Jun 2023 12:38:26 +0300 Subject: [PATCH 1178/1400] Add mod select overlay statics --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 ++ .../Overlays/Mods/ModSelectOverlayStatics.cs | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 38ae8c68cb..a46de75273 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -103,6 +103,8 @@ namespace osu.Game.Overlays.Mods private readonly BindableBool customisationVisible = new BindableBool(); + protected readonly ModSelectOverlayStatics statics = new ModSelectOverlayStatics(); + private ModSettingsArea modSettingsArea = null!; private ColumnScrollContainer columnScroll = null!; private ColumnFlowContainer columnFlow = null!; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs new file mode 100644 index 0000000000..91f7f2180d --- /dev/null +++ b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs @@ -0,0 +1,20 @@ +// 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.Configuration; + +namespace osu.Game.Overlays.Mods +{ + public class ModSelectOverlayStatics : InMemoryConfigManager + { + protected override void InitialiseDefaults() + { + SetDefault(Static.LastModSelectPanelSoundPlaybackTime, (double?)null); + } + } + + public enum Static + { + LastModSelectPanelSoundPlaybackTime + } +} From 09cd5580e133218739c2dfde63d1871b82e435c8 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 10 Jun 2023 13:13:34 +0300 Subject: [PATCH 1179/1400] Add sample playback time restrictions --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 3 ++- osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs | 4 ++-- osu.Game/Overlays/Mods/ModSelectPanel.cs | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a46de75273..f2b61e3543 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -103,7 +103,8 @@ namespace osu.Game.Overlays.Mods private readonly BindableBool customisationVisible = new BindableBool(); - protected readonly ModSelectOverlayStatics statics = new ModSelectOverlayStatics(); + [Cached] + protected readonly ModSelectOverlayStatics Statics = new ModSelectOverlayStatics(); private ModSettingsArea modSettingsArea = null!; private ColumnScrollContainer columnScroll = null!; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs index 91f7f2180d..d9e66d8f4f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs @@ -9,12 +9,12 @@ namespace osu.Game.Overlays.Mods { protected override void InitialiseDefaults() { - SetDefault(Static.LastModSelectPanelSoundPlaybackTime, (double?)null); + SetDefault(Static.LastModSelectPanelSamplePlaybackTime, (double?)null); } } public enum Static { - LastModSelectPanelSoundPlaybackTime + LastModSelectPanelSamplePlaybackTime } } diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 81285833bd..42f72fbdca 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -44,6 +44,7 @@ namespace osu.Game.Overlays.Mods public const float CORNER_RADIUS = 7; public const float HEIGHT = 42; + public double SAMPLE_PLAYBACK_DELAY = 30; protected virtual float IdleSwitchWidth => 14; protected virtual float ExpandedSwitchWidth => 30; @@ -62,6 +63,9 @@ namespace osu.Game.Overlays.Mods [Resolved] protected OverlayColourProvider ColourProvider { get; private set; } = null!; + [Resolved] + protected ModSelectOverlayStatics ModOverlayStatics { get; private set; } = null!; + private readonly OsuSpriteText titleText; private readonly OsuSpriteText descriptionText; @@ -192,10 +196,17 @@ namespace osu.Game.Overlays.Mods if (samplePlaybackDisabled.Value) return; + double? lastPlaybackTime = ModOverlayStatics.Get(Static.LastModSelectPanelSamplePlaybackTime); + + if (lastPlaybackTime is not null && Time.Current - lastPlaybackTime < SAMPLE_PLAYBACK_DELAY) + return; + if (Active.Value) sampleOn?.Play(); else sampleOff?.Play(); + + ModOverlayStatics.SetValue(Static.LastModSelectPanelSamplePlaybackTime, Time.Current); } protected override bool OnHover(HoverEvent e) From 3bf900a4df9299a3cd9bcae8caa57b42372934a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Jun 2023 10:30:10 +0200 Subject: [PATCH 1180/1400] Add failing test case for slider scenario --- .../Mods/TestSceneOsuModAutoplay.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs index 616a9c362d..32028823ae 100644 --- a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAutoplay.cs @@ -1,22 +1,29 @@ // 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 System.Linq; using NUnit.Framework; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Skinning.Default; using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Scoring; +using osuTK; namespace osu.Game.Rulesets.Osu.Tests.Mods { public partial class TestSceneOsuModAutoplay : OsuModTestScene { + protected override bool AllowFail => true; + [Test] public void TestCursorPositionStoredToJudgement() { @@ -44,6 +51,36 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods FinalRate = { Value = 1.3 } }); + [Test] + public void TestPerfectScoreOnShortSliderWithRepeat() + { + AddStep("set score to standardised", () => LocalConfig.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); + + CreateModTest(new ModTestData + { + Autoplay = true, + Beatmap = new Beatmap + { + HitObjects = new List + { + new Slider + { + StartTime = 500, + Position = new Vector2(256, 192), + Path = new SliderPath(new[] + { + new PathControlPoint(), + new PathControlPoint(new Vector2(0, 6.25f)) + }), + RepeatCount = 1, + SliderVelocity = 10 + } + } + }, + PassCondition = () => Player.ScoreProcessor.TotalScore.Value == 1_000_000 + }); + } + private void runSpmTest(Mod mod) { SpinnerSpmCalculator? spmCalculator = null; From 7e5533e2057a215f8bcbc9b9f1e9edc2282edcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 10 Jun 2023 11:02:29 +0200 Subject: [PATCH 1181/1400] Fix not being able to receive full score for extremely short sliders with repeats Closes #23862. Score V2 is a scoring algorithm, which aside from the raw numerical values of each judgement, incorporates a combo component, wherein each judgement's "combo score" is derived from both the raw numerical value of the object and the current combo after the given judgement. In particular, this means that Score V2 is sensitive to the _order_ of judging objects, as if two objects with the same start time are judged using different ordering, they can end up having a different "combo score". The issue that this change is fixing is an instance of one such reordering. Upon inspection, it turned out that the simulated autoplay run, which is used to determine max possible score so that it can be standardised to 1 million again, was processing a slider repeat before a slider tail circle, while actual gameplay was processing the same slider repeat _after_ the slider tail circle. The cause of that behaviour is unfortunately due to `LegacyLastTick`. The sliders which cause the issue are extremely short. Stable had a behaviour, in which to provide leniency, slider tails were artificially offset back by 36ms. However, if the slider is not long enough to make this possible, the last tick is placed in the middle of the slider. If that slider also happens to have exactly 1 repeat, then this means that the last tick and the repeat have the same time instant. Because of the time equality, what begins to matter now is the _order_ of processing the elements of the drawable slider in the hierarchy. For the purposes of legacy skins, tail circles were moved below ticks in fce3eacd7de3254ce75619efaa2d15d59d564623 - but in this particular case, it means that the order of processing the slider elements is now inadvertently inverted, causing the entire debacle. While the fact that scoring depends on order of processing of visuals is suboptimal, there isn't a great way to address this without significant restructuring. Due to the structure of processing judgements currently in place, in which each judgement is processed independently from others by its corresponding drawable hit object, this is probably the best that can be done for the time being at least. --- .../Objects/Drawables/DrawableSlider.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 664a8146e7..01174d4d61 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -75,18 +75,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables [BackgroundDependencyLoader] private void load() { + tailContainer = new Container { RelativeSizeAxes = Axes.Both }; + AddRangeInternal(new Drawable[] { shakeContainer = new ShakeContainer { ShakeDuration = 30, RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Children = new[] { Body = new SkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.SliderBody), _ => new DefaultSliderBody(), confineMode: ConfineMode.NoScaling), - tailContainer = new Container { RelativeSizeAxes = Axes.Both }, + // proxied here so that the tail is drawn under repeats/ticks - legacy skins rely on this + tailContainer.CreateProxy(), tickContainer = new Container { RelativeSizeAxes = Axes.Both }, repeatContainer = new Container { RelativeSizeAxes = Axes.Both }, + // actual tail container is placed here to ensure that tail hitobjects are processed after ticks/repeats. + // this is required for the correct operation of Score V2. + tailContainer, } }, // slider head is not included in shake as it handles hit detection, and handles its own shaking. From 31f370ec9b944ab994c3b4100b835f2a7d780fdb Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 10 Jun 2023 13:50:45 +0300 Subject: [PATCH 1182/1400] Add comments for `ModSelectOverlayStatics` --- osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs index d9e66d8f4f..2d432b010f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs @@ -5,6 +5,9 @@ using osu.Game.Configuration; namespace osu.Game.Overlays.Mods { + /// + /// Stores global mod overlay statics. These will not be stored after disposal of + /// public class ModSelectOverlayStatics : InMemoryConfigManager { protected override void InitialiseDefaults() @@ -15,6 +18,10 @@ namespace osu.Game.Overlays.Mods public enum Static { + /// + /// The last playback time in milliseconds of an on/off sample (from ). + /// Used to debounce on/off sounds game-wide to avoid volume saturation, especially in activating mod presets with many mods. + /// LastModSelectPanelSamplePlaybackTime } } From 502193e1c6f2cbb812c5b2f2af6392794e6af456 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 10 Jun 2023 13:55:37 +0300 Subject: [PATCH 1183/1400] Use debounce constant for select/deselect animation --- osu.Game/Overlays/Mods/ModColumn.cs | 2 +- osu.Game/Overlays/Mods/ModSelectPanel.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 5d9f616e5f..fe42cc0abf 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -176,7 +176,7 @@ namespace osu.Game.Overlays.Mods dequeuedAction(); // each time we play an animation, we decrease the time until the next animation (to ramp the visual and audible elements). - selectionDelay = Math.Max(30, selectionDelay * 0.8f); + selectionDelay = Math.Max(ModSelectPanel.SAMPLE_PLAYBACK_DELAY, selectionDelay * 0.8f); lastSelection = Time.Current; } else diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 42f72fbdca..4c06378d89 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Mods public const float CORNER_RADIUS = 7; public const float HEIGHT = 42; - public double SAMPLE_PLAYBACK_DELAY = 30; + public const double SAMPLE_PLAYBACK_DELAY = 30; protected virtual float IdleSwitchWidth => 14; protected virtual float ExpandedSwitchWidth => 30; From 274736b9c7fe0055c9da9c2401205d884c3ad9f7 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sat, 10 Jun 2023 15:14:25 +0300 Subject: [PATCH 1184/1400] Fix missing dependency exception in unit tests --- osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs | 3 +++ osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs | 3 +++ .../Visual/UserInterface/TestSceneModPresetColumn.cs | 3 +++ osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs | 3 +++ 4 files changed, 12 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index a11000214c..08110382df 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -27,6 +27,9 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + [Cached] + private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); + [Resolved] private OsuConfigManager configManager { get; set; } = null!; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs index 64bdc167c2..f1283994d6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs @@ -23,6 +23,9 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + [Cached] + private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); + [Test] public void TestVariousPanels() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 3efdba8754..3bbc24ed23 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -37,6 +37,9 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + [Cached] + private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); + [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs index 35e352534b..f1899b9e29 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs @@ -26,6 +26,9 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + [Cached] + private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); + [SetUpSteps] public void SetUpSteps() { From 61a9c6fd7eb29b964a566e8224fef41c464b86c2 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 10 Jun 2023 11:53:45 -0700 Subject: [PATCH 1185/1400] Disable `Truncate` in `OsuSpriteText` Co-Authored-By: Salman Ahmed --- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 7 +++++++ osu.Game/Graphics/Sprites/TruncatingSpriteText.cs | 3 ++- osu.Game/Overlays/Mods/ModSelectPanel.cs | 6 ++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index e149e0abfb..afbec0eab4 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -3,12 +3,19 @@ #nullable disable +using System; using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics.Sprites { public partial class OsuSpriteText : SpriteText { + [Obsolete("Use TruncatingSpriteText instead.")] + public new bool Truncate + { + set => throw new InvalidOperationException($"Use {nameof(TruncatingSpriteText)} instead."); + } + public OsuSpriteText() { Shadow = true; diff --git a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs index da0dbd49d2..229fad29f9 100644 --- a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; namespace osu.Game.Graphics.Sprites @@ -14,7 +15,7 @@ namespace osu.Game.Graphics.Sprites public TruncatingSpriteText() { - Truncate = true; + ((SpriteText)this).Truncate = true; } } } diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 81285833bd..6179f31637 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -118,22 +118,20 @@ namespace osu.Game.Overlays.Mods Direction = FillDirection.Vertical, Children = new[] { - titleText = new OsuSpriteText + titleText = new TruncatingSpriteText { Font = OsuFont.TorusAlternate.With(size: 18, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, - Truncate = true, Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), Margin = new MarginPadding { Left = -18 * ShearedOverlayContainer.SHEAR } }, - descriptionText = new OsuSpriteText + descriptionText = new TruncatingSpriteText { Font = OsuFont.Default.With(size: 12), RelativeSizeAxes = Axes.X, - Truncate = true, Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0) } } From 0d51e4f6cea0aeded84760a17156f0331c89f3bf Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 10 Jun 2023 12:24:58 -0700 Subject: [PATCH 1186/1400] Fix mod select panels having conflicting tooltips Going simple with a bool instead of making `TooltipText` init-able, as the current cases will just init `string.Empty`. And not sure if we want custom tooltip text in the future. --- osu.Game/Graphics/Sprites/TruncatingSpriteText.cs | 4 +++- osu.Game/Overlays/Mods/ModSelectPanel.cs | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs index 229fad29f9..254e708183 100644 --- a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs @@ -9,9 +9,11 @@ namespace osu.Game.Graphics.Sprites { public sealed partial class TruncatingSpriteText : OsuSpriteText, IHasTooltip { + public bool ShowTooltip { get; init; } = true; + public LocalisableString TooltipText => Text; - public override bool HandlePositionalInput => IsTruncated; + public override bool HandlePositionalInput => IsTruncated && ShowTooltip; public TruncatingSpriteText() { diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 6179f31637..09f5e5ced7 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -126,13 +126,15 @@ namespace osu.Game.Overlays.Mods Margin = new MarginPadding { Left = -18 * ShearedOverlayContainer.SHEAR - } + }, + ShowTooltip = false, }, descriptionText = new TruncatingSpriteText { Font = OsuFont.Default.With(size: 12), RelativeSizeAxes = Axes.X, - Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0) + Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), + ShowTooltip = false, } } } From 4819a2879190b80c87c8822f451abb45b1d90cfc Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 11 Jun 2023 13:53:17 +0300 Subject: [PATCH 1187/1400] Move mod overlay statics to `SessionStatics` --- .../UserInterface/TestSceneModColumn.cs | 3 --- .../Visual/UserInterface/TestSceneModPanel.cs | 3 --- .../UserInterface/TestSceneModPresetColumn.cs | 3 --- .../UserInterface/TestSceneModPresetPanel.cs | 3 --- osu.Game/Configuration/SessionStatics.cs | 8 ++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 3 --- .../Overlays/Mods/ModSelectOverlayStatics.cs | 27 ------------------- osu.Game/Overlays/Mods/ModSelectPanel.cs | 7 ++--- 8 files changed, 12 insertions(+), 45 deletions(-) delete mode 100644 osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 08110382df..a11000214c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -27,9 +27,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); - [Cached] - private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); - [Resolved] private OsuConfigManager configManager { get; set; } = null!; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs index f1283994d6..64bdc167c2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPanel.cs @@ -23,9 +23,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); - [Cached] - private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); - [Test] public void TestVariousPanels() { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 3bbc24ed23..3efdba8754 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -37,9 +37,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); - [Cached] - private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); - [Cached(typeof(IDialogOverlay))] private readonly DialogOverlay dialogOverlay = new DialogOverlay(); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs index f1899b9e29..35e352534b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetPanel.cs @@ -26,9 +26,6 @@ namespace osu.Game.Tests.Visual.UserInterface [Cached] private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); - [Cached] - private ModSelectOverlayStatics modOverlayStatics = new ModSelectOverlayStatics(); - [SetUpSteps] public void SetUpSteps() { diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs index 276563e163..5e2f0c2128 100644 --- a/osu.Game/Configuration/SessionStatics.cs +++ b/osu.Game/Configuration/SessionStatics.cs @@ -6,6 +6,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; +using osu.Game.Overlays.Mods; namespace osu.Game.Configuration { @@ -21,6 +22,7 @@ namespace osu.Game.Configuration SetDefault(Static.LowBatteryNotificationShownOnce, false); SetDefault(Static.FeaturedArtistDisclaimerShownOnce, false); SetDefault(Static.LastHoverSoundPlaybackTime, (double?)null); + SetDefault(Static.LastModSelectPanelSamplePlaybackTime, (double?)null); SetDefault(Static.SeasonalBackgrounds, null); } @@ -56,5 +58,11 @@ namespace osu.Game.Configuration /// Used to debounce hover sounds game-wide to avoid volume saturation, especially in scrolling views with many UI controls like . /// LastHoverSoundPlaybackTime, + + /// + /// The last playback time in milliseconds of an on/off sample (from ). + /// Used to debounce on/off sounds game-wide to avoid volume saturation, especially in activating mod presets with many mods. + /// + LastModSelectPanelSamplePlaybackTime } } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index f2b61e3543..38ae8c68cb 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -103,9 +103,6 @@ namespace osu.Game.Overlays.Mods private readonly BindableBool customisationVisible = new BindableBool(); - [Cached] - protected readonly ModSelectOverlayStatics Statics = new ModSelectOverlayStatics(); - private ModSettingsArea modSettingsArea = null!; private ColumnScrollContainer columnScroll = null!; private ColumnFlowContainer columnFlow = null!; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs b/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs deleted file mode 100644 index 2d432b010f..0000000000 --- a/osu.Game/Overlays/Mods/ModSelectOverlayStatics.cs +++ /dev/null @@ -1,27 +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.Configuration; - -namespace osu.Game.Overlays.Mods -{ - /// - /// Stores global mod overlay statics. These will not be stored after disposal of - /// - public class ModSelectOverlayStatics : InMemoryConfigManager - { - protected override void InitialiseDefaults() - { - SetDefault(Static.LastModSelectPanelSamplePlaybackTime, (double?)null); - } - } - - public enum Static - { - /// - /// The last playback time in milliseconds of an on/off sample (from ). - /// Used to debounce on/off sounds game-wide to avoid volume saturation, especially in activating mod presets with many mods. - /// - LastModSelectPanelSamplePlaybackTime - } -} diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 4c06378d89..be07759984 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -14,6 +14,7 @@ using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Audio; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -64,7 +65,7 @@ namespace osu.Game.Overlays.Mods protected OverlayColourProvider ColourProvider { get; private set; } = null!; [Resolved] - protected ModSelectOverlayStatics ModOverlayStatics { get; private set; } = null!; + protected SessionStatics Statics { get; private set; } = null!; private readonly OsuSpriteText titleText; private readonly OsuSpriteText descriptionText; @@ -196,7 +197,7 @@ namespace osu.Game.Overlays.Mods if (samplePlaybackDisabled.Value) return; - double? lastPlaybackTime = ModOverlayStatics.Get(Static.LastModSelectPanelSamplePlaybackTime); + double? lastPlaybackTime = Statics.Get(Static.LastModSelectPanelSamplePlaybackTime); if (lastPlaybackTime is not null && Time.Current - lastPlaybackTime < SAMPLE_PLAYBACK_DELAY) return; @@ -206,7 +207,7 @@ namespace osu.Game.Overlays.Mods else sampleOff?.Play(); - ModOverlayStatics.SetValue(Static.LastModSelectPanelSamplePlaybackTime, Time.Current); + Statics.SetValue(Static.LastModSelectPanelSamplePlaybackTime, Time.Current); } protected override bool OnHover(HoverEvent e) From 82b7e570cddc271e36360de10ee447d129733114 Mon Sep 17 00:00:00 2001 From: yhsphd Date: Sun, 11 Jun 2023 22:43:06 +0900 Subject: [PATCH 1188/1400] Add a checkbox to toggle line breaking for each mod in mappool screen --- .../Screens/MapPool/MapPoolScreen.cs | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index f0e34d78c3..fcb0c4d70b 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -25,6 +26,7 @@ namespace osu.Game.Tournament.Screens.MapPool public partial class MapPoolScreen : TournamentMatchScreen { private readonly FillFlowContainer> mapFlows; + private TournamentMatch currentMatch; [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } @@ -37,6 +39,8 @@ namespace osu.Game.Tournament.Screens.MapPool private readonly OsuButton buttonRedPick; private readonly OsuButton buttonBluePick; + private readonly SettingsCheckbox chkBoxLineBreak; + public MapPoolScreen() { InternalChildren = new Drawable[] @@ -98,6 +102,15 @@ namespace osu.Game.Tournament.Screens.MapPool Action = reset }, new ControlPanel.Spacer(), + new TournamentSpriteText + { + Text = "Each modpool takes" + }, + new TournamentSpriteText + { + Text = "different row" + }, + chkBoxLineBreak = new SettingsCheckbox() }, } }; @@ -107,6 +120,8 @@ namespace osu.Game.Tournament.Screens.MapPool private void load(MatchIPCInfo ipc) { ipc.Beatmap.BindValueChanged(beatmapChanged); + chkBoxLineBreak.Current.Value = true; + chkBoxLineBreak.Current.BindValueChanged(_ => rearrangeMappool()); } private void beatmapChanged(ValueChangedEvent beatmap) @@ -213,37 +228,42 @@ namespace osu.Game.Tournament.Screens.MapPool protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); + currentMatch = match.NewValue; + rearrangeMappool(); + } + private void rearrangeMappool() + { mapFlows.Clear(); - if (match.NewValue == null) + if (currentMatch == null) return; - int totalRows = 0; - if (match.NewValue.Round.Value != null) + if (currentMatch.Round.Value != null) { FillFlowContainer currentFlow = null; string currentMod = null; - int flowCount = 0; - foreach (var b in match.NewValue.Round.Value.Beatmaps) + foreach (var b in currentMatch.Round.Value.Beatmaps) { if (currentFlow == null || currentMod != b.Mods) { - mapFlows.Add(currentFlow = new FillFlowContainer + if (chkBoxLineBreak.Current.Value || currentFlow == null) { - Spacing = new Vector2(10, 5), - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }); + mapFlows.Add(currentFlow = new FillFlowContainer + { + Spacing = new Vector2(10, 5), + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }); + totalRows++; + flowCount = 0; + } currentMod = b.Mods; - - totalRows++; - flowCount = 0; } if (++flowCount > 2) From b986d1cee1d679fd893704e5b010a8464ab785b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 14:18:26 +0900 Subject: [PATCH 1189/1400] Rename variables to give more context --- osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs | 4 ++-- osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs index e67417c384..cecb99c690 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Argon/ArgonCirclePiece.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon private const double pre_beat_transition_time = 80; - private const float flash_opacity = 0.15f; + private const float kiai_flash_opacity = 0.15f; private ColourInfo accentColour; @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon if (drawableHitObject.State.Value == ArmedState.Idle) { flash - .FadeTo(flash_opacity) + .FadeTo(kiai_flash_opacity) .Then() .FadeOut(timingPoint.BeatLength * 0.75, Easing.OutSine); } diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs index 776996fdd2..b3833d372c 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/CirclePiece.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default private const double pre_beat_transition_time = 80; - private const float flash_opacity = 0.15f; + private const float kiai_flash_opacity = 0.15f; [Resolved] private DrawableHitObject drawableHitObject { get; set; } = null!; @@ -187,7 +187,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default if (drawableHitObject.State.Value == ArmedState.Idle) { flashBox - .FadeTo(flash_opacity) + .FadeTo(kiai_flash_opacity) .Then() .FadeOut(timingPoint.BeatLength * 0.75, Easing.OutSine); } From 03a5b701e907d46861accc439a629e7778df1e79 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 14:20:54 +0900 Subject: [PATCH 1190/1400] Fix incorrect inline comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs index 83de50184f..b0492ca6df 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon InternalChildren = new Drawable[] { - outerFill = new Circle // renders white outer border and dark fill + outerFill = new Circle // renders dark fill { Anchor = Anchor.Centre, Origin = Anchor.Centre, From bddb91dc0af428928485082c5db73560d61bbfbe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 14:23:46 +0900 Subject: [PATCH 1191/1400] Adjust adjustment to 1px based on review feedback Also split out `Size` variable for clarity --- .../Skinning/Argon/ArgonMainCirclePiece.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs index b0492ca6df..3427031dc8 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Argon/ArgonMainCirclePiece.cs @@ -48,12 +48,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon private Bindable configHitLighting = null!; + private static readonly Vector2 circle_size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + [Resolved] private DrawableHitObject drawableObject { get; set; } = null!; public ArgonMainCirclePiece(bool withOuterFill) { - Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + Size = circle_size; Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -65,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon Anchor = Anchor.Centre, Origin = Anchor.Centre, // Slightly inset to prevent bleeding outside the ring - Size = Size - new Vector2(0.5f), + Size = circle_size - new Vector2(1), Alpha = withOuterFill ? 1 : 0, }, outerGradient = new Circle // renders the outer bright gradient @@ -91,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Argon Masking = true, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = Size, + Size = circle_size, Child = new KiaiFlash { RelativeSizeAxes = Axes.Both, From 1e774fc0170585b67d2a0d8b01500998a884c3f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 14:32:55 +0900 Subject: [PATCH 1192/1400] Refactor implementation to roughly match existing `HoverSampleDebounceComponent` --- osu.Game/Overlays/Mods/ModSelectPanel.cs | 28 +++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index be07759984..be01d239b6 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -45,6 +45,7 @@ namespace osu.Game.Overlays.Mods public const float CORNER_RADIUS = 7; public const float HEIGHT = 42; + public const double SAMPLE_PLAYBACK_DELAY = 30; protected virtual float IdleSwitchWidth => 14; @@ -64,9 +65,6 @@ namespace osu.Game.Overlays.Mods [Resolved] protected OverlayColourProvider ColourProvider { get; private set; } = null!; - [Resolved] - protected SessionStatics Statics { get; private set; } = null!; - private readonly OsuSpriteText titleText; private readonly OsuSpriteText descriptionText; @@ -74,6 +72,8 @@ namespace osu.Game.Overlays.Mods private Sample? sampleOff; private Sample? sampleOn; + private Bindable lastPlaybackTime = null!; + protected ModSelectPanel() { RelativeSizeAxes = Axes.X; @@ -168,13 +168,15 @@ namespace osu.Game.Overlays.Mods protected abstract void Deselect(); [BackgroundDependencyLoader] - private void load(AudioManager audio, ISamplePlaybackDisabler? samplePlaybackDisabler) + private void load(AudioManager audio, SessionStatics statics, ISamplePlaybackDisabler? samplePlaybackDisabler) { sampleOn = audio.Samples.Get(@"UI/check-on"); sampleOff = audio.Samples.Get(@"UI/check-off"); if (samplePlaybackDisabler != null) ((IBindable)samplePlaybackDisabled).BindTo(samplePlaybackDisabler.SamplePlaybackDisabled); + + lastPlaybackTime = statics.GetBindable(Static.LastHoverSoundPlaybackTime); } protected sealed override HoverSounds CreateHoverSounds(HoverSampleSet sampleSet) => new HoverSounds(sampleSet); @@ -197,17 +199,17 @@ namespace osu.Game.Overlays.Mods if (samplePlaybackDisabled.Value) return; - double? lastPlaybackTime = Statics.Get(Static.LastModSelectPanelSamplePlaybackTime); + bool enoughTimePassedSinceLastPlayback = !lastPlaybackTime.Value.HasValue || Time.Current - lastPlaybackTime.Value >= SAMPLE_PLAYBACK_DELAY; - if (lastPlaybackTime is not null && Time.Current - lastPlaybackTime < SAMPLE_PLAYBACK_DELAY) - return; + if (enoughTimePassedSinceLastPlayback) + { + if (Active.Value) + sampleOn?.Play(); + else + sampleOff?.Play(); - if (Active.Value) - sampleOn?.Play(); - else - sampleOff?.Play(); - - Statics.SetValue(Static.LastModSelectPanelSamplePlaybackTime, Time.Current); + lastPlaybackTime.Value = Time.Current; + } } protected override bool OnHover(HoverEvent e) From 8864014af84f1dcb6932d6f4573b1c9dae6d38f1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 15:25:12 +0900 Subject: [PATCH 1193/1400] Add xmldoc --- osu.Game/Graphics/Sprites/TruncatingSpriteText.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs index 254e708183..46abdbf09e 100644 --- a/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/TruncatingSpriteText.cs @@ -7,8 +7,14 @@ using osu.Framework.Localisation; namespace osu.Game.Graphics.Sprites { + /// + /// A derived version of which automatically shows non-truncated text in tooltip when required. + /// public sealed partial class TruncatingSpriteText : OsuSpriteText, IHasTooltip { + /// + /// Whether a tooltip should be shown with non-truncated text on hover. + /// public bool ShowTooltip { get; init; } = true; public LocalisableString TooltipText => Text; From 99f93f518555bebd6c024230b359addca0954181 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 15:31:22 +0900 Subject: [PATCH 1194/1400] Add comment mentioning why `ShowTooltip` is disabled in mod select panels --- osu.Game/Overlays/Mods/ModSelectPanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index 09f5e5ced7..d6916c49da 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -127,14 +127,14 @@ namespace osu.Game.Overlays.Mods { Left = -18 * ShearedOverlayContainer.SHEAR }, - ShowTooltip = false, + ShowTooltip = false, // Tooltip is handled by `IncompatibilityDisplayingModPanel`. }, descriptionText = new TruncatingSpriteText { Font = OsuFont.Default.With(size: 12), RelativeSizeAxes = Axes.X, Shear = new Vector2(-ShearedOverlayContainer.SHEAR, 0), - ShowTooltip = false, + ShowTooltip = false, // Tooltip is handled by `IncompatibilityDisplayingModPanel`. } } } From c9f9569e4a6403e637cb586db2b7e21212e8e97a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 16:22:38 +0900 Subject: [PATCH 1195/1400] Add ability to change background colour in song progress test scene --- .../Visual/Gameplay/TestSceneSongProgress.cs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 5855838d3c..530e4af062 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -7,12 +7,15 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osu.Game.Screens.Play.HUD; using osu.Game.Skinning; +using osuTK.Graphics; namespace osu.Game.Tests.Visual.Gameplay { @@ -21,6 +24,8 @@ namespace osu.Game.Tests.Visual.Gameplay { private GameplayClockContainer gameplayClockContainer = null!; + private Box background = null!; + private const double skip_target_time = -2000; [BackgroundDependencyLoader] @@ -30,11 +35,20 @@ namespace osu.Game.Tests.Visual.Gameplay FrameStabilityContainer frameStabilityContainer; - Add(gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, skip_target_time) + AddRange(new Drawable[] { - Child = frameStabilityContainer = new FrameStabilityContainer + background = new Box { - MaxCatchUpFrames = 1 + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue + }, + gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, skip_target_time) + { + Child = frameStabilityContainer = new FrameStabilityContainer + { + MaxCatchUpFrames = 1 + } } }); @@ -71,6 +85,9 @@ namespace osu.Game.Tests.Visual.Gameplay applyToArgonProgress(s => s.ShowGraph.Value = b); }); + AddStep("set white background", () => background.FadeColour(Color4.White, 200, Easing.OutQuint)); + AddStep("randomise background colour", () => background.FadeColour(new Colour4(RNG.NextSingle(), RNG.NextSingle(), RNG.NextSingle(), 1), 200, Easing.OutQuint)); + AddStep("stop", gameplayClockContainer.Stop); } From 84670d4c909df978adc96f7864762fb6cdf80661 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 15:52:25 +0900 Subject: [PATCH 1196/1400] Adjust argon graph to use a non-gray colour range --- .../Screens/Play/HUD/ArgonSongProgressGraph.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs index 63ab9d15e0..be570c1578 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressGraph.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Graphics.UserInterface; @@ -13,6 +15,10 @@ namespace osu.Game.Screens.Play.HUD { public partial class ArgonSongProgressGraph : SegmentedGraph { + private const int tier_count = 5; + + private const int display_granularity = 200; + private IEnumerable? objects; public IEnumerable Objects @@ -21,8 +27,7 @@ namespace osu.Game.Screens.Play.HUD { objects = value; - const int granularity = 200; - int[] values = new int[granularity]; + int[] values = new int[display_granularity]; if (!objects.Any()) return; @@ -32,7 +37,7 @@ namespace osu.Game.Screens.Play.HUD if (lastHit == 0) lastHit = objects.Last().StartTime; - double interval = (lastHit - firstHit + 1) / granularity; + double interval = (lastHit - firstHit + 1) / display_granularity; foreach (var h in objects) { @@ -51,12 +56,12 @@ namespace osu.Game.Screens.Play.HUD } public ArgonSongProgressGraph() - : base(5) + : base(tier_count) { var colours = new List(); - for (int i = 0; i < 5; i++) - colours.Add(Colour4.White.Darken(1 + 1 / 5f).Opacity(1 / 5f)); + for (int i = 0; i < tier_count; i++) + colours.Add(OsuColour.Gray(0.2f).Opacity(0.1f)); TierColours = colours; } From 855185ca858f9973f6f31985499c81714c811cd2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 16:10:51 +0900 Subject: [PATCH 1197/1400] Adjust argon song progress bar's background fill to always display --- .../Screens/Play/HUD/ArgonSongProgress.cs | 1 - .../Screens/Play/HUD/ArgonSongProgressBar.cs | 34 ++++++------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs index 9dce8996c3..be2ce3b272 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgress.cs @@ -95,7 +95,6 @@ namespace osu.Game.Screens.Play.HUD private void updateGraphVisibility() { graph.FadeTo(ShowGraph.Value ? 1 : 0, 200, Easing.In); - bar.ShowBackground = !ShowGraph.Value; } protected override void Update() diff --git a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs index dd6e10ba5d..beaee0e9ee 100644 --- a/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs +++ b/osu.Game/Screens/Play/HUD/ArgonSongProgressBar.cs @@ -14,7 +14,6 @@ using osu.Framework.Threading; using osu.Framework.Utils; using osu.Game.Graphics; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD { @@ -32,18 +31,8 @@ namespace osu.Game.Screens.Play.HUD private readonly Box background; - private readonly BindableBool showBackground = new BindableBool(); - private readonly ColourInfo mainColour; - private readonly ColourInfo mainColourDarkened; private ColourInfo catchUpColour; - private ColourInfo catchUpColourDarkened; - - public bool ShowBackground - { - get => showBackground.Value; - set => showBackground.Value = value; - } public double StartTime { @@ -95,7 +84,7 @@ namespace osu.Game.Screens.Play.HUD { RelativeSizeAxes = Axes.Both, Alpha = 0, - Colour = Colour4.White.Darken(1 + 1 / 4f) + Colour = OsuColour.Gray(0.2f), }, catchupBar = new RoundedBar { @@ -112,12 +101,10 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, CornerRadius = 5, - AccentColour = mainColour = Color4.White, + AccentColour = mainColour = OsuColour.Gray(0.9f), RelativeSizeAxes = Axes.Both }, }; - - mainColourDarkened = Colour4.White.Darken(1 / 3f); } private void setupAlternateValue() @@ -141,16 +128,15 @@ namespace osu.Game.Screens.Play.HUD [BackgroundDependencyLoader] private void load(OsuColour colours) { - catchUpColour = colours.BlueLight; - catchUpColourDarkened = colours.BlueDark; - - showBackground.BindValueChanged(_ => updateBackground(), true); + catchUpColour = colours.BlueDark; } - private void updateBackground() + protected override void LoadComplete() { - background.FadeTo(showBackground.Value ? 1 / 4f : 0, 200, Easing.In); - playfieldBar.TransformTo(nameof(playfieldBar.AccentColour), ShowBackground ? mainColour : mainColourDarkened, 200, Easing.In); + base.LoadComplete(); + + background.FadeTo(0.3f, 200, Easing.In); + playfieldBar.TransformTo(nameof(playfieldBar.AccentColour), mainColour, 200, Easing.In); } protected override bool OnHover(HoverEvent e) @@ -190,8 +176,8 @@ namespace osu.Game.Screens.Play.HUD catchupBar.AccentColour = Interpolation.ValueAt( Math.Min(timeDelta, colour_transition_threshold), - ShowBackground ? mainColour : mainColourDarkened, - ShowBackground ? catchUpColour : catchUpColourDarkened, + mainColour, + catchUpColour, 0, colour_transition_threshold, Easing.OutQuint); From 062fd58602545dec493ee210daee49a2851c2ba7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 16:25:53 +0900 Subject: [PATCH 1198/1400] Add test to known time --- osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 530e4af062..e975a85401 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -91,6 +91,14 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("stop", gameplayClockContainer.Stop); } + [Test] + public void TestSeekToKnownTime() + { + AddStep("seek to known time", () => gameplayClockContainer.Seek(60000)); + AddWaitStep("wait some for seek", 15); + AddStep("stop", () => gameplayClockContainer.Stop()); + } + private void applyToArgonProgress(Action action) => this.ChildrenOfType().ForEach(action); From a1b17c4468a58179d2226457d9de2c76505682c6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 17:12:18 +0900 Subject: [PATCH 1199/1400] Adjust log output for global background changes to make more sense --- osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 0d9b39f099..d9554c10e2 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Backgrounds if (nextBackground == background) return false; - Logger.Log("🌅 Background change queued"); + Logger.Log(@"🌅 Global background change queued"); cancellationTokenSource?.Cancel(); cancellationTokenSource = new CancellationTokenSource(); @@ -94,6 +94,7 @@ namespace osu.Game.Screens.Backgrounds nextTask?.Cancel(); nextTask = Scheduler.AddDelayed(() => { + Logger.Log(@"🌅 Global background loading"); LoadComponentAsync(nextBackground, displayNext, cancellationTokenSource.Token); }, 500); From a201339f9c9ab250ce10a691cda52855f4f17374 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 17:12:38 +0900 Subject: [PATCH 1200/1400] Fix background track restarting twice when exiting song select with no active selection --- osu.Game/Screens/Select/SongSelect.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4d6a5398c5..01c38667b1 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -814,6 +814,9 @@ namespace osu.Game.Screens.Select if (!ControlGlobalMusic) return; + if (Beatmap.Value is DummyWorkingBeatmap) + return; + ITrack track = music.CurrentTrack; bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; From a29f6772cd57f5194a07fb717a333bcd6d3f0b62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 17:22:11 +0900 Subject: [PATCH 1201/1400] Fix storyboard being null if file doesn't exist It's expected that `WorkingBeatmap.Storyboard` is non-null. An example fail case is in `BeatmapBackgroundWithStoryboard.load`. --- osu.Game/Beatmaps/WorkingBeatmapCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs index 0f3d61f527..78eed626f2 100644 --- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs +++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs @@ -264,7 +264,7 @@ namespace osu.Game.Beatmaps if (beatmapFileStream == null) { Logger.Log($"Beatmap failed to load (file {BeatmapInfo.Path} not found on disk at expected location {fileStorePath})", level: LogLevel.Error); - return null; + return new Storyboard(); } using (var reader = new LineBufferedReader(beatmapFileStream)) From 430938fbb2c9591cb5222187e118fca4e6ea3832 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 12 Jun 2023 21:47:13 +0900 Subject: [PATCH 1202/1400] allow custom username color for chatLine user's color (e.g. green for NAT) will be ignore --- .../Online/TestSceneChatLineTruncation.cs | 8 +++++-- osu.Game/Overlays/Chat/ChatLine.cs | 22 ++++++++++++++++++- .../Overlays/Chat/DrawableChatUsername.cs | 10 ++++++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index 32d95ec8dc..d816555237 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -38,10 +38,13 @@ namespace osu.Game.Tests.Visual.Online private void clear() => AddStep("clear messages", textContainer.Clear); - private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null) + private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null, Colour4? color = null) { int index = textContainer.Count + 1; - var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)); + var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)) + { + UsernameColour = color + }; textContainer.Add(newLine); } @@ -51,6 +54,7 @@ namespace osu.Game.Tests.Visual.Online addMessageWithChecks($"Wide {a} character username.", username: new string('w', a)); addMessageWithChecks("Short name with spaces.", username: "sho rt name"); addMessageWithChecks("Long name with spaces.", username: "long name with s p a c e s"); + addMessageWithChecks("message with custom color", username: "I have custom color", color: Colour4.Green); } private class DummyMessage : Message diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index c85206d5f7..5691a61fc4 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.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 System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -18,6 +19,7 @@ using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Chat @@ -66,6 +68,24 @@ namespace osu.Game.Overlays.Chat private Container? highlight; + private Colour4? usernameColour; + + /// + /// if set, it will override or . + /// Must be set when constructor, otherwise throw . + /// + public Colour4? UsernameColour + { + get => usernameColour; + set + { + if (drawableUsername != null) + throw new InvalidOperationException("Can't change Username color after DrawableChatUsername created"); + + usernameColour = value; + } + } + public ChatLine(Message message) { Message = message; @@ -103,7 +123,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername = new DrawableChatUsername(message.Sender) + drawableUsername = new DrawableChatUsername(message.Sender, usernameColour) { Width = UsernameWidth, FontSize = FontSize, diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 4b4afc204c..57fddf0575 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Chat private readonly Drawable colouredDrawable; - public DrawableChatUsername(APIUser user) + public DrawableChatUsername(APIUser user, Color4? customColor = null) { this.user = user; @@ -92,6 +92,14 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.TopRight, }; + if (customColor != null) + { + AccentColour = customColor.Value; + + Add(colouredDrawable = drawableText); + return; + } + if (string.IsNullOrWhiteSpace(user.Colour)) { AccentColour = default_colours[user.Id % default_colours.Length]; From 2da8335da21d7ded7a4553928dd75054e84a2899 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 12 Jun 2023 21:56:37 +0900 Subject: [PATCH 1203/1400] let team member color match their team color --- .../TestSceneTournamentMatchChatDisplay.cs | 15 +++++++++++++ .../Components/TournamentMatchChatDisplay.cs | 21 ++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index d9ae8df651..5128add9bd 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -3,11 +3,14 @@ #nullable disable +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; using osu.Game.Tests.Visual; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; @@ -86,6 +89,12 @@ namespace osu.Game.Tournament.Tests.Components Content = "I am team red." })); + AddUntilStep("message from team red is red color", () => + { + var chatLine = this.ChildrenOfType().FirstOrDefault(m => m.Message.Sender.OnlineID == redUser.OnlineID); + return chatLine!.UsernameColour == TournamentGame.COLOUR_RED; + }); + AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = redUser.ToAPIUser(), @@ -98,6 +107,12 @@ namespace osu.Game.Tournament.Tests.Components Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." })); + AddUntilStep("message from team blue is blue color", () => + { + var chatLine = this.ChildrenOfType().FirstOrDefault(m => m.Message.Sender.OnlineID == blueUser.OnlineID); + return chatLine!.UsernameColour == TournamentGame.COLOUR_BLUE; + }); + AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = admin, diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index 8a0dd6e336..2a2e45d70c 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -21,6 +21,9 @@ namespace osu.Game.Tournament.Components private ChannelManager manager; + [Resolved] + private LadderInfo ladderInfo { get; set; } + public TournamentMatchChatDisplay() { RelativeSizeAxes = Axes.X; @@ -71,7 +74,7 @@ namespace osu.Game.Tournament.Components public void Contract() => this.FadeOut(200); - protected override ChatLine CreateMessage(Message message) => new MatchMessage(message); + protected override ChatLine CreateMessage(Message message) => new MatchMessage(message, ladderInfo); protected override StandAloneDrawableChannel CreateDrawableChannel(Channel channel) => new MatchChannel(channel); @@ -86,19 +89,13 @@ namespace osu.Game.Tournament.Components protected partial class MatchMessage : StandAloneMessage { - public MatchMessage(Message message) + public MatchMessage(Message message, LadderInfo info) : base(message) { - } - - private void load(LadderInfo info) - { - // if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == Message.Sender.Id)) - // SenderText.Colour = TournamentGame.COLOUR_RED; - // else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == Message.Sender.Id)) - // SenderText.Colour = TournamentGame.COLOUR_BLUE; - // else if (Message.Sender.Colour != null) - // SenderText.Colour = ColourBox.Colour = Color4Extensions.FromHex(Message.Sender.Colour); + if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + UsernameColour = TournamentGame.COLOUR_RED; + else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + UsernameColour = TournamentGame.COLOUR_BLUE; } } } From 27b99ea923a590a09dea50905031daa5a7a112bb Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 13 Jun 2023 00:39:25 +0900 Subject: [PATCH 1204/1400] use `{ get; init; }` --- .../TestSceneTournamentMatchChatDisplay.cs | 10 +--- osu.Game/Overlays/Chat/ChatLine.cs | 49 ++++++++++--------- .../Overlays/Chat/DrawableChatUsername.cs | 12 +---- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 5128add9bd..fada340cf7 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -90,10 +90,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team red is red color", () => - { - var chatLine = this.ChildrenOfType().FirstOrDefault(m => m.Message.Sender.OnlineID == redUser.OnlineID); - return chatLine!.UsernameColour == TournamentGame.COLOUR_RED; - }); + this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_RED)); AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { @@ -108,10 +105,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team blue is blue color", () => - { - var chatLine = this.ChildrenOfType().FirstOrDefault(m => m.Message.Sender.OnlineID == blueUser.OnlineID); - return chatLine!.UsernameColour == TournamentGame.COLOUR_BLUE; - }); + this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_BLUE)); AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 5691a61fc4..3e484d962b 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -21,6 +20,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; +using osuTK.Graphics; namespace osu.Game.Overlays.Chat { @@ -68,23 +68,10 @@ namespace osu.Game.Overlays.Chat private Container? highlight; - private Colour4? usernameColour; - /// /// if set, it will override or . - /// Must be set when constructor, otherwise throw . /// - public Colour4? UsernameColour - { - get => usernameColour; - set - { - if (drawableUsername != null) - throw new InvalidOperationException("Can't change Username color after DrawableChatUsername created"); - - usernameColour = value; - } - } + public Color4? UsernameColour { get; init; } public ChatLine(Message message) { @@ -100,6 +87,28 @@ namespace osu.Game.Overlays.Chat configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); prefer24HourTime.BindValueChanged(_ => updateTimestamp()); + if (UsernameColour != null) + { + drawableUsername = new DrawableChatUsername(message.Sender) + { + AccentColour = UsernameColour.Value + }; + } + else + { + drawableUsername = new DrawableChatUsername(message.Sender); + } + + drawableUsername.With(u => + { + u.Width = UsernameWidth; + u.FontSize = FontSize; + u.AutoSizeAxes = Axes.Y; + u.Origin = Anchor.TopRight; + u.Anchor = Anchor.TopRight; + u.Margin = new MarginPadding { Horizontal = Spacing }; + }); + InternalChild = new GridContainer { RelativeSizeAxes = Axes.X, @@ -123,15 +132,7 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername = new DrawableChatUsername(message.Sender, usernameColour) - { - Width = UsernameWidth, - FontSize = FontSize, - AutoSizeAxes = Axes.Y, - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Margin = new MarginPadding { Horizontal = Spacing }, - }, + drawableUsername, drawableContentFlow = new LinkFlowContainer(styleMessageContent) { AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 57fddf0575..9b802a8070 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Chat { public Action? ReportRequested; - public Color4 AccentColour { get; } + public Color4 AccentColour { get; init; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => colouredDrawable.ReceivePositionalInputAt(screenSpacePos); @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Chat private readonly Drawable colouredDrawable; - public DrawableChatUsername(APIUser user, Color4? customColor = null) + public DrawableChatUsername(APIUser user) { this.user = user; @@ -92,14 +92,6 @@ namespace osu.Game.Overlays.Chat Origin = Anchor.TopRight, }; - if (customColor != null) - { - AccentColour = customColor.Value; - - Add(colouredDrawable = drawableText); - return; - } - if (string.IsNullOrWhiteSpace(user.Colour)) { AccentColour = default_colours[user.Id % default_colours.Length]; From f30c1a564fa074b4ffc1167cb34acdd35b4e68e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 01:08:51 +0900 Subject: [PATCH 1205/1400] Add basic setup for score migration --- osu.Game/Database/RealmAccess.cs | 50 ++++++++- .../StandardisedScoreMigrationTools.cs | 100 ++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Database/StandardisedScoreMigrationTools.cs diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 63ab18db8c..4c55a408c4 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -28,7 +28,10 @@ using osu.Game.IO.Legacy; using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Skinning; @@ -76,8 +79,9 @@ namespace osu.Game.Database /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. /// 27 2023-06-06 Added EditorTimestamp to BeatmapInfo. /// 28 2023-06-08 Added IsLegacyScore to ScoreInfo, parsed from replay files. + /// 29 2023-06-12 Run migration of old lazer scores to be best-effort in the new scoring number space. No actual realm changes. /// - private const int schema_version = 28; + private const int schema_version = 29; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. @@ -930,6 +934,28 @@ namespace osu.Game.Database break; } + + case 29: + { + var scores = migration.NewRealm + .All() + .Where(s => !s.IsLegacyScore); + + foreach (var score in scores) + { + // Recalculate the old-style standardised score to see if this was an old lazer score. + long oldStandardised = StandardisedScoreMigrationTools.GetOldStandardised(score); + + if (oldStandardised == score.TotalScore) + { + long calculatedNew = StandardisedScoreMigrationTools.GetNewStandardised(score); + Logger.Log($"Converting score {score.Rank} {score.Accuracy:P1} {score.TotalScore} -> {calculatedNew}"); + score.TotalScore = calculatedNew; + } + } + + break; + } } } @@ -1151,4 +1177,26 @@ namespace osu.Game.Database } } } + + internal class FakeHit : HitObject + { + private readonly Judgement judgement; + + public override Judgement CreateJudgement() => judgement; + + public FakeHit(Judgement judgement) + { + this.judgement = judgement; + } + } + + internal class FakeJudgement : Judgement + { + public override HitResult MaxResult { get; } + + public FakeJudgement(HitResult result) + { + MaxResult = result; + } + } } diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs new file mode 100644 index 0000000000..3133095df6 --- /dev/null +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -0,0 +1,100 @@ +// 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 System.Diagnostics; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; + +namespace osu.Game.Database +{ + public static class StandardisedScoreMigrationTools + { + public static long GetNewStandardised(ScoreInfo score) + { + var processor = score.Ruleset.CreateInstance().CreateScoreProcessor(); + + var beatmap = new Beatmap(); + + var maximumJudgements = score.MaximumStatistics + .Where(kvp => kvp.Key.AffectsCombo()) + .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) + .SelectMany(kvp => Enumerable.Repeat(new FakeJudgement(kvp.Key), kvp.Value)) + .ToList(); + + // This is a list of all results, ordered from best to worst. + // We are constructing a "best possible" score from the statistics provided because it's the best we can do. + List sortedHits = score.Statistics + .Where(kvp => kvp.Key.AffectsCombo() && kvp.Key != HitResult.Miss && kvp.Key != HitResult.LargeTickMiss) + .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) + .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value)) + .ToList(); + + foreach (var judgement in maximumJudgements) + beatmap.HitObjects.Add(new FakeHit(judgement)); + + processor.ApplyBeatmap(beatmap); + + Queue misses = new Queue(score.Statistics + .Where(kvp => kvp.Key == HitResult.Miss || kvp.Key == HitResult.LargeTickMiss) + .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value))); + + int maxJudgementIndex = 0; + + foreach (var result in sortedHits) + { + if (processor.Combo.Value == score.MaxCombo) + { + processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) + { + Type = misses.Dequeue(), + }); + } + + // TODO: pass a Judgement with correct MaxResult + processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) + { + Type = result + }); + } + + var bonusHits = score.Statistics + .Where(kvp => kvp.Key.IsBonus()) + .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value)); + + foreach (var result in bonusHits) + processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(result)) { Type = result }); + + Debug.Assert(processor.HighestCombo.Value == score.MaxCombo); + + return processor.TotalScore.Value; + } + + public static long GetOldStandardised(ScoreInfo score) + { + double accuracyScore = + (double)score.Statistics.Where(kvp => kvp.Key.AffectsAccuracy()).Sum(kvp => Judgement.ToNumericResult(kvp.Key) * kvp.Value) + / score.MaximumStatistics.Where(kvp => kvp.Key.AffectsAccuracy()).Sum(kvp => Judgement.ToNumericResult(kvp.Key) * kvp.Value); + double comboScore = (double)score.MaxCombo / score.MaximumStatistics.Where(kvp => kvp.Key.AffectsCombo()).Sum(kvp => kvp.Value); + double bonusScore = score.Statistics.Where(kvp => kvp.Key.IsBonus()).Sum(kvp => Judgement.ToNumericResult(kvp.Key) * kvp.Value); + + double accuracyPortion = 0.3; + + switch (score.RulesetID) + { + case 1: + accuracyPortion = 0.75; + break; + + case 3: + accuracyPortion = 0.99; + break; + } + + return (long)(1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore); + } + } +} From d19f8997fc2288df0ec333fca0369be974f0c0d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 01:39:38 +0900 Subject: [PATCH 1206/1400] Account for scores which don't have correct maximum statistics populated --- .../StandardisedScoreMigrationTools.cs | 65 +++++++++++++++++-- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 3133095df6..e8f1fd640b 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -15,10 +15,13 @@ namespace osu.Game.Database { public static long GetNewStandardised(ScoreInfo score) { - var processor = score.Ruleset.CreateInstance().CreateScoreProcessor(); + var ruleset = score.Ruleset.CreateInstance(); + var processor = ruleset.CreateScoreProcessor(); var beatmap = new Beatmap(); + HitResult maxRulesetJudgement = ruleset.GetHitResults().First().result; + var maximumJudgements = score.MaximumStatistics .Where(kvp => kvp.Key.AffectsCombo()) .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) @@ -28,11 +31,20 @@ namespace osu.Game.Database // This is a list of all results, ordered from best to worst. // We are constructing a "best possible" score from the statistics provided because it's the best we can do. List sortedHits = score.Statistics - .Where(kvp => kvp.Key.AffectsCombo() && kvp.Key != HitResult.Miss && kvp.Key != HitResult.LargeTickMiss) + .Where(kvp => kvp.Key.AffectsCombo()) .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value)) .ToList(); + if (maximumJudgements.Count != sortedHits.Count) + { + // Older scores may not have maximum judgements populated correctly. + // In this case we need to fill them. + maximumJudgements = sortedHits + .Select(r => new FakeJudgement(getMaxJudgementFor(r, maxRulesetJudgement))) + .ToList(); + } + foreach (var judgement in maximumJudgements) beatmap.HitObjects.Add(new FakeHit(judgement)); @@ -46,15 +58,29 @@ namespace osu.Game.Database foreach (var result in sortedHits) { + // misses are handled from the queue. + if (result == HitResult.Miss || result == HitResult.LargeTickMiss) + continue; + if (processor.Combo.Value == score.MaxCombo) { - processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) + if (misses.Count > 0) { - Type = misses.Dequeue(), - }); + processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) + { + Type = misses.Dequeue(), + }); + } + else + { + // worst case scenario, insert a miss. + processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(getMaxJudgementFor(HitResult.Miss, maxRulesetJudgement))) + { + Type = HitResult.Miss, + }); + } } - // TODO: pass a Judgement with correct MaxResult processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) { Type = result @@ -68,11 +94,36 @@ namespace osu.Game.Database foreach (var result in bonusHits) processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(result)) { Type = result }); - Debug.Assert(processor.HighestCombo.Value == score.MaxCombo); + // Not true for all scores for whatever reason. Oh well. + // Debug.Assert(processor.HighestCombo.Value == score.MaxCombo); return processor.TotalScore.Value; } + private static HitResult getMaxJudgementFor(HitResult hitResult, HitResult max) + { + switch (hitResult) + { + case HitResult.Miss: + case HitResult.Meh: + case HitResult.Ok: + case HitResult.Good: + case HitResult.Great: + case HitResult.Perfect: + return max; + + case HitResult.SmallTickMiss: + case HitResult.SmallTickHit: + return HitResult.SmallTickHit; + + case HitResult.LargeTickMiss: + case HitResult.LargeTickHit: + return HitResult.LargeTickHit; + } + + return HitResult.IgnoreHit; + } + public static long GetOldStandardised(ScoreInfo score) { double accuracyScore = From 0e9576acfb0d282dbde2046a3cdcfbe7e840efe3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 01:40:32 +0900 Subject: [PATCH 1207/1400] Remove logging and catch any kind of errors --- osu.Game/Database/RealmAccess.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 4c55a408c4..070738363a 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -944,13 +944,20 @@ namespace osu.Game.Database foreach (var score in scores) { // Recalculate the old-style standardised score to see if this was an old lazer score. - long oldStandardised = StandardisedScoreMigrationTools.GetOldStandardised(score); + bool oldScoreMatchesExpectations = StandardisedScoreMigrationTools.GetOldStandardised(score) == score.TotalScore; + // Some older score don't have correct statistics populated, so let's give them benefit of doubt. + bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); - if (oldStandardised == score.TotalScore) + if (oldScoreMatchesExpectations || scoreIsVeryOld) { - long calculatedNew = StandardisedScoreMigrationTools.GetNewStandardised(score); - Logger.Log($"Converting score {score.Rank} {score.Accuracy:P1} {score.TotalScore} -> {calculatedNew}"); - score.TotalScore = calculatedNew; + try + { + long calculatedNew = StandardisedScoreMigrationTools.GetNewStandardised(score); + score.TotalScore = calculatedNew; + } + catch + { + } } } From 0916ae1671b18cfba735f3804cbc56ecd57983a2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 01:48:32 +0900 Subject: [PATCH 1208/1400] Add basic profiling output of realm migrations --- osu.Game/Database/RealmAccess.cs | 8 ++++++++ osu.Game/Database/StandardisedScoreMigrationTools.cs | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 070738363a..cea307f255 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -37,6 +37,7 @@ using osu.Game.Scoring.Legacy; using osu.Game.Skinning; using Realms; using Realms.Exceptions; +using Stopwatch = System.Diagnostics.Stopwatch; namespace osu.Game.Database { @@ -728,6 +729,11 @@ namespace osu.Game.Database private void applyMigrationsForVersion(Migration migration, ulong targetVersion) { + Logger.Log($"Running realm migration to version {targetVersion}..."); + Stopwatch stopwatch = new Stopwatch(); + + stopwatch.Start(); + switch (targetVersion) { case 7: @@ -964,6 +970,8 @@ namespace osu.Game.Database break; } } + + Logger.Log($"Migration completed in {stopwatch.ElapsedMilliseconds}ms"); } private string? getRulesetShortNameFromLegacyID(long rulesetId) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index e8f1fd640b..f103ded6d5 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; From 87520ae4000ec34efbc22560d5566c8602acc782 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 02:05:00 +0900 Subject: [PATCH 1209/1400] Avoid overhead from retrieving `MaxCombo` inside loop from realm --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index f103ded6d5..b621b67cf8 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -14,6 +14,9 @@ namespace osu.Game.Database { public static long GetNewStandardised(ScoreInfo score) { + // Avoid retrieving from realm inside loops. + int maxCombo = score.MaxCombo; + var ruleset = score.Ruleset.CreateInstance(); var processor = ruleset.CreateScoreProcessor(); @@ -61,7 +64,7 @@ namespace osu.Game.Database if (result == HitResult.Miss || result == HitResult.LargeTickMiss) continue; - if (processor.Combo.Value == score.MaxCombo) + if (processor.Combo.Value == maxCombo) { if (misses.Count > 0) { From e0ebb000d697aebeab253bf810c371d020b7ec31 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 02:05:11 +0900 Subject: [PATCH 1210/1400] Avoid unnecessary operations during score processor simulation --- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 9 +++++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 09b5f0a6bc..b16c307206 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -30,6 +30,11 @@ namespace osu.Game.Rulesets.Scoring /// protected int MaxHits { get; private set; } + /// + /// Whether is currently running. + /// + protected bool IsSimulating { get; private set; } + /// /// The total number of judged s at the current point in time. /// @@ -146,6 +151,8 @@ namespace osu.Game.Rulesets.Scoring /// The to simulate. protected virtual void SimulateAutoplay(IBeatmap beatmap) { + IsSimulating = true; + foreach (var obj in beatmap.HitObjects) simulate(obj); @@ -163,6 +170,8 @@ namespace osu.Game.Rulesets.Scoring result.Type = GetSimulatedHitResult(judgement); ApplyResult(result); } + + IsSimulating = false; } protected override void Update() diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ac17de32d8..87f2b1e5ee 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -226,10 +226,13 @@ namespace osu.Game.Rulesets.Scoring ApplyScoreChange(result); - hitEvents.Add(CreateHitEvent(result)); - lastHitObject = result.HitObject; + if (!IsSimulating) + { + hitEvents.Add(CreateHitEvent(result)); + lastHitObject = result.HitObject; - updateScore(); + updateScore(); + } } /// From 385f6dbd84f3af5d76d984f09a489e5b44da15f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 02:12:23 +0900 Subject: [PATCH 1211/1400] Move local classes to their rightful location --- osu.Game/Database/RealmAccess.cs | 22 ------------------ .../StandardisedScoreMigrationTools.cs | 23 +++++++++++++++++++ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index cea307f255..1194e1d9f8 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -1192,26 +1192,4 @@ namespace osu.Game.Database } } } - - internal class FakeHit : HitObject - { - private readonly Judgement judgement; - - public override Judgement CreateJudgement() => judgement; - - public FakeHit(Judgement judgement) - { - this.judgement = judgement; - } - } - - internal class FakeJudgement : Judgement - { - public override HitResult MaxResult { get; } - - public FakeJudgement(HitResult result) - { - MaxResult = result; - } - } } diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index b621b67cf8..ec08168f7c 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -149,5 +150,27 @@ namespace osu.Game.Database return (long)(1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore); } + + private class FakeHit : HitObject + { + private readonly Judgement judgement; + + public override Judgement CreateJudgement() => judgement; + + public FakeHit(Judgement judgement) + { + this.judgement = judgement; + } + } + + private class FakeJudgement : Judgement + { + public override HitResult MaxResult { get; } + + public FakeJudgement(HitResult result) + { + MaxResult = result; + } + } } } From e9fb1f89326d549ee6f67e457daa471f1ee23467 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 02:15:08 +0900 Subject: [PATCH 1212/1400] Avoid tracking hit events altogether during migration --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 2 ++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index ec08168f7c..c06502b521 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -21,6 +21,8 @@ namespace osu.Game.Database var ruleset = score.Ruleset.CreateInstance(); var processor = ruleset.CreateScoreProcessor(); + processor.TrackHitEvents = false; + var beatmap = new Beatmap(); HitResult maxRulesetJudgement = ruleset.GetHitResults().First().result; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 87f2b1e5ee..f29e3533a0 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -30,6 +30,11 @@ namespace osu.Game.Rulesets.Scoring private const double accuracy_cutoff_c = 0.7; private const double accuracy_cutoff_d = 0; + /// + /// Whether should be populated during application of results. + /// + internal bool TrackHitEvents = true; + /// /// Invoked when this was reset from a replay frame. /// @@ -226,7 +231,7 @@ namespace osu.Game.Rulesets.Scoring ApplyScoreChange(result); - if (!IsSimulating) + if (!IsSimulating && TrackHitEvents) { hitEvents.Add(CreateHitEvent(result)); lastHitObject = result.HitObject; From afb5a9243a2b47e084ff1dc01f4ef2037ded3ea8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 05:13:22 +0900 Subject: [PATCH 1213/1400] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1194e1d9f8..663833575a 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -951,7 +951,7 @@ namespace osu.Game.Database { // Recalculate the old-style standardised score to see if this was an old lazer score. bool oldScoreMatchesExpectations = StandardisedScoreMigrationTools.GetOldStandardised(score) == score.TotalScore; - // Some older score don't have correct statistics populated, so let's give them benefit of doubt. + // Some older scores don't have correct statistics populated, so let's give them benefit of doubt. bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); if (oldScoreMatchesExpectations || scoreIsVeryOld) From 3304e41a3012492bf054460462ea449f1d55d002 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 05:20:29 +0900 Subject: [PATCH 1214/1400] Add more commenting --- .../StandardisedScoreMigrationTools.cs | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index c06502b521..edc3288f61 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -27,12 +27,6 @@ namespace osu.Game.Database HitResult maxRulesetJudgement = ruleset.GetHitResults().First().result; - var maximumJudgements = score.MaximumStatistics - .Where(kvp => kvp.Key.AffectsCombo()) - .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) - .SelectMany(kvp => Enumerable.Repeat(new FakeJudgement(kvp.Key), kvp.Value)) - .ToList(); - // This is a list of all results, ordered from best to worst. // We are constructing a "best possible" score from the statistics provided because it's the best we can do. List sortedHits = score.Statistics @@ -41,20 +35,29 @@ namespace osu.Game.Database .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value)) .ToList(); + // Attempt to use maximum statistics from the database. + var maximumJudgements = score.MaximumStatistics + .Where(kvp => kvp.Key.AffectsCombo()) + .OrderByDescending(kvp => Judgement.ToNumericResult(kvp.Key)) + .SelectMany(kvp => Enumerable.Repeat(new FakeJudgement(kvp.Key), kvp.Value)) + .ToList(); + + // Some older scores may not have maximum statistics populated correctly. + // In this case we need to fill them with best-known-defaults. if (maximumJudgements.Count != sortedHits.Count) { - // Older scores may not have maximum judgements populated correctly. - // In this case we need to fill them. maximumJudgements = sortedHits .Select(r => new FakeJudgement(getMaxJudgementFor(r, maxRulesetJudgement))) .ToList(); } + // This is required to get the correct maximum combo portion. foreach (var judgement in maximumJudgements) beatmap.HitObjects.Add(new FakeHit(judgement)); - processor.ApplyBeatmap(beatmap); + // Insert all misses into a queue. + // These will be nibbled at whenever we need to reset the combo. Queue misses = new Queue(score.Statistics .Where(kvp => kvp.Key == HitResult.Miss || kvp.Key == HitResult.LargeTickMiss) .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value))); @@ -63,7 +66,7 @@ namespace osu.Game.Database foreach (var result in sortedHits) { - // misses are handled from the queue. + // For the main part of this loop, ignore all misses, as they will be inserted from the queue. if (result == HitResult.Miss || result == HitResult.LargeTickMiss) continue; @@ -78,7 +81,8 @@ namespace osu.Game.Database } else { - // worst case scenario, insert a miss. + // We ran out of misses. But we can't let max combo increase beyond the known value, + // so let's forge a miss. processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(getMaxJudgementFor(HitResult.Miss, maxRulesetJudgement))) { Type = HitResult.Miss, @@ -169,9 +173,9 @@ namespace osu.Game.Database { public override HitResult MaxResult { get; } - public FakeJudgement(HitResult result) + public FakeJudgement(HitResult maxResult) { - MaxResult = result; + MaxResult = maxResult; } } } From c1b0c60e79c9b828b6ed69e8e34ec82f5e6cda58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 05:24:04 +0900 Subject: [PATCH 1215/1400] Ensure all misses are dequeued --- .../StandardisedScoreMigrationTools.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index edc3288f61..d980f7a858 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -15,6 +15,8 @@ namespace osu.Game.Database { public static long GetNewStandardised(ScoreInfo score) { + int maxJudgementIndex = 0; + // Avoid retrieving from realm inside loops. int maxCombo = score.MaxCombo; @@ -62,33 +64,15 @@ namespace osu.Game.Database .Where(kvp => kvp.Key == HitResult.Miss || kvp.Key == HitResult.LargeTickMiss) .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value))); - int maxJudgementIndex = 0; - foreach (var result in sortedHits) { // For the main part of this loop, ignore all misses, as they will be inserted from the queue. if (result == HitResult.Miss || result == HitResult.LargeTickMiss) continue; + // Reset combo if required. if (processor.Combo.Value == maxCombo) - { - if (misses.Count > 0) - { - processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) - { - Type = misses.Dequeue(), - }); - } - else - { - // We ran out of misses. But we can't let max combo increase beyond the known value, - // so let's forge a miss. - processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(getMaxJudgementFor(HitResult.Miss, maxRulesetJudgement))) - { - Type = HitResult.Miss, - }); - } - } + insertMiss(); processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) { @@ -96,6 +80,10 @@ namespace osu.Game.Database }); } + // Ensure we haven't forgotten any misses. + while (misses.Count > 0) + insertMiss(); + var bonusHits = score.Statistics .Where(kvp => kvp.Key.IsBonus()) .SelectMany(kvp => Enumerable.Repeat(kvp.Key, kvp.Value)); @@ -107,6 +95,26 @@ namespace osu.Game.Database // Debug.Assert(processor.HighestCombo.Value == score.MaxCombo); return processor.TotalScore.Value; + + void insertMiss() + { + if (misses.Count > 0) + { + processor.ApplyResult(new JudgementResult(null!, maximumJudgements[maxJudgementIndex++]) + { + Type = misses.Dequeue(), + }); + } + else + { + // We ran out of misses. But we can't let max combo increase beyond the known value, + // so let's forge a miss. + processor.ApplyResult(new JudgementResult(null!, new FakeJudgement(getMaxJudgementFor(HitResult.Miss, maxRulesetJudgement))) + { + Type = HitResult.Miss, + }); + } + } } private static HitResult getMaxJudgementFor(HitResult hitResult, HitResult max) From 422e87f0ec362506ccbe16943f3732a14c9018cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 05:30:12 +0900 Subject: [PATCH 1216/1400] Fix weird usings --- osu.Game/Database/RealmAccess.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 663833575a..68a4679656 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -28,16 +28,12 @@ using osu.Game.IO.Legacy; using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Skinning; using Realms; using Realms.Exceptions; -using Stopwatch = System.Diagnostics.Stopwatch; namespace osu.Game.Database { From 0ab9a48f004be0e6b044391eed4b2677bf07180d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 11:44:52 +0900 Subject: [PATCH 1217/1400] Fix score not updating when `TrackHitEvents` is set to `false` --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index f29e3533a0..7d2bc17bda 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -33,6 +33,9 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether should be populated during application of results. /// + /// + /// Should only be disabled for special cases. + /// When disabled, cannot be used. internal bool TrackHitEvents = true; /// @@ -231,10 +234,13 @@ namespace osu.Game.Rulesets.Scoring ApplyScoreChange(result); - if (!IsSimulating && TrackHitEvents) + if (!IsSimulating) { - hitEvents.Add(CreateHitEvent(result)); - lastHitObject = result.HitObject; + if (TrackHitEvents) + { + hitEvents.Add(CreateHitEvent(result)); + lastHitObject = result.HitObject; + } updateScore(); } @@ -250,6 +256,9 @@ namespace osu.Game.Rulesets.Scoring protected sealed override void RevertResultInternal(JudgementResult result) { + if (!TrackHitEvents) + throw new InvalidOperationException(@$"Rewind is not supported when {nameof(TrackHitEvents)} is disabled."); + Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; From 4cdd4561c4e00c5253ff10d735046bd0be21f715 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 13 Jun 2023 14:17:32 +0900 Subject: [PATCH 1218/1400] Add a few more search keywords for offset settings https://github.com/ppy/osu/discussions/23898#discussioncomment-6159206 --- osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 1755c12f94..fc354027c1 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { protected override LocalisableString Header => AudioSettingsStrings.OffsetHeader; - public override IEnumerable FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "universal", "uo", "timing" }); + public override IEnumerable FilterTerms => base.FilterTerms.Concat(new LocalisableString[] { "universal", "uo", "timing", "delay", "latency" }); [BackgroundDependencyLoader] private void load(OsuConfigManager config) From a5c3c9a93f4adf8ee0ceab485eb650de8e1acf70 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 12 Jun 2023 23:30:08 -0700 Subject: [PATCH 1219/1400] Use `FillFlowContainer` instead of `GridContainer` for drawable room background gradient --- .../Lounge/Components/DrawableRoom.cs | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 8c85a8235c..522438227a 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -103,29 +103,25 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components CornerRadius = CORNER_RADIUS, Children = new Drawable[] { - new GridContainer + new FillFlowContainer { RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] + Direction = FillDirection.Horizontal, + Children = new Drawable[] { - new Dimension(GridSizeMode.Relative, 0.2f) - }, - Content = new[] - { - new Drawable[] + new Box { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)) - }, - } - } + RelativeSizeAxes = Axes.Both, + Colour = colours.Background5, + Width = 0.2f, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)), + Width = 0.8f, + }, + }, }, new Container { From 432b5e2d258091d27f3b8262fddfa35aa6b83f50 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Tue, 13 Jun 2023 15:47:44 +0900 Subject: [PATCH 1220/1400] move Inverted and color logic to ChatLine --- .../TestSceneTournamentMatchChatDisplay.cs | 4 +- osu.Game/Overlays/Chat/ChatLine.cs | 80 ++++++++++++++----- .../Overlays/Chat/DrawableChatUsername.cs | 66 ++++----------- 3 files changed, 76 insertions(+), 74 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index fada340cf7..71d8cbeea7 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team red is red color", () => - this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_RED)); + this.ChildrenOfType().Any(s => s.AccentColour.Value == TournamentGame.COLOUR_RED)); AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { @@ -105,7 +105,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team blue is blue color", () => - this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_BLUE)); + this.ChildrenOfType().Any(s => s.AccentColour.Value == TournamentGame.COLOUR_BLUE)); AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 3e484d962b..2931685239 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -21,6 +21,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osuTK.Graphics; +using Message = osu.Game.Online.Chat.Message; namespace osu.Game.Overlays.Chat { @@ -69,9 +70,9 @@ namespace osu.Game.Overlays.Chat private Container? highlight; /// - /// if set, it will override or . + /// if set, it will override or . /// - public Color4? UsernameColour { get; init; } + public Color4 UsernameColour { get; init; } public ChatLine(Message message) { @@ -79,6 +80,11 @@ namespace osu.Game.Overlays.Chat RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + + // If we have custom value, this value will be override. + UsernameColour = !string.IsNullOrEmpty(message.Sender.Colour) + ? Color4Extensions.FromHex(message.Sender.Colour) + : default_colours[message.SenderId % default_colours.Length]; } [BackgroundDependencyLoader] @@ -87,27 +93,18 @@ namespace osu.Game.Overlays.Chat configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); prefer24HourTime.BindValueChanged(_ => updateTimestamp()); - if (UsernameColour != null) + drawableUsername = new DrawableChatUsername(message.Sender) { - drawableUsername = new DrawableChatUsername(message.Sender) - { - AccentColour = UsernameColour.Value - }; - } - else - { - drawableUsername = new DrawableChatUsername(message.Sender); - } + Width = UsernameWidth, + FontSize = FontSize, + AutoSizeAxes = Axes.Y, + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Margin = new MarginPadding { Horizontal = Spacing }, + Inverted = !string.IsNullOrEmpty(message.Sender.Colour), + }; - drawableUsername.With(u => - { - u.Width = UsernameWidth; - u.FontSize = FontSize; - u.AutoSizeAxes = Axes.Y; - u.Origin = Anchor.TopRight; - u.Anchor = Anchor.TopRight; - u.Margin = new MarginPadding { Horizontal = Spacing }; - }); + drawableUsername.AccentColour.Value = UsernameColour; InternalChild = new GridContainer { @@ -178,7 +175,7 @@ namespace osu.Game.Overlays.Chat CornerRadius = 2f, Masking = true, RelativeSizeAxes = Axes.Both, - Colour = drawableUsername.AccentColour.Darken(1f), + Colour = drawableUsername.AccentColour.Value.Darken(1f), Depth = float.MaxValue, Child = new Box { RelativeSizeAxes = Axes.Both } }); @@ -216,5 +213,44 @@ namespace osu.Game.Overlays.Chat { drawableTimestamp.Text = message.Timestamp.LocalDateTime.ToLocalisableString(prefer24HourTime.Value ? @"HH:mm:ss" : @"hh:mm:ss tt"); } + + private static readonly Color4[] default_colours = + { + Color4Extensions.FromHex("588c7e"), + Color4Extensions.FromHex("b2a367"), + Color4Extensions.FromHex("c98f65"), + Color4Extensions.FromHex("bc5151"), + Color4Extensions.FromHex("5c8bd6"), + Color4Extensions.FromHex("7f6ab7"), + Color4Extensions.FromHex("a368ad"), + Color4Extensions.FromHex("aa6880"), + + Color4Extensions.FromHex("6fad9b"), + Color4Extensions.FromHex("f2e394"), + Color4Extensions.FromHex("f2ae72"), + Color4Extensions.FromHex("f98f8a"), + Color4Extensions.FromHex("7daef4"), + Color4Extensions.FromHex("a691f2"), + Color4Extensions.FromHex("c894d3"), + Color4Extensions.FromHex("d895b0"), + + Color4Extensions.FromHex("53c4a1"), + Color4Extensions.FromHex("eace5c"), + Color4Extensions.FromHex("ea8c47"), + Color4Extensions.FromHex("fc4f4f"), + Color4Extensions.FromHex("3d94ea"), + Color4Extensions.FromHex("7760ea"), + Color4Extensions.FromHex("af52c6"), + Color4Extensions.FromHex("e25696"), + + Color4Extensions.FromHex("677c66"), + Color4Extensions.FromHex("9b8732"), + Color4Extensions.FromHex("8c5129"), + Color4Extensions.FromHex("8c3030"), + Color4Extensions.FromHex("1f5d91"), + Color4Extensions.FromHex("4335a5"), + Color4Extensions.FromHex("812a96"), + Color4Extensions.FromHex("992861"), + }; } } diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 9b802a8070..05772051da 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -33,7 +33,9 @@ namespace osu.Game.Overlays.Chat { public Action? ReportRequested; - public Color4 AccentColour { get; init; } + public Bindable AccentColour { get; } = new Bindable(); + + public bool Inverted { get; init; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => colouredDrawable.ReceivePositionalInputAt(screenSpacePos); @@ -75,7 +77,7 @@ namespace osu.Game.Overlays.Chat private readonly APIUser user; private readonly OsuSpriteText drawableText; - private readonly Drawable colouredDrawable; + private Drawable colouredDrawable = null!; public DrawableChatUsername(APIUser user) { @@ -91,17 +93,17 @@ namespace osu.Game.Overlays.Chat Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }; + } - if (string.IsNullOrWhiteSpace(user.Colour)) + [BackgroundDependencyLoader] + private void load() + { + if (!Inverted) { - AccentColour = default_colours[user.Id % default_colours.Length]; - Add(colouredDrawable = drawableText); } else { - AccentColour = Color4Extensions.FromHex(user.Colour); - Add(new Container { Anchor = Anchor.TopRight, @@ -143,9 +145,12 @@ namespace osu.Game.Overlays.Chat protected override void LoadComplete() { base.LoadComplete(); - drawableText.Colour = colours.ChatBlue; - colouredDrawable.Colour = AccentColour; + + AccentColour.BindValueChanged(c => + { + colouredDrawable.Colour = c.NewValue; + }, true); } public MenuItem[] ContextMenuItems @@ -191,7 +196,7 @@ namespace osu.Game.Overlays.Chat protected override bool OnHover(HoverEvent e) { - colouredDrawable.FadeColour(AccentColour.Lighten(0.6f), 30, Easing.OutQuint); + colouredDrawable.FadeColour(AccentColour.Value.Lighten(0.6f), 30, Easing.OutQuint); return base.OnHover(e); } @@ -200,46 +205,7 @@ namespace osu.Game.Overlays.Chat { base.OnHoverLost(e); - colouredDrawable.FadeColour(AccentColour, 800, Easing.OutQuint); + colouredDrawable.FadeColour(AccentColour.Value, 800, Easing.OutQuint); } - - private static readonly Color4[] default_colours = - { - Color4Extensions.FromHex("588c7e"), - Color4Extensions.FromHex("b2a367"), - Color4Extensions.FromHex("c98f65"), - Color4Extensions.FromHex("bc5151"), - Color4Extensions.FromHex("5c8bd6"), - Color4Extensions.FromHex("7f6ab7"), - Color4Extensions.FromHex("a368ad"), - Color4Extensions.FromHex("aa6880"), - - Color4Extensions.FromHex("6fad9b"), - Color4Extensions.FromHex("f2e394"), - Color4Extensions.FromHex("f2ae72"), - Color4Extensions.FromHex("f98f8a"), - Color4Extensions.FromHex("7daef4"), - Color4Extensions.FromHex("a691f2"), - Color4Extensions.FromHex("c894d3"), - Color4Extensions.FromHex("d895b0"), - - Color4Extensions.FromHex("53c4a1"), - Color4Extensions.FromHex("eace5c"), - Color4Extensions.FromHex("ea8c47"), - Color4Extensions.FromHex("fc4f4f"), - Color4Extensions.FromHex("3d94ea"), - Color4Extensions.FromHex("7760ea"), - Color4Extensions.FromHex("af52c6"), - Color4Extensions.FromHex("e25696"), - - Color4Extensions.FromHex("677c66"), - Color4Extensions.FromHex("9b8732"), - Color4Extensions.FromHex("8c5129"), - Color4Extensions.FromHex("8c3030"), - Color4Extensions.FromHex("1f5d91"), - Color4Extensions.FromHex("4335a5"), - Color4Extensions.FromHex("812a96"), - Color4Extensions.FromHex("992861"), - }; } } From 0adb399ea869c758796790edb8184df173c43f69 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 13 Jun 2023 00:09:58 -0700 Subject: [PATCH 1221/1400] Use anchor instead of `FillFlowContainer` --- .../Lounge/Components/DrawableRoom.cs | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 522438227a..f1fc751630 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -103,25 +103,19 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components CornerRadius = CORNER_RADIUS, Children = new Drawable[] { - new FillFlowContainer + new Box { RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colours.Background5, - Width = 0.2f, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)), - Width = 0.8f, - }, - }, + Colour = colours.Background5, + Width = 0.2f, + }, + new Box + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)), + Width = 0.8f, }, new Container { From 51451bd53e92c4e160bfee4d319669cc9937b7e8 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Wed, 14 Jun 2023 01:32:27 +0900 Subject: [PATCH 1222/1400] fix test --- .../Visual/Online/TestSceneChatLineTruncation.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index d816555237..d1c380e2c7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -41,10 +41,14 @@ namespace osu.Game.Tests.Visual.Online private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null, Colour4? color = null) { int index = textContainer.Count + 1; - var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)) - { - UsernameColour = color - }; + + var newLine = color != null + ? new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)) + { + UsernameColour = color.Value + } + : new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)); + textContainer.Add(newLine); } From 3334323eb7cdecf753fe3266e5edc85e332b6373 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Jun 2023 01:54:57 +0900 Subject: [PATCH 1223/1400] Run `updateScore` on `Reset` for good measure --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7d2bc17bda..35a7dfe369 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -328,6 +328,9 @@ namespace osu.Game.Rulesets.Scoring /// Whether to store the current state of the for future use. protected override void Reset(bool storeResults) { + // Run one last time to store max values. + updateScore(); + base.Reset(storeResults); hitEvents.Clear(); From 6205864c62571faea9a6af432091c3f7b30a4fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 13 Jun 2023 18:45:35 +0200 Subject: [PATCH 1224/1400] Fix score migration not considering mod multipliers --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index d980f7a858..af91bee9e4 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -57,6 +57,7 @@ namespace osu.Game.Database foreach (var judgement in maximumJudgements) beatmap.HitObjects.Add(new FakeHit(judgement)); processor.ApplyBeatmap(beatmap); + processor.Mods.Value = score.Mods; // Insert all misses into a queue. // These will be nibbled at whenever we need to reset the combo. @@ -162,7 +163,12 @@ namespace osu.Game.Database break; } - return (long)(1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore); + double modMultiplier = 1; + + foreach (var mod in score.Mods) + modMultiplier *= mod.ScoreMultiplier; + + return (long)((1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore) * modMultiplier); } private class FakeHit : HitObject From f553efba8a03639f8e086a244eabfbc8b2527759 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Jun 2023 02:29:56 +0900 Subject: [PATCH 1225/1400] Fix playback controls in editor handling key repeat when they probably shouldn't Closes https://github.com/ppy/osu/issues/23903. --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 3 +++ osu.Game/Screens/Edit/Editor.cs | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 72c299f443..431336aa60 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -76,6 +76,9 @@ namespace osu.Game.Screens.Edit.Components protected override bool OnKeyDown(KeyDownEvent e) { + if (e.Repeat) + return false; + switch (e.Key) { case Key.Space: diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index bb052b1d22..74947aab09 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -533,6 +533,9 @@ namespace osu.Game.Screens.Edit // Track traversal keys. // Matching osu-stable implementations. case Key.Z: + if (e.Repeat) + return false; + // Seek to first object time, or track start if already there. double? firstObjectTime = editorBeatmap.HitObjects.FirstOrDefault()?.StartTime; @@ -543,12 +546,18 @@ namespace osu.Game.Screens.Edit return true; case Key.X: + if (e.Repeat) + return false; + // Restart playback from beginning of track. clock.Seek(0); clock.Start(); return true; case Key.C: + if (e.Repeat) + return false; + // Pause or resume. if (clock.IsRunning) clock.Stop(); @@ -557,6 +566,9 @@ namespace osu.Game.Screens.Edit return true; case Key.V: + if (e.Repeat) + return false; + // Seek to last object time, or track end if already there. // Note that in osu-stable subsequent presses when at track end won't return to last object. // This has intentionally been changed to make it more useful. From df49a48d4d70e3a365cccd76778c0b8f60f0adb2 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 13 Jun 2023 13:48:47 -0700 Subject: [PATCH 1226/1400] Put left and right details inside `GridContainer` --- .../Lounge/Components/DrawableRoom.cs | 163 ++++++++++-------- 1 file changed, 89 insertions(+), 74 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index f1fc751630..f26d9b168d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -117,94 +117,109 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Colour = ColourInfo.GradientHorizontal(colours.Background5, colours.Background5.Opacity(0.3f)), Width = 0.8f, }, - new Container + new GridContainer { - Name = @"Left details", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + ColumnDimensions = new[] { - Left = 20, - Vertical = 5 + new Dimension(), + new Dimension(GridSizeMode.AutoSize), }, - Children = new Drawable[] + Content = new[] { - new FillFlowContainer + new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new Container { - new FillFlowContainer + Name = @"Left details", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - Children = new Drawable[] - { - new RoomStatusPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - specialCategoryPill = new RoomSpecialCategoryPill - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft - }, - endDateInfo = new EndDateInfo - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - } + Left = 20, + Vertical = 5 }, - new FillFlowContainer + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = 3 }, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new FillFlowContainer { - new RoomNameText(), - new RoomStatusText() + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + Children = new Drawable[] + { + new RoomStatusPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + specialCategoryPill = new RoomSpecialCategoryPill + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + endDateInfo = new EndDateInfo + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Top = 3 }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new RoomNameText(), + new RoomStatusText() + } + } + }, + }, + new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5), + ChildrenEnumerable = CreateBottomDetails() + } + } + }, + new FillFlowContainer + { + Name = "Right content", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Spacing = new Vector2(5), + Padding = new MarginPadding + { + Right = 10, + Vertical = 20, + }, + Children = new Drawable[] + { + ButtonsContainer, + drawableRoomParticipantsList = new DrawableRoomParticipantsList + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + NumberOfCircles = NumberOfAvatars } } }, - }, - new FillFlowContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5), - ChildrenEnumerable = CreateBottomDetails() - } - } - }, - new FillFlowContainer - { - Name = "Right content", - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Spacing = new Vector2(5), - Padding = new MarginPadding - { - Right = 10, - Vertical = 20, - }, - Children = new Drawable[] - { - ButtonsContainer, - drawableRoomParticipantsList = new DrawableRoomParticipantsList - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - NumberOfCircles = NumberOfAvatars } } }, From 2a3f2ff122e0ec8fe0d26ddc9a6b72c4ca253af9 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 13 Jun 2023 13:56:29 -0700 Subject: [PATCH 1227/1400] Truncate room name text --- .../Lounge/Components/DrawableRoom.cs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index f26d9b168d..11c649a9ae 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -179,7 +179,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Direction = FillDirection.Vertical, Children = new Drawable[] { - new RoomNameText(), + new TruncatingSpriteText + { + RelativeSizeAxes = Axes.X, + Font = OsuFont.GetFont(size: 28), + Current = { BindTarget = Room.Name } + }, new RoomStatusText() } } @@ -316,23 +321,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components return pills; } - private partial class RoomNameText : OsuSpriteText - { - [Resolved(typeof(Room), nameof(Online.Rooms.Room.Name))] - private Bindable name { get; set; } - - public RoomNameText() - { - Font = OsuFont.GetFont(size: 28); - } - - [BackgroundDependencyLoader] - private void load() - { - Current = name; - } - } - private partial class RoomStatusText : OnlinePlayComposite { [Resolved] From 05bdc924267edf3afdea1a8573cc5ce603c5c1e5 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Tue, 13 Jun 2023 13:58:58 -0700 Subject: [PATCH 1228/1400] Add right padding according to right detail shear --- .../OnlinePlay/Lounge/Components/DrawableRoom.cs | 1 + .../Components/DrawableRoomParticipantsList.cs | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 11c649a9ae..ad421fce94 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -136,6 +136,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Padding = new MarginPadding { Left = 20, + Right = DrawableRoomParticipantsList.SHEAR_WIDTH, Vertical = 5 }, Children = new Drawable[] diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs index c31633eefc..06f9f35479 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoomParticipantsList.cs @@ -24,8 +24,14 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { public partial class DrawableRoomParticipantsList : OnlinePlayComposite { + public const float SHEAR_WIDTH = 12f; + private const float avatar_size = 36; + private const float height = 60f; + + private static readonly Vector2 shear = new Vector2(SHEAR_WIDTH / height, 0); + private FillFlowContainer avatarFlow; private CircularAvatar hostAvatar; @@ -36,7 +42,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public DrawableRoomParticipantsList() { AutoSizeAxes = Axes.X; - Height = 60; + Height = height; } [BackgroundDependencyLoader] @@ -49,7 +55,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Masking = true, CornerRadius = 10, - Shear = new Vector2(0.2f, 0), + Shear = shear, Child = new Box { RelativeSizeAxes = Axes.Both, @@ -98,7 +104,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components RelativeSizeAxes = Axes.Both, Masking = true, CornerRadius = 10, - Shear = new Vector2(0.2f, 0), + Shear = shear, Child = new Box { RelativeSizeAxes = Axes.Both, From 83abc80950f5e19c590d8c5099aaf872411a7708 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Jun 2023 13:54:37 +0900 Subject: [PATCH 1229/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b2faa7dfc2..e08b09aef9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 24d8e336e24fbdb1f4fdfe01f7c2336546a3184b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Jun 2023 07:55:03 +0300 Subject: [PATCH 1230/1400] Remove width limit on room status text in favour of cell distribution --- osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index ad421fce94..ef06d21655 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -337,7 +337,6 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Width = 0.5f; } [BackgroundDependencyLoader] From 6543c720efcf154f0d29b8e839aa076e5a8359d0 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Jun 2023 09:58:39 +0300 Subject: [PATCH 1231/1400] Fix map pool test scene using invalid mod acronyms --- osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 5695cb5574..48375c2cbd 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -92,7 +92,7 @@ namespace osu.Game.Tournament.Tests.Screens Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); for (int i = 0; i < 11; i++) - addBeatmap(i > 4 ? $"M{i}" : "NM"); + addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); }); AddStep("reset match", () => @@ -118,7 +118,7 @@ namespace osu.Game.Tournament.Tests.Screens Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); for (int i = 0; i < 12; i++) - addBeatmap(i > 4 ? $"M{i}" : "NM"); + addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); }); AddStep("reset match", () => @@ -130,7 +130,7 @@ namespace osu.Game.Tournament.Tests.Screens assertThreeWide(); } - private void addBeatmap(string mods = "nm") + private void addBeatmap(string mods = "NM") { Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Add(new RoundBeatmap { From 90a5c75474275cd56bfd8031bd35b6a94d7c3e4c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Jun 2023 10:01:01 +0300 Subject: [PATCH 1232/1400] Add setting to ladder info and simplify changes --- osu.Game.Tournament/Models/LadderInfo.cs | 2 + .../Screens/MapPool/MapPoolScreen.cs | 79 +++++++++---------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 6b64a1156e..cb4e8bc16a 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -42,5 +42,7 @@ namespace osu.Game.Tournament.Models }; public Bindable AutoProgressScreens = new BindableBool(true); + + public Bindable SplitMapPoolByMods = new BindableBool(true); } } diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs index fcb0c4d70b..cb6c5902ec 100644 --- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs +++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Threading; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; @@ -25,8 +24,7 @@ namespace osu.Game.Tournament.Screens.MapPool { public partial class MapPoolScreen : TournamentMatchScreen { - private readonly FillFlowContainer> mapFlows; - private TournamentMatch currentMatch; + private FillFlowContainer> mapFlows; [Resolved(canBeNull: true)] private TournamentSceneManager sceneManager { get; set; } @@ -34,14 +32,13 @@ namespace osu.Game.Tournament.Screens.MapPool private TeamColour pickColour; private ChoiceType pickType; - private readonly OsuButton buttonRedBan; - private readonly OsuButton buttonBlueBan; - private readonly OsuButton buttonRedPick; - private readonly OsuButton buttonBluePick; + private OsuButton buttonRedBan; + private OsuButton buttonBlueBan; + private OsuButton buttonRedPick; + private OsuButton buttonBluePick; - private readonly SettingsCheckbox chkBoxLineBreak; - - public MapPoolScreen() + [BackgroundDependencyLoader] + private void load(MatchIPCInfo ipc) { InternalChildren = new Drawable[] { @@ -102,26 +99,26 @@ namespace osu.Game.Tournament.Screens.MapPool Action = reset }, new ControlPanel.Spacer(), - new TournamentSpriteText + new OsuCheckbox { - Text = "Each modpool takes" + LabelText = "Split display by mods", + Current = LadderInfo.SplitMapPoolByMods, }, - new TournamentSpriteText - { - Text = "different row" - }, - chkBoxLineBreak = new SettingsCheckbox() }, } }; + + ipc.Beatmap.BindValueChanged(beatmapChanged); } - [BackgroundDependencyLoader] - private void load(MatchIPCInfo ipc) + private Bindable splitMapPoolByMods; + + protected override void LoadComplete() { - ipc.Beatmap.BindValueChanged(beatmapChanged); - chkBoxLineBreak.Current.Value = true; - chkBoxLineBreak.Current.BindValueChanged(_ => rearrangeMappool()); + base.LoadComplete(); + + splitMapPoolByMods = LadderInfo.SplitMapPoolByMods.GetBoundCopy(); + splitMapPoolByMods.BindValueChanged(_ => updateDisplay()); } private void beatmapChanged(ValueChangedEvent beatmap) @@ -228,42 +225,40 @@ namespace osu.Game.Tournament.Screens.MapPool protected override void CurrentMatchChanged(ValueChangedEvent match) { base.CurrentMatchChanged(match); - currentMatch = match.NewValue; - rearrangeMappool(); + updateDisplay(); } - private void rearrangeMappool() + private void updateDisplay() { mapFlows.Clear(); - if (currentMatch == null) + if (CurrentMatch.Value == null) return; + int totalRows = 0; - if (currentMatch.Round.Value != null) + if (CurrentMatch.Value.Round.Value != null) { FillFlowContainer currentFlow = null; - string currentMod = null; + string currentMods = null; int flowCount = 0; - foreach (var b in currentMatch.Round.Value.Beatmaps) + foreach (var b in CurrentMatch.Value.Round.Value.Beatmaps) { - if (currentFlow == null || currentMod != b.Mods) + if (currentFlow == null || (LadderInfo.SplitMapPoolByMods.Value && currentMods != b.Mods)) { - if (chkBoxLineBreak.Current.Value || currentFlow == null) + mapFlows.Add(currentFlow = new FillFlowContainer { - mapFlows.Add(currentFlow = new FillFlowContainer - { - Spacing = new Vector2(10, 5), - Direction = FillDirection.Full, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y - }); + Spacing = new Vector2(10, 5), + Direction = FillDirection.Full, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + }); - totalRows++; - flowCount = 0; - } - currentMod = b.Mods; + currentMods = b.Mods; + + totalRows++; + flowCount = 0; } if (++flowCount > 2) From 78fe71182430e145a4d647b40c15a6118b448550 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 14 Jun 2023 10:01:52 +0300 Subject: [PATCH 1233/1400] Add visual test case --- .../Screens/TestSceneMapPoolScreen.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 48375c2cbd..0ffbeeb491 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -24,6 +24,9 @@ namespace osu.Game.Tournament.Tests.Screens Add(screen = new MapPoolScreen { Width = 0.7f }); } + [SetUp] + public void SetUp() => Schedule(() => Ladder.SplitMapPoolByMods.Value = true); + [Test] public void TestFewMaps() { @@ -130,6 +133,26 @@ namespace osu.Game.Tournament.Tests.Screens assertThreeWide(); } + [Test] + public void TestDisableMapsPerMod() + { + AddStep("load many maps", () => + { + Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Clear(); + + for (int i = 0; i < 12; i++) + addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); + }); + + AddStep("disable maps per mod", () => Ladder.SplitMapPoolByMods.Value = false); + + AddStep("reset match", () => + { + Ladder.CurrentMatch.Value = new TournamentMatch(); + Ladder.CurrentMatch.Value = Ladder.Matches.First(); + }); + } + private void addBeatmap(string mods = "NM") { Ladder.CurrentMatch.Value.Round.Value.Beatmaps.Add(new RoundBeatmap From ed95fb59823d4c2459f8921aaa0c883535bb6e37 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Jun 2023 07:30:46 -0700 Subject: [PATCH 1234/1400] Revert blocking password requirement text localisation --- osu.Game/Localisation/AccountCreationStrings.cs | 11 ----------- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 9 +++------ 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 6acfaaa9ac..3884e4d8bf 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -51,17 +51,6 @@ namespace osu.Game.Localisation /// public static LocalisableString MakeSureToGetIt => new TranslatableString(getKey(@"make_sure_to_get_it"), @" Make sure to get it right!"); - /// - /// "At least {0}. Choose something long but also something you will remember, like a line from your favourite song." - /// - public static LocalisableString PasswordRequirements(string arg0) => new TranslatableString(getKey(@"password_requirements"), - @"At least {0}. Choose something long but also something you will remember, like a line from your favourite song.", arg0); - - /// - /// "8 characters long" - /// - public static LocalisableString CharactersLong => new TranslatableString(getKey(@"characters_long"), @"8 characters long"); - private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 5725f9cf7d..ec3e7f893f 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -139,12 +139,9 @@ namespace osu.Game.Overlays.AccountCreation emailAddressDescription.AddText(AccountCreationStrings.EmailUsage); emailAddressDescription.AddText(AccountCreationStrings.MakeSureToGetIt, cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); - string[] passwordReq = localisationManager.GetLocalisedBindableString(AccountCreationStrings.PasswordRequirements("{}")).Value.Split("{}"); - if (passwordReq.Length != 2) passwordReq = AccountCreationStrings.PasswordRequirements("{}").ToString().Split("{}"); - - passwordDescription.AddText(passwordReq[0]); - characterCheckText = passwordDescription.AddText(AccountCreationStrings.CharactersLong); - passwordDescription.AddText(passwordReq[1]); + passwordDescription.AddText("At least "); + characterCheckText = passwordDescription.AddText("8 characters long"); + passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); passwordTextBox.Current.BindValueChanged(_ => updateCharacterCheckTextColour(), true); characterCheckText.DrawablePartsRecreated += _ => updateCharacterCheckTextColour(); From 8cecfef2ff6bfe30d2f2af2419449eadbacd4235 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Jun 2023 07:40:26 -0700 Subject: [PATCH 1235/1400] Apply key renaming suggestions --- osu.Game/Localisation/AccountCreationStrings.cs | 12 ++++++------ osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 6 +++--- osu.Game/Overlays/AccountCreation/ScreenWarning.cs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 3884e4d8bf..282e458bb9 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -27,29 +27,29 @@ namespace osu.Game.Localisation /// /// "Help, I can't access my account!" /// - public static LocalisableString HelpICantAccess => new TranslatableString(getKey(@"help_icant_access"), @"Help, I can't access my account!"); + public static LocalisableString MultiAccountWarningHelp => new TranslatableString(getKey(@"multi_account_warning_help"), @"Help, I can't access my account!"); /// /// "I understand. This account isn't for me." /// - public static LocalisableString AccountIsntForMe => new TranslatableString(getKey(@"account_isnt_for_me"), @"I understand. This account isn't for me."); + public static LocalisableString MultiAccountWarningAccept => new TranslatableString(getKey(@"multi_account_warning_accept"), @"I understand. This account isn't for me."); /// /// "This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!" /// - public static LocalisableString ThisWillBeYourPublic => new TranslatableString(getKey(@"this_will_be_your_public"), + public static LocalisableString UsernameDescription => new TranslatableString(getKey(@"username_description"), @"This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); /// /// "Will be used for notifications, account verification and in the case you forget your password. No spam, ever." /// - public static LocalisableString EmailUsage => - new TranslatableString(getKey(@"email_usage"), @"Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + public static LocalisableString EmailDescription1 => + new TranslatableString(getKey(@"email_description_1"), @"Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); /// /// " Make sure to get it right!" /// - public static LocalisableString MakeSureToGetIt => new TranslatableString(getKey(@"make_sure_to_get_it"), @" Make sure to get it right!"); + public static LocalisableString EmailDescription2 => new TranslatableString(getKey(@"email_description_2"), @" Make sure to get it right!"); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index ec3e7f893f..726fcc4304 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -134,10 +134,10 @@ namespace osu.Game.Overlays.AccountCreation textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox }; - usernameDescription.AddText(AccountCreationStrings.ThisWillBeYourPublic); + usernameDescription.AddText(AccountCreationStrings.UsernameDescription); - emailAddressDescription.AddText(AccountCreationStrings.EmailUsage); - emailAddressDescription.AddText(AccountCreationStrings.MakeSureToGetIt, cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); + emailAddressDescription.AddText(AccountCreationStrings.EmailDescription1); + emailAddressDescription.AddText(AccountCreationStrings.EmailDescription2, cp => cp.Font = cp.Font.With(Typeface.Torus, weight: FontWeight.Bold)); passwordDescription.AddText("At least "); characterCheckText = passwordDescription.AddText("8 characters long"); diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index f5807b49b5..0fbf6ba59e 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -102,13 +102,13 @@ namespace osu.Game.Overlays.AccountCreation }, new SettingsButton { - Text = AccountCreationStrings.HelpICantAccess, + Text = AccountCreationStrings.MultiAccountWarningHelp, Margin = new MarginPadding { Top = 50 }, Action = () => game?.OpenUrlExternally(help_centre_url) }, new DangerousSettingsButton { - Text = AccountCreationStrings.AccountIsntForMe, + Text = AccountCreationStrings.MultiAccountWarningAccept, Action = () => this.Push(new ScreenEntry()) }, furtherAssistance = new LinkFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) From e4af1df6637e8a2f4fbc6613013d6cfadb81b0f3 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Jun 2023 07:41:14 -0700 Subject: [PATCH 1236/1400] Apply automated formatting changes --- osu.Game/Localisation/AccountCreationStrings.cs | 6 ++---- osu.Game/Localisation/CommonStrings.cs | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 282e458bb9..20ba7fe953 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -37,14 +37,12 @@ namespace osu.Game.Localisation /// /// "This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!" /// - public static LocalisableString UsernameDescription => new TranslatableString(getKey(@"username_description"), - @"This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); + public static LocalisableString UsernameDescription => new TranslatableString(getKey(@"username_description"), @"This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); /// /// "Will be used for notifications, account verification and in the case you forget your password. No spam, ever." /// - public static LocalisableString EmailDescription1 => - new TranslatableString(getKey(@"email_description_1"), @"Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); + public static LocalisableString EmailDescription1 => new TranslatableString(getKey(@"email_description_1"), @"Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); /// /// " Make sure to get it right!" diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index 4ce05e96ef..ec78d34a16 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -166,4 +166,4 @@ namespace osu.Game.Localisation private static string getKey(string key) => $@"{prefix}:{key}"; } -} \ No newline at end of file +} From b54f3a2cba46e7073d2f5ba3ac798f8a3b732852 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Jun 2023 07:58:55 -0700 Subject: [PATCH 1237/1400] Normalise source strings to sentence case The casing of the "caps lock" tooltip wasn't changed in code, as tooltips should be ideally sentence-cased, see https://github.com/ppy/osu/pull/21765#issuecomment-1552378930. --- osu.Game/Localisation/AccountCreationStrings.cs | 8 ++++---- osu.Game/Localisation/CommonStrings.cs | 4 ++-- osu.Game/Localisation/LoginPanelStrings.cs | 4 ++-- osu.Game/Overlays/AccountCreation/ScreenWelcome.cs | 5 +++-- osu.Game/Overlays/Login/LoginPanel.cs | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/Localisation/AccountCreationStrings.cs b/osu.Game/Localisation/AccountCreationStrings.cs index 20ba7fe953..2183df9b52 100644 --- a/osu.Game/Localisation/AccountCreationStrings.cs +++ b/osu.Game/Localisation/AccountCreationStrings.cs @@ -10,14 +10,14 @@ namespace osu.Game.Localisation private const string prefix = @"osu.Game.Resources.Localisation.AccountCreation"; /// - /// "New Player Registration" + /// "New player registration" /// - public static LocalisableString NewPlayerRegistration => new TranslatableString(getKey(@"new_player_registration"), @"New Player Registration"); + public static LocalisableString NewPlayerRegistration => new TranslatableString(getKey(@"new_player_registration"), @"New player registration"); /// - /// "let's get you started" + /// "Let's get you started" /// - public static LocalisableString LetsGetYouStarted => new TranslatableString(getKey(@"lets_get_you_started"), @"let's get you started"); + public static LocalisableString LetsGetYouStarted => new TranslatableString(getKey(@"lets_get_you_started"), @"Let's get you started"); /// /// "Let's create an account!" diff --git a/osu.Game/Localisation/CommonStrings.cs b/osu.Game/Localisation/CommonStrings.cs index ec78d34a16..c9223db246 100644 --- a/osu.Game/Localisation/CommonStrings.cs +++ b/osu.Game/Localisation/CommonStrings.cs @@ -155,9 +155,9 @@ namespace osu.Game.Localisation public static LocalisableString Exit => new TranslatableString(getKey(@"exit"), @"Exit"); /// - /// "caps lock is active" + /// "Caps lock is active" /// - public static LocalisableString CapsLockIsActive => new TranslatableString(getKey(@"caps_lock_is_active"), @"caps lock is active"); + public static LocalisableString CapsLockIsActive => new TranslatableString(getKey(@"caps_lock_is_active"), @"Caps lock is active"); /// /// "Revert to default" diff --git a/osu.Game/Localisation/LoginPanelStrings.cs b/osu.Game/Localisation/LoginPanelStrings.cs index 535d86fbc5..19b0ca3b52 100644 --- a/osu.Game/Localisation/LoginPanelStrings.cs +++ b/osu.Game/Localisation/LoginPanelStrings.cs @@ -25,9 +25,9 @@ namespace osu.Game.Localisation public static LocalisableString SignedIn => new TranslatableString(getKey(@"signed_in"), @"Signed in"); /// - /// "ACCOUNT" + /// "Account" /// - public static LocalisableString Account => new TranslatableString(getKey(@"account"), @"ACCOUNT"); + public static LocalisableString Account => new TranslatableString(getKey(@"account"), @"Account"); /// /// "Remember username" diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index a81b1019fe..610b9ee282 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; @@ -45,14 +46,14 @@ namespace osu.Game.Overlays.AccountCreation Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), - Text = AccountCreationStrings.NewPlayerRegistration, + Text = AccountCreationStrings.NewPlayerRegistration.ToTitle(), }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Font = OsuFont.GetFont(size: 12), - Text = AccountCreationStrings.LetsGetYouStarted, + Text = AccountCreationStrings.LetsGetYouStarted.ToLower(), }, new SettingsButton { diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index fb9987bd82..79569ada65 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.Login { new OsuSpriteText { - Text = LoginPanelStrings.Account, + Text = LoginPanelStrings.Account.ToUpper(), Margin = new MarginPadding { Bottom = 5 }, Font = OsuFont.GetFont(weight: FontWeight.Bold), }, From 45e67fbe788bb34ac315ed1fb10e48d777c47cbe Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 14 Jun 2023 08:09:03 -0700 Subject: [PATCH 1238/1400] Remove unused load dependency --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 726fcc4304..9ad507d82a 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -10,7 +10,6 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Framework.Platform; using osu.Framework.Screens; @@ -53,7 +52,7 @@ namespace osu.Game.Overlays.AccountCreation private OsuGame game { get; set; } [BackgroundDependencyLoader] - private void load(LocalisationManager localisationManager) + private void load() { InternalChildren = new Drawable[] { From 4cc2bb0c7db35e4b52ac230e81cb5f50a08dfbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 14 Jun 2023 21:33:11 +0200 Subject: [PATCH 1239/1400] Rename things in test to match --- osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs index 0ffbeeb491..94086f10f2 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tournament.Tests.Screens } [Test] - public void TestDisableMapsPerMod() + public void TestSplitMapPoolByMods() { AddStep("load many maps", () => { @@ -144,7 +144,7 @@ namespace osu.Game.Tournament.Tests.Screens addBeatmap(i > 4 ? Ruleset.Value.CreateInstance().AllMods.ElementAt(i).Acronym : "NM"); }); - AddStep("disable maps per mod", () => Ladder.SplitMapPoolByMods.Value = false); + AddStep("disable splitting map pool by mods", () => Ladder.SplitMapPoolByMods.Value = false); AddStep("reset match", () => { From 0ddd43d44df5e2f5c78b0be670c1ce978f59824a Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Jun 2023 15:15:32 +0900 Subject: [PATCH 1240/1400] Update CFS to NET6.0 --- .config/dotnet-tools.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1f937e1837..8c8a3be771 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "codefilesanity": { - "version": "0.0.36", + "version": "0.0.37", "commands": [ "CodeFileSanity" ] From b9543f4fddb173701fc1e110d25c5522d85b22fe Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 15 Jun 2023 11:05:06 +0300 Subject: [PATCH 1241/1400] Add failing test case --- .../SongSelect/TestSceneBeatmapCarousel.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 61a8322ee3..61f95dc628 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -453,6 +453,25 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); } + [Test] + public void TestRewindToDeletedBeatmap() + { + loadBeatmaps(); + + var firstAdded = TestResources.CreateTestBeatmapSetInfo(); + + AddStep("add new set", () => carousel.UpdateBeatmapSet(firstAdded)); + AddStep("select set", () => carousel.SelectBeatmap(firstAdded.Beatmaps.First())); + + nextRandom(); + + AddStep("delete set", () => carousel.RemoveBeatmapSet(firstAdded)); + + prevRandom(); + + AddAssert("deleted set not selected", () => carousel.SelectedBeatmapSet?.Equals(firstAdded) == false); + } + /// /// Test adding and removing beatmap sets /// From 39db17d2e97c20f3d56c55113514ac80724aa5f5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 15 Jun 2023 11:22:11 +0300 Subject: [PATCH 1242/1400] Use better method to avoid rewinding to deleted beatmaps --- osu.Game/Screens/Select/BeatmapCarousel.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 8c0f67564a..3d87a57295 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -155,7 +155,7 @@ namespace osu.Game.Screens.Select public Bindable RandomAlgorithm = new Bindable(); private readonly List previouslyVisitedRandomSets = new List(); - private readonly Stack randomSelectedBeatmaps = new Stack(); + private readonly List randomSelectedBeatmaps = new List(); private CarouselRoot root; @@ -348,6 +348,11 @@ namespace osu.Game.Screens.Select if (!root.BeatmapSetsByID.TryGetValue(beatmapSetID, out var existingSet)) return; + foreach (var beatmap in existingSet.Beatmaps) + randomSelectedBeatmaps.Remove(beatmap); + + previouslyVisitedRandomSets.Remove(existingSet); + root.RemoveItem(existingSet); itemsCache.Invalidate(); @@ -501,7 +506,7 @@ namespace osu.Game.Screens.Select if (selectedBeatmap != null && selectedBeatmapSet != null) { - randomSelectedBeatmaps.Push(selectedBeatmap); + randomSelectedBeatmaps.Add(selectedBeatmap); // when performing a random, we want to add the current set to the previously visited list // else the user may be "randomised" to the existing selection. @@ -538,9 +543,10 @@ namespace osu.Game.Screens.Select { while (randomSelectedBeatmaps.Any()) { - var beatmap = randomSelectedBeatmaps.Pop(); + var beatmap = randomSelectedBeatmaps[^1]; + randomSelectedBeatmaps.Remove(beatmap); - if (!beatmap.Filtered.Value && beatmapSets.Any(beatset => beatset.Beatmaps.Contains(beatmap))) + if (!beatmap.Filtered.Value && beatmap.BeatmapInfo.BeatmapSet?.DeletePending != true) { if (selectedBeatmapSet != null) { From 145530035cccad94947aba2e4c8ba78d3c18c817 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 15 Jun 2023 20:00:15 +0900 Subject: [PATCH 1243/1400] Optimise mania density calculation during beatmap conversion --- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 632b7cdcc7..bdc5a00583 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -119,14 +119,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps yield return obj; } - private readonly List prevNoteTimes = new List(max_notes_for_density); + private readonly LimitedCapacityQueue prevNoteTimes = new LimitedCapacityQueue(max_notes_for_density); private double density = int.MaxValue; private void computeDensity(double newNoteTime) { - if (prevNoteTimes.Count == max_notes_for_density) - prevNoteTimes.RemoveAt(0); - prevNoteTimes.Add(newNoteTime); + prevNoteTimes.Enqueue(newNoteTime); if (prevNoteTimes.Count >= 2) density = (prevNoteTimes[^1] - prevNoteTimes[0]) / prevNoteTimes.Count; From d83bf029239bf54c4ef290b210c8d8dc232b206f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 14 Jun 2023 17:50:46 +0900 Subject: [PATCH 1244/1400] Fix thing --- osu.Game/Database/RealmAccess.cs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 68a4679656..b2bbbf3155 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -945,22 +945,26 @@ namespace osu.Game.Database foreach (var score in scores) { - // Recalculate the old-style standardised score to see if this was an old lazer score. - bool oldScoreMatchesExpectations = StandardisedScoreMigrationTools.GetOldStandardised(score) == score.TotalScore; - // Some older scores don't have correct statistics populated, so let's give them benefit of doubt. - bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); - - if (oldScoreMatchesExpectations || scoreIsVeryOld) + try { - try - { - long calculatedNew = StandardisedScoreMigrationTools.GetNewStandardised(score); - score.TotalScore = calculatedNew; - } - catch + // Recalculate the old-style standardised score to see if this was an old lazer score. + bool oldScoreMatchesExpectations = StandardisedScoreMigrationTools.GetOldStandardised(score) == score.TotalScore; + // Some older scores don't have correct statistics populated, so let's give them benefit of doubt. + bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); + + if (oldScoreMatchesExpectations || scoreIsVeryOld) { + try + { + long calculatedNew = StandardisedScoreMigrationTools.GetNewStandardised(score); + score.TotalScore = calculatedNew; + } + catch + { + } } } + catch { } } break; From 51b5a0863f97b0d3e777fbcae5490e10848e0d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 15 Jun 2023 21:48:57 +0200 Subject: [PATCH 1245/1400] Apply migration to new standardised score on normal reimport too --- osu.Game/Database/RealmAccess.cs | 7 +------ .../Database/StandardisedScoreMigrationTools.cs | 14 ++++++++++++++ osu.Game/Scoring/ScoreImporter.cs | 5 +++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index b2bbbf3155..48eb2826f5 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -947,12 +947,7 @@ namespace osu.Game.Database { try { - // Recalculate the old-style standardised score to see if this was an old lazer score. - bool oldScoreMatchesExpectations = StandardisedScoreMigrationTools.GetOldStandardised(score) == score.TotalScore; - // Some older scores don't have correct statistics populated, so let's give them benefit of doubt. - bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); - - if (oldScoreMatchesExpectations || scoreIsVeryOld) + if (StandardisedScoreMigrationTools.ShouldMigrateToNewStandardised(score)) { try { diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index af91bee9e4..66e64f3f7a 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.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 System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; @@ -13,6 +14,19 @@ namespace osu.Game.Database { public static class StandardisedScoreMigrationTools { + public static bool ShouldMigrateToNewStandardised(ScoreInfo score) + { + if (score.IsLegacyScore) + return false; + + // Recalculate the old-style standardised score to see if this was an old lazer score. + bool oldScoreMatchesExpectations = GetOldStandardised(score) == score.TotalScore; + // Some older scores don't have correct statistics populated, so let's give them benefit of doubt. + bool scoreIsVeryOld = score.Date < new DateTime(2023, 1, 1, 0, 0, 0); + + return oldScoreMatchesExpectations || scoreIsVeryOld; + } + public static long GetNewStandardised(ScoreInfo score) { int maxJudgementIndex = 0; diff --git a/osu.Game/Scoring/ScoreImporter.cs b/osu.Game/Scoring/ScoreImporter.cs index 1c24cfbc85..16658a598a 100644 --- a/osu.Game/Scoring/ScoreImporter.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -83,6 +83,11 @@ namespace osu.Game.Scoring if (string.IsNullOrEmpty(model.MaximumStatisticsJson)) model.MaximumStatisticsJson = JsonConvert.SerializeObject(model.MaximumStatistics); + + // for pre-ScoreV2 lazer scores, apply a best-effort conversion of total score to ScoreV2. + // this requires: max combo, statistics, max statistics (where available), and mods to already be populated on the score. + if (StandardisedScoreMigrationTools.ShouldMigrateToNewStandardised(model)) + model.TotalScore = StandardisedScoreMigrationTools.GetNewStandardised(model); } /// From 94b7de4b3f5b131a231aba17c48c75c721884169 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 14:01:56 +0900 Subject: [PATCH 1246/1400] Fix old-new standardised score conversion missing some scores due to not rounding correctly --- osu.Game/Database/StandardisedScoreMigrationTools.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/StandardisedScoreMigrationTools.cs b/osu.Game/Database/StandardisedScoreMigrationTools.cs index 66e64f3f7a..582a656efa 100644 --- a/osu.Game/Database/StandardisedScoreMigrationTools.cs +++ b/osu.Game/Database/StandardisedScoreMigrationTools.cs @@ -182,7 +182,7 @@ namespace osu.Game.Database foreach (var mod in score.Mods) modMultiplier *= mod.ScoreMultiplier; - return (long)((1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore) * modMultiplier); + return (long)Math.Round((1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore) * modMultiplier); } private class FakeHit : HitObject From 1f17f416a4e43112303407998bf09b6b9fe42e32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 14:04:18 +0900 Subject: [PATCH 1247/1400] Force migration of old-new standardised scores to run once more --- osu.Game/Database/RealmAccess.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 48eb2826f5..da4caa42ba 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -77,8 +77,9 @@ namespace osu.Game.Database /// 27 2023-06-06 Added EditorTimestamp to BeatmapInfo. /// 28 2023-06-08 Added IsLegacyScore to ScoreInfo, parsed from replay files. /// 29 2023-06-12 Run migration of old lazer scores to be best-effort in the new scoring number space. No actual realm changes. + /// 30 2023-06-16 Run migration of old lazer scores again. This time with more correct rounding considerations. /// - private const int schema_version = 29; + private const int schema_version = 30; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. @@ -938,6 +939,7 @@ namespace osu.Game.Database } case 29: + case 30: { var scores = migration.NewRealm .All() From b5de109cb31ab021778677722c959e49d6c6f4ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 14:54:19 +0900 Subject: [PATCH 1248/1400] Fix osu!mania hold notes sometimes looking incorrect after rewind --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 3f91328128..faeb133615 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -254,6 +254,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; sizingContainer.Height = 1 - yOffset / DrawHeight; } + else + sizingContainer.Height = 1; } protected override void CheckForResult(bool userTriggered, double timeOffset) From ce41ef6e5d3e6163dfbd6d1dfadb53aabfe409d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 15:24:30 +0900 Subject: [PATCH 1249/1400] Move `OrderByTotalScore()` to an extension method --- .../Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +---- osu.Game/Scoring/ScoreInfoExtensions.cs | 13 +++++++++++++ osu.Game/Scoring/ScoreManager.cs | 11 ----------- .../OnlinePlay/Playlists/PlaylistsResultsScreen.cs | 2 +- osu.Game/Screens/Select/Carousel/TopLocalRank.cs | 5 +---- .../Select/Leaderboards/BeatmapLeaderboard.cs | 7 ++----- 6 files changed, 18 insertions(+), 25 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 6d89313979..b53b7826f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -47,9 +47,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores [Resolved] private RulesetStore rulesets { get; set; } - [Resolved] - private ScoreManager scoreManager { get; set; } - private GetScoresRequest getScoresRequest; private CancellationTokenSource loadCancellationSource; @@ -85,7 +82,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores MD5Hash = apiBeatmap.MD5Hash }; - var scores = scoreManager.OrderByTotalScore(value.Scores.Select(s => s.ToScoreInfo(rulesets, beatmapInfo))).ToArray(); + var scores = value.Scores.Select(s => s.ToScoreInfo(rulesets, beatmapInfo)).OrderByTotalScore().ToArray(); var topScore = scores.First(); scoreTable.DisplayScores(scores, apiBeatmap.Status.GrantsPerformancePoints()); diff --git a/osu.Game/Scoring/ScoreInfoExtensions.cs b/osu.Game/Scoring/ScoreInfoExtensions.cs index 7979ca8aaa..e15ab0d34c 100644 --- a/osu.Game/Scoring/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/ScoreInfoExtensions.cs @@ -3,6 +3,8 @@ #nullable disable +using System.Collections.Generic; +using System.Linq; using osu.Game.Beatmaps; namespace osu.Game.Scoring @@ -13,5 +15,16 @@ namespace osu.Game.Scoring /// A user-presentable display title representing this score. /// public static string GetDisplayTitle(this IScoreInfo scoreInfo) => $"{scoreInfo.User.Username} playing {scoreInfo.Beatmap.GetDisplayTitle()}"; + + /// + /// Orders an array of s by total score. + /// + /// The array of s to reorder. + /// The given ordered by decreasing total score. + public static IEnumerable OrderByTotalScore(this IEnumerable scores) + => scores.OrderByDescending(s => s.TotalScore) + .ThenBy(s => s.OnlineID) + // Local scores may not have an online ID. Fall back to date in these cases. + .ThenBy(s => s.Date); } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index d5509538fd..9ba7339a31 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -69,17 +69,6 @@ namespace osu.Game.Scoring return Realm.Run(r => r.All().FirstOrDefault(query)?.Detach()); } - /// - /// Orders an array of s by total score. - /// - /// The array of s to reorder. - /// The given ordered by decreasing total score. - public IEnumerable OrderByTotalScore(IEnumerable scores) - => scores.OrderByDescending(s => s.TotalScore) - .ThenBy(s => s.OnlineID) - // Local scores may not have an online ID. Fall back to date in these cases. - .ThenBy(s => s.Date); - /// /// Retrieves a bindable that represents the total score of a . /// diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index d40d43cd54..aa72394ac9 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -182,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists /// An optional pivot around which the scores were retrieved. private void performSuccessCallback([NotNull] Action> callback, [NotNull] List scores, [CanBeNull] MultiplayerScores pivot = null) => Schedule(() => { - var scoreInfos = scoreManager.OrderByTotalScore(scores.Select(s => s.CreateScoreInfo(scoreManager, rulesets, playlistItem, Beatmap.Value.BeatmapInfo))).ToArray(); + var scoreInfos = scores.Select(s => s.CreateScoreInfo(scoreManager, rulesets, playlistItem, Beatmap.Value.BeatmapInfo)).OrderByTotalScore().ToArray(); // Select a score if we don't already have one selected. // Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll). diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index a57a8b0f27..7c632b63db 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -29,9 +29,6 @@ namespace osu.Game.Screens.Select.Carousel [Resolved] private RealmAccess realm { get; set; } = null!; - [Resolved] - private ScoreManager scoreManager { get; set; } = null!; - [Resolved] private IAPIProvider api { get; set; } = null!; @@ -78,7 +75,7 @@ namespace osu.Game.Screens.Select.Carousel if (changes?.HasCollectionChanges() == false) return; - ScoreInfo? topScore = scoreManager.OrderByTotalScore(sender.Detach()).FirstOrDefault(); + ScoreInfo? topScore = sender.Detach().OrderByTotalScore().FirstOrDefault(); updateable.Rank = topScore?.Rank; updateable.Alpha = topScore != null ? 1 : 0; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 2b40b9faf8..4c41ed3622 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -67,9 +67,6 @@ namespace osu.Game.Screens.Select.Leaderboards } } - [Resolved] - private ScoreManager scoreManager { get; set; } = null!; - [Resolved] private IBindable ruleset { get; set; } = null!; @@ -164,7 +161,7 @@ namespace osu.Game.Screens.Select.Leaderboards return; SetScores( - scoreManager.OrderByTotalScore(response.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo))), + response.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo)).OrderByTotalScore(), response.UserScore?.CreateScoreInfo(rulesets, fetchBeatmapInfo) ); }); @@ -222,7 +219,7 @@ namespace osu.Game.Screens.Select.Leaderboards scores = scores.Where(s => selectedMods.SetEquals(s.Mods.Select(m => m.Acronym))); } - scores = scoreManager.OrderByTotalScore(scores.Detach()); + scores = scores.Detach().OrderByTotalScore(); SetScores(scores); } From 362aa4b3763223c3294b23029eb6284d45525ad6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 15:26:13 +0900 Subject: [PATCH 1250/1400] Also move `GetMaxAchievableCombo` --- osu.Game/Scoring/ScoreInfoExtensions.cs | 10 ++++++++-- osu.Game/Scoring/ScoreManager.cs | 7 ------- .../Ranking/Expanded/ExpandedPanelMiddleContent.cs | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfoExtensions.cs b/osu.Game/Scoring/ScoreInfoExtensions.cs index e15ab0d34c..85598076d6 100644 --- a/osu.Game/Scoring/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/ScoreInfoExtensions.cs @@ -1,11 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Scoring { @@ -26,5 +25,12 @@ namespace osu.Game.Scoring .ThenBy(s => s.OnlineID) // Local scores may not have an online ID. Fall back to date in these cases. .ThenBy(s => s.Date); + + /// + /// Retrieves the maximum achievable combo for the provided score. + /// + /// The to compute the maximum achievable combo for. + /// The maximum achievable combo. + public static int GetMaximumAchievableCombo(this ScoreInfo score) => score.MaximumStatistics.Where(kvp => kvp.Key.AffectsCombo()).Sum(kvp => kvp.Value); } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 9ba7339a31..55bcb9f79d 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -89,13 +89,6 @@ namespace osu.Game.Scoring /// The bindable containing the formatted total score string. public Bindable GetBindableTotalScoreString([NotNull] ScoreInfo score) => new TotalScoreStringBindable(GetBindableTotalScore(score)); - /// - /// Retrieves the maximum achievable combo for the provided score. - /// - /// The to compute the maximum achievable combo for. - /// The maximum achievable combo. - public int GetMaximumAchievableCombo([NotNull] ScoreInfo score) => score.MaximumStatistics.Where(kvp => kvp.Key.AffectsCombo()).Sum(kvp => kvp.Value); - /// /// Provides the total score of a . Responds to changes in the currently-selected . /// diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs index fe74c1ba0d..82c429798e 100644 --- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Ranking.Expanded var topStatistics = new List { new AccuracyStatistic(score.Accuracy), - new ComboStatistic(score.MaxCombo, scoreManager.GetMaximumAchievableCombo(score)), + new ComboStatistic(score.MaxCombo, score.GetMaximumAchievableCombo()), new PerformanceStatistic(score), }; From 36954e55ad395b99673d15ee68eba42800fa8362 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 17:15:45 +0900 Subject: [PATCH 1251/1400] Fix incorrect mapping when distance spacing is not 1.0x --- .../Compose/Components/CircularDistanceSnapGrid.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 2eec833832..63886e38eb 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -101,12 +101,11 @@ namespace osu.Game.Screens.Edit.Compose.Components if (travelLength < DistanceBetweenTicks) travelLength = DistanceBetweenTicks; - if (LimitedDistanceSnap.Value) - travelLength = SnapProvider.DurationToDistance(ReferenceObject, editorClock.CurrentTime - ReferenceObject.GetEndTime()); - - // When interacting with the resolved snap provider, the distance spacing multiplier should first be removed - // to allow for snapping at a non-multiplied ratio. - float snappedDistance = SnapProvider.FindSnappedDistance(ReferenceObject, travelLength / distanceSpacingMultiplier); + float snappedDistance = LimitedDistanceSnap.Value + ? SnapProvider.DurationToDistance(ReferenceObject, editorClock.CurrentTime - ReferenceObject.GetEndTime()) + // When interacting with the resolved snap provider, the distance spacing multiplier should first be removed + // to allow for snapping at a non-multiplied ratio. + : SnapProvider.FindSnappedDistance(ReferenceObject, travelLength / distanceSpacingMultiplier); double snappedTime = StartTime + SnapProvider.DistanceToDuration(ReferenceObject, snappedDistance); From d965d39c4442849561d59c25186c2a6fb6ad7af9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 16 Jun 2023 17:16:11 +0900 Subject: [PATCH 1252/1400] Fix distance snap grid circles not correctly being centered on snap point --- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index d6e4e1f030..f27ecf60cc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -63,13 +63,14 @@ namespace osu.Game.Screens.Edit.Compose.Components for (int i = 0; i < requiredCircles; i++) { float diameter = (offset + (i + 1) * DistanceBetweenTicks) * 2; + const float thickness = 4; AddInternal(new Ring(ReferenceObject, GetColourForIndexFromPlacement(i)) { Position = StartPosition, Origin = Anchor.Centre, - Size = new Vector2(diameter), - InnerRadius = 4 * 1f / diameter, + Size = new Vector2(diameter + thickness / 2), + InnerRadius = thickness * 1f / diameter, }); } } From 28696f595fbd601b18808af1c5dba47c7eb764ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 16 Jun 2023 16:24:07 +0200 Subject: [PATCH 1253/1400] Privatise setter --- osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs index 9882f6596f..8aa2fa9f45 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DistanceSnapGrid.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// When enabled, distance snap should only snap to the current time (as per the editor clock). /// This is to emulate stable behaviour. /// - protected Bindable LimitedDistanceSnap; + protected Bindable LimitedDistanceSnap { get; private set; } [BackgroundDependencyLoader] private void load(OsuConfigManager config) From a62b11606e75b579fa2086b5f191c251f54b41f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Jun 2023 01:32:41 +0900 Subject: [PATCH 1254/1400] Attempt to fix NaN fps display The only thing I can see which could cause this is reading from the `drawClock.ElapsedFrameTime` after the `isSpike` read causing a div-by-zero. Reading the values once at the start should avoid this. --- osu.Game/Graphics/UserInterface/FPSCounter.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/FPSCounter.cs b/osu.Game/Graphics/UserInterface/FPSCounter.cs index 9dbeba6449..c1ef573848 100644 --- a/osu.Game/Graphics/UserInterface/FPSCounter.cs +++ b/osu.Game/Graphics/UserInterface/FPSCounter.cs @@ -167,9 +167,12 @@ namespace osu.Game.Graphics.UserInterface { base.Update(); + double elapsedDrawFrameTime = drawClock.ElapsedFrameTime; + double elapsedUpdateFrameTime = updateClock.ElapsedFrameTime; + // If the game goes into a suspended state (ie. debugger attached or backgrounded on a mobile device) // we want to ignore really long periods of no processing. - if (updateClock.ElapsedFrameTime > 10000) + if (elapsedUpdateFrameTime > 10000) return; mainContent.Width = Math.Max(mainContent.Width, counters.DrawWidth); @@ -178,17 +181,17 @@ namespace osu.Game.Graphics.UserInterface // frame limiter (we want to show the FPS as it's changing, even if it isn't an outlier). bool aimRatesChanged = updateAimFPS(); - bool hasUpdateSpike = displayedFrameTime < spike_time_ms && updateClock.ElapsedFrameTime > spike_time_ms; + bool hasUpdateSpike = displayedFrameTime < spike_time_ms && elapsedUpdateFrameTime > spike_time_ms; // use elapsed frame time rather then FramesPerSecond to better catch stutter frames. - bool hasDrawSpike = displayedFpsCount > (1000 / spike_time_ms) && drawClock.ElapsedFrameTime > spike_time_ms; + bool hasDrawSpike = displayedFpsCount > (1000 / spike_time_ms) && elapsedDrawFrameTime > spike_time_ms; const float damp_time = 100; - displayedFrameTime = Interpolation.DampContinuously(displayedFrameTime, updateClock.ElapsedFrameTime, hasUpdateSpike ? 0 : damp_time, updateClock.ElapsedFrameTime); + displayedFrameTime = Interpolation.DampContinuously(displayedFrameTime, elapsedUpdateFrameTime, hasUpdateSpike ? 0 : damp_time, elapsedUpdateFrameTime); if (hasDrawSpike) // show spike time using raw elapsed value, to account for `FramesPerSecond` being so averaged spike frames don't show. - displayedFpsCount = 1000 / drawClock.ElapsedFrameTime; + displayedFpsCount = 1000 / elapsedDrawFrameTime; else displayedFpsCount = Interpolation.DampContinuously(displayedFpsCount, drawClock.FramesPerSecond, damp_time, Time.Elapsed); From 3b1f92d8b84f081738d7b660aaa03910ac8fcecc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 17 Jun 2023 01:37:09 +0900 Subject: [PATCH 1255/1400] Fix fix logic causing further regression on release --- .../Objects/Drawables/DrawableHoldNote.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index faeb133615..a8563d65c4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -242,17 +242,20 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Y = (Direction.Value == ScrollingDirection.Up ? 1 : -1) * Head.Height / 2; bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; - // As the note is being held, adjust the size of the sizing container. This has two effects: - // 1. The contained masking container will mask the body and ticks. - // 2. The head note will move along with the new "head position" in the container. - // - // As per stable, this should not apply for early hits, waiting until the object starts to touch the - // judgement area first. - if (Head.IsHit && releaseTime == null && DrawHeight > 0 && Time.Current >= HitObject.StartTime) + if (Time.Current >= HitObject.StartTime) { - // How far past the hit target this hold note is. - float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; - sizingContainer.Height = 1 - yOffset / DrawHeight; + // As the note is being held, adjust the size of the sizing container. This has two effects: + // 1. The contained masking container will mask the body and ticks. + // 2. The head note will move along with the new "head position" in the container. + // + // As per stable, this should not apply for early hits, waiting until the object starts to touch the + // judgement area first. + if (Head.IsHit && releaseTime == null && DrawHeight > 0) + { + // How far past the hit target this hold note is. + float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y; + sizingContainer.Height = 1 - yOffset / DrawHeight; + } } else sizingContainer.Height = 1; From f70342bd6772cefbfcd389dc30b780116c6ed8d3 Mon Sep 17 00:00:00 2001 From: Maksim Kan Date: Tue, 13 Jun 2023 18:18:46 +0300 Subject: [PATCH 1256/1400] Fix Triangle skin colors with Dual Stage mod --- .../Skinning/Default/ManiaTrianglesSkinTransformer.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Default/ManiaTrianglesSkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Default/ManiaTrianglesSkinTransformer.cs index eb51179cea..3e0fe8ed4b 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Default/ManiaTrianglesSkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Default/ManiaTrianglesSkinTransformer.cs @@ -35,10 +35,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.Default var stage = beatmap.GetStageForColumnIndex(column); - if (stage.IsSpecialColumn(column)) + int columnInStage = column % stage.Columns; + + if (stage.IsSpecialColumn(columnInStage)) return SkinUtils.As(new Bindable(colourSpecial)); - int distanceToEdge = Math.Min(column, (stage.Columns - 1) - column); + int distanceToEdge = Math.Min(columnInStage, (stage.Columns - 1) - columnInStage); return SkinUtils.As(new Bindable(distanceToEdge % 2 == 0 ? colourOdd : colourEven)); } } From 688e65475dd938544924ba2d7e06355b50fb4bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 17 Jun 2023 10:25:09 +0200 Subject: [PATCH 1257/1400] Add better test coverage of dual stages in skinnable tests --- .../Skinning/TestScenePlayfield.cs | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs index f85e303940..6485cbb76b 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs @@ -8,6 +8,7 @@ using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; +using osuTK; namespace osu.Game.Rulesets.Mania.Tests.Skinning { @@ -25,22 +26,35 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning new StageDefinition(2) }; - SetContents(_ => new ManiaPlayfield(stageDefinitions)); + SetContents(_ => new ManiaInputManager(new ManiaRuleset().RulesetInfo, 2) + { + Child = new ManiaPlayfield(stageDefinitions) + }); }); } - [Test] - public void TestDualStages() + [TestCase(2)] + [TestCase(3)] + [TestCase(5)] + public void TestDualStages(int columnCount) { AddStep("create stage", () => { stageDefinitions = new List { - new StageDefinition(2), - new StageDefinition(2) + new StageDefinition(columnCount), + new StageDefinition(columnCount) }; - SetContents(_ => new ManiaPlayfield(stageDefinitions)); + SetContents(_ => new ManiaInputManager(new ManiaRuleset().RulesetInfo, (int)PlayfieldType.Dual + 2 * columnCount) + { + Child = new ManiaPlayfield(stageDefinitions) + { + // bit of a hack to make sure the dual stages fit on screen without overlapping each other. + Size = new Vector2(1.5f), + Scale = new Vector2(1 / 1.5f) + } + }); }); } From 4919069ea6d115c49b0b7993016d92110e350974 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Jun 2023 01:58:02 +0900 Subject: [PATCH 1258/1400] Avoid humanizer regex compilation overhead when opening song select for the first time --- osu.Game/Screens/Select/SongSelect.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 4d6a5398c5..91799dabf0 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Humanizer; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -864,7 +863,7 @@ namespace osu.Game.Screens.Select { // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // but also in this case we want support for formatting a number within a string). - FilterControl.InformationalText = $"{"match".ToQuantity(Carousel.CountDisplayed, "#,0")}"; + FilterControl.InformationalText = Carousel.CountDisplayed != 1 ? $"{Carousel.CountDisplayed} matches" : $"{Carousel.CountDisplayed} match"; } private bool boundLocalBindables; From 25fa4a2eb53b00fcb66a6fb2ce4f5fc5dc7d8082 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 17 Jun 2023 19:57:08 +0300 Subject: [PATCH 1259/1400] Move `DragDrop` handling to base game implementation for iOS support --- osu.Desktop/OsuGameDesktop.cs | 45 -------------------------------- osu.Game/OsuGame.cs | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index d92fea27bf..21cea3ba76 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -2,12 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.Versioning; -using System.Threading.Tasks; using Microsoft.Win32; using osu.Desktop.Security; using osu.Framework.Platform; @@ -17,7 +15,6 @@ using osu.Framework; using osu.Framework.Logging; using osu.Game.Updater; using osu.Desktop.Windows; -using osu.Framework.Threading; using osu.Game.IO; using osu.Game.IPC; using osu.Game.Utils; @@ -138,52 +135,10 @@ namespace osu.Desktop desktopWindow.CursorState |= CursorState.Hidden; desktopWindow.Title = Name; - desktopWindow.DragDrop += f => - { - // on macOS, URL associations are handled via SDL_DROPFILE events. - if (f.StartsWith(OSU_PROTOCOL, StringComparison.Ordinal)) - { - HandleLink(f); - return; - } - - fileDrop(new[] { f }); - }; } protected override BatteryInfo CreateBatteryInfo() => new SDL2BatteryInfo(); - private readonly List importableFiles = new List(); - private ScheduledDelegate? importSchedule; - - private void fileDrop(string[] filePaths) - { - lock (importableFiles) - { - importableFiles.AddRange(filePaths); - - Logger.Log($"Adding {filePaths.Length} files for import"); - - // File drag drop operations can potentially trigger hundreds or thousands of these calls on some platforms. - // In order to avoid spawning multiple import tasks for a single drop operation, debounce a touch. - importSchedule?.Cancel(); - importSchedule = Scheduler.AddDelayed(handlePendingImports, 100); - } - } - - private void handlePendingImports() - { - lock (importableFiles) - { - Logger.Log($"Handling batch import of {importableFiles.Count} files"); - - string[] paths = importableFiles.ToArray(); - importableFiles.Clear(); - - Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); - } - } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3768dad370..a80639d4ff 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -28,6 +29,7 @@ using osu.Framework.Input.Events; using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Localisation; using osu.Framework.Logging; +using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; @@ -281,6 +283,52 @@ namespace osu.Game protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + private readonly List dragDropFiles = new List(); + private ScheduledDelegate dragDropImportSchedule; + + public override void SetHost(GameHost host) + { + base.SetHost(host); + + if (host.Window is SDL2Window sdlWindow) + { + sdlWindow.DragDrop += path => + { + // on macOS/iOS, URL associations are handled via SDL_DROPFILE events. + if (path.StartsWith(OSU_PROTOCOL, StringComparison.Ordinal)) + { + HandleLink(path); + return; + } + + lock (dragDropFiles) + { + dragDropFiles.Add(path); + + Logger.Log($@"Adding ""{Path.GetFileName(path)}"" for import"); + + // File drag drop operations can potentially trigger hundreds or thousands of these calls on some platforms. + // In order to avoid spawning multiple import tasks for a single drop operation, debounce a touch. + dragDropImportSchedule?.Cancel(); + dragDropImportSchedule = Scheduler.AddDelayed(handlePendingDragDropImports, 100); + } + }; + } + } + + private void handlePendingDragDropImports() + { + lock (dragDropFiles) + { + Logger.Log($"Handling batch import of {dragDropFiles.Count} files"); + + string[] paths = dragDropFiles.ToArray(); + dragDropFiles.Clear(); + + Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); + } + } + [BackgroundDependencyLoader] private void load() { From eafd774044faad4030a4f4d19a4c26d03e13f2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 17 Jun 2023 20:03:24 +0200 Subject: [PATCH 1260/1400] Bring back old formatting spec --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 91799dabf0..47e5325baf 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -863,7 +863,7 @@ namespace osu.Game.Screens.Select { // Intentionally not localised until we have proper support for this (see https://github.com/ppy/osu-framework/pull/4918 // but also in this case we want support for formatting a number within a string). - FilterControl.InformationalText = Carousel.CountDisplayed != 1 ? $"{Carousel.CountDisplayed} matches" : $"{Carousel.CountDisplayed} match"; + FilterControl.InformationalText = Carousel.CountDisplayed != 1 ? $"{Carousel.CountDisplayed:#,0} matches" : $"{Carousel.CountDisplayed:#,0} match"; } private bool boundLocalBindables; From fdebf93ae41a87010b973a4ec73bbf9312e8b99b Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 17 Jun 2023 14:55:27 -0700 Subject: [PATCH 1261/1400] Fix incorrect xmldoc of `IBeatmapInfo.Length` --- osu.Game/Beatmaps/IBeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/IBeatmapInfo.cs b/osu.Game/Beatmaps/IBeatmapInfo.cs index 4f2c08f63d..b8c69cc525 100644 --- a/osu.Game/Beatmaps/IBeatmapInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapInfo.cs @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps IBeatmapSetInfo? BeatmapSet { get; } /// - /// The playable length in milliseconds of this beatmap. + /// The total length in milliseconds of this beatmap. /// double Length { get; } From 9ae864c219c1bed9f6777383f9ddcbf13fca4019 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sat, 17 Jun 2023 15:00:32 -0700 Subject: [PATCH 1262/1400] Fix beatmap info length tooltip not showing actual drain length --- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 1 + osu.Game/Beatmaps/IBeatmapOnlineInfo.cs | 5 +++++ osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 10 ++++++++++ osu.Game/Overlays/BeatmapSet/BasicStats.cs | 8 ++++---- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index a27c4ddad2..d9763ef6c8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -86,6 +86,7 @@ namespace osu.Game.Tests.Visual.Online StarRating = 9.99, DifficultyName = @"TEST", Length = 456000, + HitLength = 400000, RulesetID = 3, CircleSize = 1, DrainRate = 2.3f, diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs index e1634e7d24..707a0696ba 100644 --- a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -59,5 +59,10 @@ namespace osu.Game.Beatmaps int PassCount { get; } APIFailTimes? FailTimes { get; } + + /// + /// The playable length in milliseconds of this beatmap. + /// + double HitLength { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 7d6740ee46..902b651be9 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -63,6 +63,16 @@ namespace osu.Game.Online.API.Requests.Responses set => Length = TimeSpan.FromSeconds(value).TotalMilliseconds; } + [JsonIgnore] + public double HitLength { get; set; } + + [JsonProperty(@"hit_length")] + private double hitLengthInSeconds + { + get => TimeSpan.FromMilliseconds(HitLength).TotalSeconds; + set => HitLength = TimeSpan.FromSeconds(value).TotalMilliseconds; + } + [JsonProperty(@"convert")] public bool Convert { get; set; } diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 4a9a3d8089..3cc655d561 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -68,13 +68,13 @@ namespace osu.Game.Overlays.BeatmapSet } else { - length.TooltipText = BeatmapsetsStrings.ShowStatsTotalLength(TimeSpan.FromMilliseconds(beatmapInfo.Length).ToFormattedDuration()); length.Value = TimeSpan.FromMilliseconds(beatmapInfo.Length).ToFormattedDuration(); - var onlineInfo = beatmapInfo as IBeatmapOnlineInfo; + if (beatmapInfo is not IBeatmapOnlineInfo onlineInfo) return; - circleCount.Value = (onlineInfo?.CircleCount ?? 0).ToLocalisableString(@"N0"); - sliderCount.Value = (onlineInfo?.SliderCount ?? 0).ToLocalisableString(@"N0"); + circleCount.Value = onlineInfo.CircleCount.ToLocalisableString(@"N0"); + sliderCount.Value = onlineInfo.SliderCount.ToLocalisableString(@"N0"); + length.TooltipText = BeatmapsetsStrings.ShowStatsTotalLength(TimeSpan.FromMilliseconds(onlineInfo.HitLength).ToFormattedDuration()); } } From eb31fdecee97c8551788aa6422aac492357230fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 12 Jun 2023 13:48:56 +0900 Subject: [PATCH 1263/1400] Apply osu! side changes in line with `FocusedOverlayContainer.PopIn` `abstract` change See https://github.com/ppy/osu-framework/pull/5834 --- .../Visual/UserInterface/TestSceneOverlayContainer.cs | 4 ++++ osu.Game/Collections/ManageCollectionsDialog.cs | 2 -- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 1 - osu.Game/Overlays/AccountCreationOverlay.cs | 1 - osu.Game/Overlays/ChatOverlay.cs | 2 -- osu.Game/Overlays/DialogOverlay.cs | 1 - osu.Game/Overlays/LoginOverlay.cs | 2 -- osu.Game/Overlays/MedalOverlay.cs | 6 +++++- osu.Game/Overlays/Mods/ShearedOverlayContainer.cs | 1 - osu.Game/Overlays/NotificationOverlay.cs | 2 -- osu.Game/Overlays/NowPlayingOverlay.cs | 2 -- osu.Game/Overlays/SettingsPanel.cs | 2 -- osu.Game/Overlays/WaveOverlayContainer.cs | 2 -- .../OnlinePlay/Match/Components/RoomSettingsOverlay.cs | 2 -- osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs | 2 -- 15 files changed, 9 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs index d9c2774611..bb94912c83 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayContainer.cs @@ -101,6 +101,10 @@ namespace osu.Game.Tests.Visual.UserInterface }, }; } + + protected override void PopIn() + { + } } } } diff --git a/osu.Game/Collections/ManageCollectionsDialog.cs b/osu.Game/Collections/ManageCollectionsDialog.cs index 36142cf26f..31016b807b 100644 --- a/osu.Game/Collections/ManageCollectionsDialog.cs +++ b/osu.Game/Collections/ManageCollectionsDialog.cs @@ -114,8 +114,6 @@ namespace osu.Game.Collections protected override void PopIn() { - base.PopIn(); - lowPassFilter.CutoffTo(300, 100, Easing.OutCubic); this.FadeIn(enter_duration, Easing.OutQuint); this.ScaleTo(0.9f).Then().ScaleTo(1f, enter_duration, Easing.OutQuint); diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 07b5b53e0e..f92cfc2306 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -152,7 +152,6 @@ namespace osu.Game.Graphics.Containers protected override void PopOut() { - base.PopOut(); previewTrackManager.StopAnyPlaying(this); } diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 6f79316670..ef2e055eae 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -90,7 +90,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); this.FadeIn(transition_time, Easing.OutQuint); if (welcomeScreen.GetChildScreen() != null) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 96dbfe31f3..87df08ceec 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -276,8 +276,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - this.MoveToY(0, transition_length, Easing.OutQuint); this.FadeIn(transition_length, Easing.OutQuint); } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 098a5d0a33..005162bbcc 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -99,7 +99,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); lowPassFilter.CutoffTo(300, 100, Easing.OutCubic); } diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 536811dfcf..8b60024682 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -75,8 +75,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - panel.Bounding = true; this.FadeIn(transition_time, Easing.OutQuint); diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index bd895fe6bf..eba35ec6f9 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -246,9 +246,13 @@ namespace osu.Game.Overlays } } + protected override void PopIn() + { + this.FadeIn(200); + } + protected override void PopOut() { - base.PopOut(); this.FadeOut(200); } diff --git a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs index 7f7b09a62c..a372ec70db 100644 --- a/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs +++ b/osu.Game/Overlays/Mods/ShearedOverlayContainer.cs @@ -130,7 +130,6 @@ namespace osu.Game.Overlays.Mods { const double fade_in_duration = 400; - base.PopIn(); this.FadeIn(fade_in_duration, Easing.OutQuint); Header.MoveToY(0, fade_in_duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index f2eefb6e4b..15e6c94b34 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -206,8 +206,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - this.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); mainContent.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); mainContent.FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index e3e3b4bd80..15eefb2d9f 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -229,8 +229,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - this.FadeIn(transition_length, Easing.OutQuint); dragContainer.ScaleTo(1, transition_length, Easing.OutElastic); } diff --git a/osu.Game/Overlays/SettingsPanel.cs b/osu.Game/Overlays/SettingsPanel.cs index 1681187f82..d7f39a9d8f 100644 --- a/osu.Game/Overlays/SettingsPanel.cs +++ b/osu.Game/Overlays/SettingsPanel.cs @@ -163,8 +163,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); SectionsContainer.FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 00474cc0d8..34fbec93b7 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -34,8 +34,6 @@ namespace osu.Game.Overlays protected override void PopIn() { - base.PopIn(); - Waves.Show(); this.FadeIn(100, Easing.OutQuint); } diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs index 4d4fe4ea56..05232fe0e2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/RoomSettingsOverlay.cs @@ -54,14 +54,12 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components protected override void PopIn() { - base.PopIn(); Settings.MoveToY(0, TRANSITION_DURATION, Easing.OutQuint); Settings.FadeIn(TRANSITION_DURATION / 2); } protected override void PopOut() { - base.PopOut(); Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine); Settings.Delay(TRANSITION_DURATION / 2).FadeOut(TRANSITION_DURATION / 2); } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index c92dc2e343..5753c268d9 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -86,8 +86,6 @@ namespace osu.Game.Screens.Select.Options protected override void PopIn() { - base.PopIn(); - this.FadeIn(transition_duration, Easing.OutQuint); if (buttonsContainer.Position.X == 1 || Alpha == 0) From d9c00fc4be6aeb7fba570ccee75e39095d0363f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 18 Jun 2023 20:57:43 +0900 Subject: [PATCH 1264/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f4d08e443c..522d28dca7 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e08b09aef9..4b9f37270b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 9aafec6c50..96396ca4ad 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 62f01e4f4008421280925c7bd26608f084c10ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 13:49:29 +0200 Subject: [PATCH 1265/1400] Rename `ModState` members to better convey what's what --- osu.Game/Overlays/Mods/ModColumn.cs | 2 +- osu.Game/Overlays/Mods/ModPanel.cs | 8 ++++---- osu.Game/Overlays/Mods/ModState.cs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 610fd4e935..0845edf7f8 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.Mods foreach (var mod in availableMods) { mod.Active.BindValueChanged(_ => updateState()); - mod.MatchingFilter.BindValueChanged(_ => updateState()); + mod.MatchingTextFilter.BindValueChanged(_ => updateState()); mod.ValidForSelection.BindValueChanged(_ => updateState()); } diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 86ecdfa31d..3f85e0b5eb 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.Mods base.LoadComplete(); modState.ValidForSelection.BindValueChanged(_ => updateFilterState()); - modState.MatchingFilter.BindValueChanged(_ => updateFilterState(), true); + modState.MatchingTextFilter.BindValueChanged(_ => updateFilterState(), true); } protected override void Select() @@ -100,13 +100,13 @@ namespace osu.Game.Overlays.Mods public override bool MatchingFilter { - get => modState.MatchingFilter.Value; + get => modState.MatchingTextFilter.Value; set { - if (modState.MatchingFilter.Value == value) + if (modState.MatchingTextFilter.Value == value) return; - modState.MatchingFilter.Value = value; + modState.MatchingTextFilter.Value = value; } } diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index 5e0d768021..1ec517ca11 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.cs @@ -39,14 +39,14 @@ namespace osu.Game.Overlays.Mods public BindableBool ValidForSelection { get; } = new BindableBool(true); /// - /// Whether the is passing all filters and visible for user + /// Whether the mod is matching the current textual filter. /// - public bool Visible => MatchingFilter.Value && ValidForSelection.Value; + public BindableBool MatchingTextFilter { get; } = new BindableBool(true); /// - /// Whether the mod is matching the current filter, i.e. it is available for user selection. + /// Whether the matches all applicable filters and visible for the user to select. /// - public BindableBool MatchingFilter { get; } = new BindableBool(true); + public bool Visible => MatchingTextFilter.Value && ValidForSelection.Value; public ModState(Mod mod) { From c7e89905767a6cffc6437eece94ddde56d8c2365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 13:51:03 +0200 Subject: [PATCH 1266/1400] Remove unused property --- osu.Game/Overlays/Mods/ModPanel.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 3f85e0b5eb..829a0886c3 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -77,18 +77,6 @@ namespace osu.Game.Overlays.Mods /// public bool Visible => modState.Visible; - public bool ValidForSelection - { - get => modState.ValidForSelection.Value; - set - { - if (modState.ValidForSelection.Value == value) - return; - - modState.ValidForSelection.Value = value; - } - } - #region Filtering support public override IEnumerable FilterTerms => new[] From 1b4d7db1e6254d55683ae9bbb14a7313a82cb088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 13:51:13 +0200 Subject: [PATCH 1267/1400] Remove redundant guard `Bindable` has one of those already. --- osu.Game/Overlays/Mods/ModPanel.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 829a0886c3..14e5040767 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -89,13 +89,7 @@ namespace osu.Game.Overlays.Mods public override bool MatchingFilter { get => modState.MatchingTextFilter.Value; - set - { - if (modState.MatchingTextFilter.Value == value) - return; - - modState.MatchingTextFilter.Value = value; - } + set => modState.MatchingTextFilter.Value = value; } private void updateFilterState() From a1015b4145502fc5951548f2bdcd08de857f13e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 13:59:02 +0200 Subject: [PATCH 1268/1400] Remove duplicated xmldoc and move into relevant region --- osu.Game/Overlays/Mods/ModPanel.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPanel.cs b/osu.Game/Overlays/Mods/ModPanel.cs index 14e5040767..f294b1892d 100644 --- a/osu.Game/Overlays/Mods/ModPanel.cs +++ b/osu.Game/Overlays/Mods/ModPanel.cs @@ -72,13 +72,11 @@ namespace osu.Game.Overlays.Mods Active.Value = false; } - /// - /// Whether the is passing all filters and visible for user - /// - public bool Visible => modState.Visible; - #region Filtering support + /// + public bool Visible => modState.Visible; + public override IEnumerable FilterTerms => new[] { Mod.Name, From 64e96c6d82772e19a4a8cc8733ef8a560eeb5ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:03:26 +0200 Subject: [PATCH 1269/1400] Fix duplicate linq and reword comment --- osu.Game/Overlays/Mods/ModColumn.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 0845edf7f8..60c1282a65 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -150,10 +150,12 @@ namespace osu.Game.Overlays.Mods if (toggleAllCheckbox != null && !SelectionAnimationRunning) { - toggleAllCheckbox.Alpha = availableMods.Any(panel => panel.Visible) ? 1 : 0; + bool anyPanelsVisible = availableMods.Any(panel => panel.Visible); - //Prevent checkbox from checking when column have on valid panels - if (availableMods.Any(panel => panel.Visible)) + toggleAllCheckbox.Alpha = anyPanelsVisible ? 1 : 0; + + // checking `anyPanelsVisible` is important since `.All()` returns `true` for empty enumerables. + if (anyPanelsVisible) toggleAllCheckbox.Current.Value = availableMods.Where(panel => panel.Visible).All(panel => panel.Active.Value); } } From 4c78144d10093b4ee3dcd718d06e7ca8b4b66e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:04:00 +0200 Subject: [PATCH 1270/1400] Remove obvious comment --- osu.Game/Overlays/Mods/ModColumn.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModColumn.cs b/osu.Game/Overlays/Mods/ModColumn.cs index 60c1282a65..d65c94d14d 100644 --- a/osu.Game/Overlays/Mods/ModColumn.cs +++ b/osu.Game/Overlays/Mods/ModColumn.cs @@ -215,7 +215,7 @@ namespace osu.Game.Overlays.Mods foreach (var button in availableMods.Where(b => b.Active.Value)) { if (!button.Visible) - button.Active.Value = false; //If mod panel is hidden change state manually without any animation + button.Active.Value = false; else pendingSelectionOperations.Enqueue(() => button.Active.Value = false); } From 9758e5f840c88b3dc39745a4bd8f7841ef9fcc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:16:31 +0200 Subject: [PATCH 1271/1400] Fix utterly broken test - Was on wrong ruleset, so the mod/free mod sets did literally nothing - `assertHasFreeModButton` had a param that did nothing - Was checking `MatchingFilter` rather than `Visible` --- .../TestSceneMultiplayerMatchSongSelect.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs index 23090e9da4..947b7e5be6 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs @@ -94,6 +94,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestCase(typeof(OsuModHidden), typeof(OsuModTraceable))] // Incompatible. public void TestAllowedModDeselectedWhenRequired(Type allowedMod, Type requiredMod) { + AddStep("change ruleset", () => Ruleset.Value = new OsuRuleset().RulesetInfo); AddStep($"select {allowedMod.ReadableName()} as allowed", () => songSelect.FreeMods.Value = new[] { (Mod)Activator.CreateInstance(allowedMod) }); AddStep($"select {requiredMod.ReadableName()} as required", () => songSelect.Mods.Value = new[] { (Mod)Activator.CreateInstance(requiredMod) }); @@ -102,17 +103,17 @@ namespace osu.Game.Tests.Visual.Multiplayer // A previous test's mod overlay could still be fading out. AddUntilStep("wait for only one freemod overlay", () => this.ChildrenOfType().Count() == 1); - assertHasFreeModButton(allowedMod, false); - assertHasFreeModButton(requiredMod, false); + assertFreeModNotShown(allowedMod); + assertFreeModNotShown(requiredMod); } - private void assertHasFreeModButton(Type type, bool hasButton = true) + private void assertFreeModNotShown(Type type) { - AddAssert($"{type.ReadableName()} {(hasButton ? "displayed" : "not displayed")} in freemod overlay", + AddAssert($"{type.ReadableName()} not displayed in freemod overlay", () => this.ChildrenOfType() .Single() .ChildrenOfType() - .Where(panel => panel.MatchingFilter) + .Where(panel => panel.Visible) .All(b => b.Mod.GetType() != type)); } From 76f509a1db5d57601595b3c050d3ba9458e3383e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:19:38 +0200 Subject: [PATCH 1272/1400] Do not use `?? true` pattern Universally disliked. `!= false` is preferred. --- osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs index 255dbfcdd3..18739c0275 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModColumn.cs @@ -334,7 +334,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void setFilter(Func? filter) { foreach (var modState in this.ChildrenOfType().Single().AvailableMods) - modState.ValidForSelection.Value = filter?.Invoke(modState.Mod) ?? true; + modState.ValidForSelection.Value = filter?.Invoke(modState.Mod) != false; } private partial class TestModColumn : ModColumn From b9156b1df312789c17b8815120e84b19f096784b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:24:35 +0200 Subject: [PATCH 1273/1400] Reword/rename some stuff in test --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index ffc0a0a0ad..868ee2c73c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -678,10 +678,10 @@ namespace osu.Game.Tests.Visual.UserInterface } /// - /// Internal search applies from code by setting + /// Covers columns hiding/unhiding on changes of . /// [Test] - public void TestColumnHidingOnInternalSearch() + public void TestColumnHidingOnIsValidChange() { AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay { @@ -711,10 +711,10 @@ namespace osu.Game.Tests.Visual.UserInterface } /// - /// External search applies by user by entering search term into search bar + /// Covers columns hiding/unhiding on changes of . /// [Test] - public void TestColumnHidingOnExternalSearch() + public void TestColumnHidingOnTextFilterChange() { AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay { @@ -738,7 +738,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestHidingOverlayClearsSearch() + public void TestHidingOverlayClearsTextSearch() { AddStep("create screen", () => Child = modSelectOverlay = new TestModSelectOverlay { From 28f929dc4db740c5037c99d77f36791927a36f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:28:26 +0200 Subject: [PATCH 1274/1400] Remove yet another redundant guard --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 574d18de0e..a741a7a005 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -70,13 +70,7 @@ namespace osu.Game.Overlays.Mods public string SearchTerm { get => SearchTextBox.Current.Value; - set - { - if (SearchTextBox.Current.Value == value) - return; - - SearchTextBox.Current.Value = value; - } + set => SearchTextBox.Current.Value = value; } public ShearedSearchTextBox SearchTextBox { get; private set; } = null!; From a49af06e883d4270cca6061c8c8d8864be6283af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:34:33 +0200 Subject: [PATCH 1275/1400] Reword comments in `ModSelectOverlay` --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index a741a7a005..b12b1a7df4 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -247,7 +247,7 @@ namespace osu.Game.Overlays.Mods { base.Hide(); - //We want to clear search for next user interaction with mod overlay + // clear search for next user interaction with mod overlay SearchTextBox.Current.Value = string.Empty; } @@ -615,7 +615,9 @@ namespace osu.Game.Overlays.Mods hideOverlay(true); return true; - //This is handled locally here to prevent search box from coupling in DeselectAllModsButton + // This is handled locally here due to conflicts in input handling between the search text box and the deselect all mods button. + // Attempting to handle this action locally in both places leads to a possible scenario + // wherein activating the binding will both change the contents of the search text box and deselect all mods. case GlobalAction.DeselectAllMods: { if (!SearchTextBox.HasFocus) @@ -664,7 +666,9 @@ namespace osu.Game.Overlays.Mods /// /// - /// This is handled locally here to allow handle first + /// This is handled locally here due to conflicts in input handling between the search text box and the select all mods button. + /// Attempting to handle this action locally in both places leads to a possible scenario + /// wherein activating the "select all" platform binding will both select all text in the search box and select all mods. /// > public bool OnPressed(KeyBindingPressEvent e) { @@ -832,8 +836,7 @@ namespace osu.Game.Overlays.Mods if (!Active.Value) RequestScroll?.Invoke(this); - //By doing this we kill the focus on SearchTextBox. - //Killing focus is done here because it's the only feasible place on ModSelectOverlay you can click on without triggering any action. + // Killing focus is done here because it's the only feasible place on ModSelectOverlay you can click on without triggering any action. Scheduler.Add(() => GetContainingInputManager().ChangeFocus(null)); return true; From 0b6c0592e4ee8ab28babdcc3384135e86b3d2145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:45:43 +0200 Subject: [PATCH 1276/1400] Add failing test case for mod preset filtering not working after ruleset change --- .../UserInterface/TestSceneModPresetColumn.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs index 3efdba8754..2d54a4e566 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModPresetColumn.cs @@ -392,6 +392,28 @@ namespace osu.Game.Tests.Visual.UserInterface new HashSet(this.ChildrenOfType().First().Preset.Value.Mods).SetEquals(mods)); } + [Test] + public void TestTextFiltering() + { + ModPresetColumn modPresetColumn = null!; + + AddStep("clear mods", () => SelectedMods.Value = Array.Empty()); + AddStep("create content", () => Child = modPresetColumn = new ModPresetColumn + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + + AddUntilStep("items loaded", () => modPresetColumn.IsLoaded && modPresetColumn.ItemsLoaded); + + AddStep("set osu! ruleset", () => Ruleset.Value = rulesets.GetRuleset(0)); + AddStep("set text filter", () => modPresetColumn.SearchTerm = "First"); + AddUntilStep("one panel visible", () => modPresetColumn.ChildrenOfType().Count(panel => panel.IsPresent), () => Is.EqualTo(1)); + + AddStep("set mania ruleset", () => Ruleset.Value = rulesets.GetRuleset(3)); + AddUntilStep("no panels visible", () => modPresetColumn.ChildrenOfType().Count(panel => panel.IsPresent), () => Is.EqualTo(0)); + } + private ICollection createTestPresets() => new[] { new ModPreset From d4c9eb013e22290fe0b2998abdbf69073aee281e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 14:51:50 +0200 Subject: [PATCH 1277/1400] Fix bugged initial state of matching filter flag Was preventing mod preset panels from refiltering correctly on ruleset change due to the `matchingFilter == value` guard. --- osu.Game/Overlays/Mods/ModSelectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Mods/ModSelectPanel.cs b/osu.Game/Overlays/Mods/ModSelectPanel.cs index cc13657c04..a69fb19c4c 100644 --- a/osu.Game/Overlays/Mods/ModSelectPanel.cs +++ b/osu.Game/Overlays/Mods/ModSelectPanel.cs @@ -286,7 +286,7 @@ namespace osu.Game.Overlays.Mods public abstract IEnumerable FilterTerms { get; } - private bool matchingFilter; + private bool matchingFilter = true; public virtual bool MatchingFilter { From 75300ca2295bce92b70e23450a1b1ffe61efa221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 15:50:25 +0200 Subject: [PATCH 1278/1400] Switch search box to initially unfocused Done primarily to keep mod hotkeys working without any behavioural changes when mod select is opened. --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 10 +++++----- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 868ee2c73c..d566a04261 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -550,12 +550,12 @@ namespace osu.Game.Tests.Visual.UserInterface { createScreen(); - AddStep("click on mod column", navigateAndClick); - AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); - AddStep("click on search", navigateAndClick); AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); + AddStep("click on mod column", navigateAndClick); + AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); + void navigateAndClick() where T : Drawable { InputManager.MoveMouseTo(modSelectOverlay.ChildrenOfType().FirstOrDefault()); @@ -571,10 +571,10 @@ namespace osu.Game.Tests.Visual.UserInterface const Key focus_switch_key = Key.Tab; AddStep("press tab", () => InputManager.Key(focus_switch_key)); - AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); + AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); AddStep("press tab", () => InputManager.Key(focus_switch_key)); - AddAssert("focused", () => modSelectOverlay.SearchTextBox.HasFocus); + AddAssert("lost focus", () => !modSelectOverlay.SearchTextBox.HasFocus); } [Test] diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index b12b1a7df4..23e278e378 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -500,8 +500,6 @@ namespace osu.Game.Overlays.Mods base.PopIn(); - SearchTextBox.TakeFocus(); - aboveColumnsContent .FadeIn(fade_in_duration, Easing.OutQuint) .MoveToY(0, fade_in_duration, Easing.OutQuint); From b87acfa66feb51787b9a46a207d84af762f82865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 15:53:49 +0200 Subject: [PATCH 1279/1400] Dynamically change placeholder to convey how to activate search --- osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs | 7 +++++++ osu.Game/Localisation/ModSelectOverlayStrings.cs | 9 +++++++-- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index a6954fafb1..fb0a66cb8d 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Mods; @@ -37,6 +38,12 @@ namespace osu.Game.Graphics.UserInterface set => textBox.HoldFocus = value; } + public LocalisableString PlaceholderText + { + get => textBox.PlaceholderText; + set => textBox.PlaceholderText = value; + } + public new bool HasFocus => textBox.HasFocus; public void TakeFocus() => textBox.TakeFocus(); diff --git a/osu.Game/Localisation/ModSelectOverlayStrings.cs b/osu.Game/Localisation/ModSelectOverlayStrings.cs index f11c52ee20..05dcf138d7 100644 --- a/osu.Game/Localisation/ModSelectOverlayStrings.cs +++ b/osu.Game/Localisation/ModSelectOverlayStrings.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Localisation; @@ -39,6 +39,11 @@ namespace osu.Game.Localisation /// public static LocalisableString UseCurrentMods => new TranslatableString(getKey(@"use_current_mods"), @"Use current mods"); + /// + /// "tab to search..." + /// + public static LocalisableString TabToSearch => new TranslatableString(getKey(@"tab_to_search"), @"tab to search..."); + private static string getKey(string key) => $@"{prefix}:{key}"; } -} +} \ No newline at end of file diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 23e278e378..2f39758982 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -303,6 +303,13 @@ namespace osu.Game.Overlays.Mods }); } + protected override void Update() + { + base.Update(); + + SearchTextBox.PlaceholderText = SearchTextBox.HasFocus ? Resources.Localisation.Web.CommonStrings.InputSearch : ModSelectOverlayStrings.TabToSearch; + } + /// /// Select all visible mods in all columns. /// From b4c1266fc5ca746cb0ea0c50b0093bc74796038b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 15:56:15 +0200 Subject: [PATCH 1280/1400] Add TODO for future support of typical search shortcuts --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 2f39758982..9035503723 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -693,6 +693,7 @@ namespace osu.Game.Overlays.Mods if (e.Repeat || e.Key != Key.Tab) return false; + // TODO: should probably eventually support typical platform search shortcuts (`Ctrl-F`, `/`) if (SearchTextBox.HasFocus) SearchTextBox.KillFocus(); else From 425d3c23f5265b136c9a385304897db208b9b6b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jun 2023 01:02:16 +0900 Subject: [PATCH 1281/1400] Fix some code layout and NRT some classes --- osu.Game/Overlays/Mods/ModState.cs | 2 -- osu.Game/Overlays/Mods/SelectAllModsButton.cs | 2 -- osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs | 13 +++++-------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModState.cs b/osu.Game/Overlays/Mods/ModState.cs index 1ec517ca11..7a5bc0f3ae 100644 --- a/osu.Game/Overlays/Mods/ModState.cs +++ b/osu.Game/Overlays/Mods/ModState.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Overlays/Mods/SelectAllModsButton.cs b/osu.Game/Overlays/Mods/SelectAllModsButton.cs index dd14514a3b..bb61cdc35d 100644 --- a/osu.Game/Overlays/Mods/SelectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/SelectAllModsButton.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs index d5e57b9ec9..4d5d724089 100644 --- a/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/FreeModSelectOverlay.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. -#nullable disable - using System; using osu.Game.Overlays; using System.Collections.Generic; @@ -36,11 +34,10 @@ namespace osu.Game.Screens.OnlinePlay protected override IEnumerable CreateFooterButtons() => base.CreateFooterButtons() - .Prepend( - SelectAllModsButton = new SelectAllModsButton(this) - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - }); + .Prepend(SelectAllModsButton = new SelectAllModsButton(this) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); } } From db445660e763b510ce4a7214e9f8614045a87546 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jun 2023 01:06:45 +0900 Subject: [PATCH 1282/1400] Avoid resolving realm `Live` more than once --- osu.Game/Overlays/Mods/ModPresetPanel.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModPresetPanel.cs b/osu.Game/Overlays/Mods/ModPresetPanel.cs index 607d236781..00f6e36972 100644 --- a/osu.Game/Overlays/Mods/ModPresetPanel.cs +++ b/osu.Game/Overlays/Mods/ModPresetPanel.cs @@ -88,10 +88,12 @@ namespace osu.Game.Overlays.Mods private IEnumerable getFilterTerms() { - yield return Preset.Value.Name; - yield return Preset.Value.Description; + var preset = Preset.Value; - foreach (Mod mod in Preset.Value.Mods) + yield return preset.Name; + yield return preset.Description; + + foreach (Mod mod in preset.Mods) { yield return mod.Name; yield return mod.Acronym; From bd174b5193f06f81dea4da34fb3e3d596fe39d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 18:37:04 +0200 Subject: [PATCH 1283/1400] Revert to non-bindable `AccentColour` Not necessary for now, so let's not incur unnecessary overheads. --- .../TestSceneTournamentMatchChatDisplay.cs | 4 +-- osu.Game/Overlays/Chat/ChatLine.cs | 27 +++++++++---------- .../Overlays/Chat/DrawableChatUsername.cs | 12 +++------ 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index 71d8cbeea7..fada340cf7 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team red is red color", () => - this.ChildrenOfType().Any(s => s.AccentColour.Value == TournamentGame.COLOUR_RED)); + this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_RED)); AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { @@ -105,7 +105,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team blue is blue color", () => - this.ChildrenOfType().Any(s => s.AccentColour.Value == TournamentGame.COLOUR_BLUE)); + this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_BLUE)); AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 2931685239..13f26e6fcc 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -93,19 +93,6 @@ namespace osu.Game.Overlays.Chat configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime); prefer24HourTime.BindValueChanged(_ => updateTimestamp()); - drawableUsername = new DrawableChatUsername(message.Sender) - { - Width = UsernameWidth, - FontSize = FontSize, - AutoSizeAxes = Axes.Y, - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Margin = new MarginPadding { Horizontal = Spacing }, - Inverted = !string.IsNullOrEmpty(message.Sender.Colour), - }; - - drawableUsername.AccentColour.Value = UsernameColour; - InternalChild = new GridContainer { RelativeSizeAxes = Axes.X, @@ -129,7 +116,17 @@ namespace osu.Game.Overlays.Chat Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true), AlwaysPresent = true, }, - drawableUsername, + drawableUsername = new DrawableChatUsername(message.Sender) + { + Width = UsernameWidth, + FontSize = FontSize, + AutoSizeAxes = Axes.Y, + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Margin = new MarginPadding { Horizontal = Spacing }, + AccentColour = UsernameColour, + Inverted = !string.IsNullOrEmpty(message.Sender.Colour), + }, drawableContentFlow = new LinkFlowContainer(styleMessageContent) { AutoSizeAxes = Axes.Y, @@ -175,7 +172,7 @@ namespace osu.Game.Overlays.Chat CornerRadius = 2f, Masking = true, RelativeSizeAxes = Axes.Both, - Colour = drawableUsername.AccentColour.Value.Darken(1f), + Colour = drawableUsername.AccentColour.Darken(1f), Depth = float.MaxValue, Child = new Box { RelativeSizeAxes = Axes.Both } }); diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index 05772051da..cb5df93e00 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Chat { public Action? ReportRequested; - public Bindable AccentColour { get; } = new Bindable(); + public Color4 AccentColour { get; init; } public bool Inverted { get; init; } @@ -146,11 +146,7 @@ namespace osu.Game.Overlays.Chat { base.LoadComplete(); drawableText.Colour = colours.ChatBlue; - - AccentColour.BindValueChanged(c => - { - colouredDrawable.Colour = c.NewValue; - }, true); + colouredDrawable.Colour = AccentColour; } public MenuItem[] ContextMenuItems @@ -196,7 +192,7 @@ namespace osu.Game.Overlays.Chat protected override bool OnHover(HoverEvent e) { - colouredDrawable.FadeColour(AccentColour.Value.Lighten(0.6f), 30, Easing.OutQuint); + colouredDrawable.FadeColour(AccentColour.Lighten(0.6f), 30, Easing.OutQuint); return base.OnHover(e); } @@ -205,7 +201,7 @@ namespace osu.Game.Overlays.Chat { base.OnHoverLost(e); - colouredDrawable.FadeColour(AccentColour.Value, 800, Easing.OutQuint); + colouredDrawable.FadeColour(AccentColour, 800, Easing.OutQuint); } } } From dad32817ee49bece00f2cf42e9648e4cbe9e293c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 18:37:28 +0200 Subject: [PATCH 1284/1400] Improve `UsernameColour` documentation --- osu.Game/Overlays/Chat/ChatLine.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 13f26e6fcc..b2024e15c7 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -70,8 +70,16 @@ namespace osu.Game.Overlays.Chat private Container? highlight; /// - /// if set, it will override or . + /// The colour to use to paint the chat mesasge author's username. /// + /// + /// The colour can be set explicitly by consumers via the property initialiser. + /// If unspecified, the colour is by default initialised to: + /// + /// message.Sender.Colour, if non-empty, + /// a random colour from if the above is empty. + /// + /// public Color4 UsernameColour { get; init; } public ChatLine(Message message) @@ -81,7 +89,8 @@ namespace osu.Game.Overlays.Chat RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - // If we have custom value, this value will be override. + // initialise using sane defaults. + // consumers can use the initialiser of `UsernameColour` to override this if they wish to. UsernameColour = !string.IsNullOrEmpty(message.Sender.Colour) ? Color4Extensions.FromHex(message.Sender.Colour) : default_colours[message.SenderId % default_colours.Length]; From a2a9823d8400513ed20cdf895931a15c78f8dcc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 18:43:55 +0200 Subject: [PATCH 1285/1400] Rename constant --- osu.Game/Overlays/Chat/ChatLine.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index b2024e15c7..fdf91dce23 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Chat /// If unspecified, the colour is by default initialised to: /// /// message.Sender.Colour, if non-empty, - /// a random colour from if the above is empty. + /// a random colour from if the above is empty. /// /// public Color4 UsernameColour { get; init; } @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Chat // consumers can use the initialiser of `UsernameColour` to override this if they wish to. UsernameColour = !string.IsNullOrEmpty(message.Sender.Colour) ? Color4Extensions.FromHex(message.Sender.Colour) - : default_colours[message.SenderId % default_colours.Length]; + : default_username_colours[message.SenderId % default_username_colours.Length]; } [BackgroundDependencyLoader] @@ -220,7 +220,7 @@ namespace osu.Game.Overlays.Chat drawableTimestamp.Text = message.Timestamp.LocalDateTime.ToLocalisableString(prefer24HourTime.Value ? @"HH:mm:ss" : @"hh:mm:ss tt"); } - private static readonly Color4[] default_colours = + private static readonly Color4[] default_username_colours = { Color4Extensions.FromHex("588c7e"), Color4Extensions.FromHex("b2a367"), From ee08ed414c1c4fa60458fd07fd96150c8d61b10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 18:45:53 +0200 Subject: [PATCH 1286/1400] Document `DrawableChatUsername` members --- osu.Game/Overlays/Chat/DrawableChatUsername.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/Chat/DrawableChatUsername.cs b/osu.Game/Overlays/Chat/DrawableChatUsername.cs index cb5df93e00..21c3bd4b40 100644 --- a/osu.Game/Overlays/Chat/DrawableChatUsername.cs +++ b/osu.Game/Overlays/Chat/DrawableChatUsername.cs @@ -33,8 +33,15 @@ namespace osu.Game.Overlays.Chat { public Action? ReportRequested; + /// + /// The primary colour to use for the username. + /// public Color4 AccentColour { get; init; } + /// + /// If set to , the username will be drawn as plain text in . + /// If set to , the username will be drawn as black text inside a rounded rectangle in . + /// public bool Inverted { get; init; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => From 1a6a66e953b1325561f7a8f0d289cfe8bcc6bdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 18 Jun 2023 18:48:54 +0200 Subject: [PATCH 1287/1400] Rewrite assertions to be better --- .../Components/TestSceneTournamentMatchChatDisplay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index fada340cf7..b552d49d1d 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -4,6 +4,7 @@ #nullable disable using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -90,7 +91,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team red is red color", () => - this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_RED)); + this.ChildrenOfType().Last().AccentColour, () => Is.EqualTo(TournamentGame.COLOUR_RED)); AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { @@ -105,7 +106,7 @@ namespace osu.Game.Tournament.Tests.Components })); AddUntilStep("message from team blue is blue color", () => - this.ChildrenOfType().Any(s => s.AccentColour == TournamentGame.COLOUR_BLUE)); + this.ChildrenOfType().Last().AccentColour, () => Is.EqualTo(TournamentGame.COLOUR_BLUE)); AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { From 0900cebc0dc03bd720ff11b5058fe68aa793d0af Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jun 2023 20:09:53 +0900 Subject: [PATCH 1288/1400] Avoid doing expensive colour fetch operation every update --- osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs index 2aec416867..6918993696 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs @@ -7,6 +7,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Screens.Edit; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -26,14 +27,20 @@ namespace osu.Game.Rulesets.Osu.Mods currentBeatmap = beatmap; } - public void ApplyToDrawableHitObject(DrawableHitObject drawable) + public void ApplyToDrawableHitObject(DrawableHitObject d) { if (currentBeatmap == null) return; - drawable.OnUpdate += _ => - drawable.AccentColour.Value = BindableBeatDivisor.GetColourFor( - currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(drawable.HitObject.StartTime), - colours); + Color4? timingBasedColour = null; + + d.HitObjectApplied += _ => timingBasedColour = BindableBeatDivisor.GetColourFor(currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(d.HitObject.StartTime), colours); + + // Need to set this every update to ensure it doesn't get overwritten by DrawableHitObject.OnApply() -> UpdateComboColour(). + d.OnUpdate += _ => + { + if (timingBasedColour != null) + d.AccentColour.Value = timingBasedColour.Value; + }; } } } From 84fc6e92db99d725c24e7e4e6412d629a36a099b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jun 2023 20:23:46 +0900 Subject: [PATCH 1289/1400] Fix slightly incorrect calculations --- .../Edit/Compose/Components/CircularDistanceSnapGrid.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index cf8b0c14ed..602ed6f627 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -65,14 +65,14 @@ namespace osu.Game.Screens.Edit.Compose.Components for (int i = 0; i < requiredCircles; i++) { - float diameter = (offset + (i + 1) * DistanceBetweenTicks) * 2; const float thickness = 4; + float diameter = (offset + (i + 1) * DistanceBetweenTicks + thickness / 2) * 2; AddInternal(new Ring(ReferenceObject, GetColourForIndexFromPlacement(i)) { Position = StartPosition, Origin = Anchor.Centre, - Size = new Vector2(diameter + thickness / 2), + Size = new Vector2(diameter), InnerRadius = thickness * 1f / diameter, }); } From 69526f25bb9743bb3fdca14a4c105bbd9d8465b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 19 Jun 2023 20:43:33 +0900 Subject: [PATCH 1290/1400] Add hotkey to save replay Defaults to `F2` aka stable. --- .../Input/Bindings/GlobalActionContainer.cs | 4 ++++ .../GlobalActionKeyBindingStrings.cs | 5 +++++ .../Screens/Play/SaveFailedScoreButton.cs | 21 ++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index fdd96d3890..0ae29ebc8e 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -119,6 +119,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay), new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD), new KeyBinding(InputKey.Tab, GlobalAction.ToggleChatFocus), + new KeyBinding(InputKey.F2, GlobalAction.SaveReplay), }; public IEnumerable ReplayKeyBindings => new[] @@ -366,5 +367,8 @@ namespace osu.Game.Input.Bindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCycleNextBeatSnapDivisor))] EditorCycleNextBeatSnapDivisor, + + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SaveReplay))] + SaveReplay, } } diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs index aa608a603b..708fdaa174 100644 --- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -324,6 +324,11 @@ namespace osu.Game.Localisation /// public static LocalisableString ToggleChatFocus => new TranslatableString(getKey(@"toggle_chat_focus"), @"Toggle chat focus"); + /// + /// "Save replay" + /// + public static LocalisableString SaveReplay => new TranslatableString(getKey(@"save_replay"), @"Save replay"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index 20d2130e76..c5bb265dcb 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -8,15 +8,18 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Database; using osu.Game.Scoring; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osu.Game.Online; using osuTK; namespace osu.Game.Screens.Play { - public partial class SaveFailedScoreButton : CompositeDrawable + public partial class SaveFailedScoreButton : CompositeDrawable, IKeyBindingHandler { private readonly Bindable state = new Bindable(); @@ -87,5 +90,21 @@ namespace osu.Game.Screens.Play } }, true); } + + public bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case GlobalAction.SaveReplay: + button.TriggerClick(); + return true; + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } } } From 6d32206a08e0f854fa67ef751c1032679072938f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 19 Jun 2023 17:47:01 +0200 Subject: [PATCH 1291/1400] Fix slider tails receiving wrong colours Only visually apparent on legacy skins. --- osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs index 6918993696..9537f8b388 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSynesthesia.cs @@ -6,6 +6,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Screens.Edit; using osuTK.Graphics; @@ -33,7 +34,15 @@ namespace osu.Game.Rulesets.Osu.Mods Color4? timingBasedColour = null; - d.HitObjectApplied += _ => timingBasedColour = BindableBeatDivisor.GetColourFor(currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(d.HitObject.StartTime), colours); + d.HitObjectApplied += _ => + { + // slider tails are a painful edge case, as their start time is offset 36ms back (see `LegacyLastTick`). + // to work around this, look up the slider tail's parenting slider's end time instead to ensure proper snap. + double snapTime = d is DrawableSliderTail tail + ? tail.Slider.GetEndTime() + : d.HitObject.StartTime; + timingBasedColour = BindableBeatDivisor.GetColourFor(currentBeatmap.ControlPointInfo.GetClosestBeatDivisor(snapTime), colours); + }; // Need to set this every update to ensure it doesn't get overwritten by DrawableHitObject.OnApply() -> UpdateComboColour(). d.OnUpdate += _ => From 9bcd86d66d8514319ce75f14bbd7362eb1a50688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 19 Jun 2023 18:42:30 +0200 Subject: [PATCH 1292/1400] Fix test failure due to relying on implementation detail --- .../Editor/TestSceneOsuDistanceSnapGrid.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs index 7579e8077b..0c064ecfa6 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuDistanceSnapGrid.cs @@ -185,7 +185,18 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor AddAssert("Ensure cursor is on a grid line", () => { - return grid.ChildrenOfType().Any(p => Precision.AlmostEquals(p.ScreenSpaceDrawQuad.TopRight.X, grid.ToScreenSpace(cursor.LastSnappedPosition).X)); + return grid.ChildrenOfType().Any(ring => + { + // the grid rings are actually slightly _larger_ than the snapping radii. + // this is done such that the snapping radius falls right in the middle of each grid ring thickness-wise, + // but it does however complicate the following calculations slightly. + + // we want to calculate the coordinates of the rightmost point on the grid line, which is in the exact middle of the ring thickness-wise. + // for the X component, we take the entire width of the ring, minus one half of the inner radius (since we want the middle of the line on the right side). + // for the Y component, we just take 0.5f. + var rightMiddleOfGridLine = ring.ToScreenSpace(ring.DrawSize * new Vector2(1 - ring.InnerRadius / 2, 0.5f)); + return Precision.AlmostEquals(rightMiddleOfGridLine.X, grid.ToScreenSpace(cursor.LastSnappedPosition).X); + }); }); } From 362fe62b4bbea9b590614b6df05587ad602fb2d0 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 19 Jun 2023 10:20:56 -0700 Subject: [PATCH 1293/1400] Fix beatmap info not showing individual difficulty bpm --- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 3cc655d561..0b1befe7b9 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -58,16 +58,18 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - bpm.Value = BeatmapSet?.BPM.ToLocalisableString(@"0.##") ?? (LocalisableString)"-"; - if (beatmapInfo == null) { + bpm.Value = "-"; + length.Value = string.Empty; circleCount.Value = string.Empty; sliderCount.Value = string.Empty; } else { + bpm.Value = beatmapInfo.BPM.ToLocalisableString(@"0.##"); + length.Value = TimeSpan.FromMilliseconds(beatmapInfo.Length).ToFormattedDuration(); if (beatmapInfo is not IBeatmapOnlineInfo onlineInfo) return; From 4a9543092a663a7695368c4fadb691c174a2a3d4 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 17:08:04 -0400 Subject: [PATCH 1294/1400] disable posting comments when logged out --- osu.Game/Overlays/Comments/CommentEditor.cs | 25 +++++++++++++++++-- .../Overlays/Comments/ReplyCommentEditor.cs | 3 ++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 2af7dd3093..5c9f78d05f 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -13,6 +13,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -26,6 +29,8 @@ namespace osu.Game.Overlays.Comments protected abstract LocalisableString CommitButtonText { get; } + private LocalisableString textBoxPlaceholderLoggedOut => AuthorizationStrings.RequireLogin; + protected abstract LocalisableString TextBoxPlaceholder { get; } protected FillFlowContainer ButtonsContainer { get; private set; } = null!; @@ -37,6 +42,13 @@ namespace osu.Game.Overlays.Comments protected TextBox TextBox { get; private set; } = null!; + protected readonly IBindable User = new Bindable(); + + [Resolved] + private IAPIProvider api { get; set; } = null!; + + private LocalisableString placeholderText => api.IsLoggedIn ? TextBoxPlaceholder : textBoxPlaceholderLoggedOut; + protected bool ShowLoadingSpinner { set @@ -78,8 +90,9 @@ namespace osu.Game.Overlays.Comments { Height = 40, RelativeSizeAxes = Axes.X, - PlaceholderText = TextBoxPlaceholder, - Current = Current + PlaceholderText = placeholderText, + Current = Current, + ReadOnly = !api.IsLoggedIn }, new Container { @@ -134,12 +147,14 @@ namespace osu.Game.Overlays.Comments }); TextBox.OnCommit += (_, _) => commitButton.TriggerClick(); + User.BindTo(api.LocalUser); } protected override void LoadComplete() { base.LoadComplete(); Current.BindValueChanged(_ => updateCommitButtonState(), true); + User.BindValueChanged(_ => updateTextBoxState()); } protected abstract void OnCommit(string text); @@ -147,6 +162,12 @@ namespace osu.Game.Overlays.Comments private void updateCommitButtonState() => commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); + private void updateTextBoxState() + { + TextBox.PlaceholderText = placeholderText; + TextBox.ReadOnly = !api.IsLoggedIn; + } + private partial class EditorTextBox : OsuTextBox { protected override float LeftRightPadding => side_padding; diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index 8aca183dee..8c4b25a7dc 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -38,7 +38,8 @@ namespace osu.Game.Overlays.Comments { base.LoadComplete(); - GetContainingInputManager().ChangeFocus(TextBox); + if (!TextBox.ReadOnly) + GetContainingInputManager().ChangeFocus(TextBox); } protected override void OnCommit(string text) From d5d494f07bd7dd97682214f7b386ebfba9ff3655 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 17:36:40 -0400 Subject: [PATCH 1295/1400] resolve protected API in comments superclass --- osu.Game/Overlays/Comments/CommentEditor.cs | 10 +++++----- osu.Game/Overlays/Comments/CommentsContainer.cs | 5 +---- osu.Game/Overlays/Comments/ReplyCommentEditor.cs | 6 +----- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 5c9f78d05f..35c96cf531 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -45,9 +45,9 @@ namespace osu.Game.Overlays.Comments protected readonly IBindable User = new Bindable(); [Resolved] - private IAPIProvider api { get; set; } = null!; + protected IAPIProvider API { get; private set; } = null!; - private LocalisableString placeholderText => api.IsLoggedIn ? TextBoxPlaceholder : textBoxPlaceholderLoggedOut; + private LocalisableString placeholderText => API.IsLoggedIn ? TextBoxPlaceholder : textBoxPlaceholderLoggedOut; protected bool ShowLoadingSpinner { @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.X, PlaceholderText = placeholderText, Current = Current, - ReadOnly = !api.IsLoggedIn + ReadOnly = !API.IsLoggedIn }, new Container { @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Comments }); TextBox.OnCommit += (_, _) => commitButton.TriggerClick(); - User.BindTo(api.LocalUser); + User.BindTo(API.LocalUser); } protected override void LoadComplete() @@ -165,7 +165,7 @@ namespace osu.Game.Overlays.Comments private void updateTextBoxState() { TextBox.PlaceholderText = placeholderText; - TextBox.ReadOnly = !api.IsLoggedIn; + TextBox.ReadOnly = !API.IsLoggedIn; } private partial class EditorTextBox : OsuTextBox diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 24536fe460..f50bbb7116 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -405,9 +405,6 @@ namespace osu.Game.Overlays.Comments [Resolved] private CommentsContainer commentsContainer { get; set; } - [Resolved] - private IAPIProvider api { get; set; } - public Action OnPost; //TODO should match web, left empty due to no multiline support @@ -432,7 +429,7 @@ namespace osu.Game.Overlays.Comments Current.Value = string.Empty; OnPost?.Invoke(cb); }); - api.Queue(req); + API.Queue(req); } } } diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index 8c4b25a7dc..7fbf556e1f 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Logging; -using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Resources.Localisation.Web; @@ -18,9 +17,6 @@ namespace osu.Game.Overlays.Comments [Resolved] private CommentsContainer commentsContainer { get; set; } = null!; - [Resolved] - private IAPIProvider api { get; set; } = null!; - private readonly Comment parentComment; public Action? OnPost; @@ -52,7 +48,7 @@ namespace osu.Game.Overlays.Comments Logger.Error(e, "Posting reply comment failed."); }); req.Success += cb => Schedule(processPostedComments, cb); - api.Queue(req); + API.Queue(req); } private void processPostedComments(CommentBundle cb) From 591277e0f97bc3e2e63219d23c24d38b28daa0eb Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 18:10:37 -0400 Subject: [PATCH 1296/1400] extract button text properties to methods, show login overlay on click --- osu.Game/Overlays/Comments/CommentEditor.cs | 48 ++++++++++++------- .../Overlays/Comments/CommentsContainer.cs | 6 ++- .../Overlays/Comments/ReplyCommentEditor.cs | 8 +++- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 35c96cf531..58fba4bb57 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -15,7 +15,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Resources.Localisation.Web; using osuTK; using osuTK.Graphics; @@ -27,12 +26,6 @@ namespace osu.Game.Overlays.Comments protected abstract LocalisableString FooterText { get; } - protected abstract LocalisableString CommitButtonText { get; } - - private LocalisableString textBoxPlaceholderLoggedOut => AuthorizationStrings.RequireLogin; - - protected abstract LocalisableString TextBoxPlaceholder { get; } - protected FillFlowContainer ButtonsContainer { get; private set; } = null!; protected readonly Bindable Current = new Bindable(string.Empty); @@ -47,7 +40,12 @@ namespace osu.Game.Overlays.Comments [Resolved] protected IAPIProvider API { get; private set; } = null!; - private LocalisableString placeholderText => API.IsLoggedIn ? TextBoxPlaceholder : textBoxPlaceholderLoggedOut; + [Resolved] + private LoginOverlay? loginOverlay { get; set; } + + protected abstract LocalisableString GetCommitButtonText(bool isLoggedIn); + + protected abstract LocalisableString GetTextBoxPlaceholder(bool isLoggedIn); protected bool ShowLoadingSpinner { @@ -90,7 +88,7 @@ namespace osu.Game.Overlays.Comments { Height = 40, RelativeSizeAxes = Axes.X, - PlaceholderText = placeholderText, + PlaceholderText = GetTextBoxPlaceholder(API.IsLoggedIn), Current = Current, ReadOnly = !API.IsLoggedIn }, @@ -128,8 +126,8 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Child = commitButton = new EditorButton { - Text = CommitButtonText, - Action = () => OnCommit(Current.Value) + Text = GetCommitButtonText(API.IsLoggedIn), + Action = () => commitOrLogIn(Current.Value) } }, loadingSpinner = new LoadingSpinner @@ -154,18 +152,34 @@ namespace osu.Game.Overlays.Comments { base.LoadComplete(); Current.BindValueChanged(_ => updateCommitButtonState(), true); - User.BindValueChanged(_ => updateTextBoxState()); + User.BindValueChanged(_ => updateStateForLoggedIn()); } protected abstract void OnCommit(string text); - private void updateCommitButtonState() => - commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); - - private void updateTextBoxState() + private void commitOrLogIn(string text) { - TextBox.PlaceholderText = placeholderText; + if (!API.IsLoggedIn) + { + loginOverlay?.Show(); + return; + } + + OnCommit(text); + } + + private void updateCommitButtonState() + { + bool textBoxValid = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); + commitButton.Enabled.Value = textBoxValid || !API.IsLoggedIn; + } + + private void updateStateForLoggedIn() + { + TextBox.PlaceholderText = GetTextBoxPlaceholder(API.IsLoggedIn); TextBox.ReadOnly = !API.IsLoggedIn; + commitButton.Text = GetCommitButtonText(API.IsLoggedIn); + updateCommitButtonState(); } private partial class EditorTextBox : OsuTextBox diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index f50bbb7116..1dfcb5f5c6 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -410,9 +410,11 @@ namespace osu.Game.Overlays.Comments //TODO should match web, left empty due to no multiline support protected override LocalisableString FooterText => default; - protected override LocalisableString CommitButtonText => CommonStrings.ButtonsPost; + protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + isLoggedIn ? CommonStrings.ButtonsPost : CommentsStrings.GuestButtonNew; - protected override LocalisableString TextBoxPlaceholder => CommentsStrings.PlaceholderNew; + protected override LocalisableString GetTextBoxPlaceholder(bool isLoggedIn) => + isLoggedIn ? CommentsStrings.PlaceholderNew : AuthorizationStrings.RequireLogin; protected override void OnCommit(string text) { diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index 7fbf556e1f..52e301f0a3 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -22,8 +22,12 @@ namespace osu.Game.Overlays.Comments public Action? OnPost; protected override LocalisableString FooterText => default; - protected override LocalisableString CommitButtonText => CommonStrings.ButtonsReply; - protected override LocalisableString TextBoxPlaceholder => CommentsStrings.PlaceholderReply; + + protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + isLoggedIn ? CommonStrings.ButtonsReply : CommentsStrings.GuestButtonReply; + + protected override LocalisableString GetTextBoxPlaceholder(bool isLoggedIn) => + isLoggedIn ? CommentsStrings.PlaceholderReply : AuthorizationStrings.RequireLogin; public ReplyCommentEditor(Comment parent) { From f7dde53f9b11afc256c0bb6103be4904ff0a84df Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 18:20:16 -0400 Subject: [PATCH 1297/1400] use runOnceImmediately instead of duplicating logic --- osu.Game/Overlays/Comments/CommentEditor.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 58fba4bb57..b139fbefe6 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -88,9 +88,7 @@ namespace osu.Game.Overlays.Comments { Height = 40, RelativeSizeAxes = Axes.X, - PlaceholderText = GetTextBoxPlaceholder(API.IsLoggedIn), - Current = Current, - ReadOnly = !API.IsLoggedIn + Current = Current }, new Container { @@ -126,7 +124,6 @@ namespace osu.Game.Overlays.Comments Spacing = new Vector2(5, 0), Child = commitButton = new EditorButton { - Text = GetCommitButtonText(API.IsLoggedIn), Action = () => commitOrLogIn(Current.Value) } }, @@ -152,7 +149,7 @@ namespace osu.Game.Overlays.Comments { base.LoadComplete(); Current.BindValueChanged(_ => updateCommitButtonState(), true); - User.BindValueChanged(_ => updateStateForLoggedIn()); + User.BindValueChanged(_ => updateStateForLoggedIn(), true); } protected abstract void OnCommit(string text); From 60eedbafd1be892a0e248eabb955090eff6eaf48 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 22:05:18 -0400 Subject: [PATCH 1298/1400] rename GetTextBoxPlaceholder to GetPlaceholderText --- osu.Game/Overlays/Comments/CommentEditor.cs | 4 ++-- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/ReplyCommentEditor.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index b139fbefe6..b363fe5881 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Comments protected abstract LocalisableString GetCommitButtonText(bool isLoggedIn); - protected abstract LocalisableString GetTextBoxPlaceholder(bool isLoggedIn); + protected abstract LocalisableString GetPlaceholderText(bool isLoggedIn); protected bool ShowLoadingSpinner { @@ -173,7 +173,7 @@ namespace osu.Game.Overlays.Comments private void updateStateForLoggedIn() { - TextBox.PlaceholderText = GetTextBoxPlaceholder(API.IsLoggedIn); + TextBox.PlaceholderText = GetPlaceholderText(API.IsLoggedIn); TextBox.ReadOnly = !API.IsLoggedIn; commitButton.Text = GetCommitButtonText(API.IsLoggedIn); updateCommitButtonState(); diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 1dfcb5f5c6..e6c69d2090 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -413,7 +413,7 @@ namespace osu.Game.Overlays.Comments protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => isLoggedIn ? CommonStrings.ButtonsPost : CommentsStrings.GuestButtonNew; - protected override LocalisableString GetTextBoxPlaceholder(bool isLoggedIn) => + protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => isLoggedIn ? CommentsStrings.PlaceholderNew : AuthorizationStrings.RequireLogin; protected override void OnCommit(string text) diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index 52e301f0a3..0d210021b9 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -26,7 +26,7 @@ namespace osu.Game.Overlays.Comments protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => isLoggedIn ? CommonStrings.ButtonsReply : CommentsStrings.GuestButtonReply; - protected override LocalisableString GetTextBoxPlaceholder(bool isLoggedIn) => + protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => isLoggedIn ? CommentsStrings.PlaceholderReply : AuthorizationStrings.RequireLogin; public ReplyCommentEditor(Comment parent) From 343052410b1eb83be437e1ed0d49343b474b1c37 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Mon, 19 Jun 2023 22:08:45 -0400 Subject: [PATCH 1299/1400] update CommentEditor test components --- .../Visual/UserInterface/TestSceneCommentEditor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index e7840d4a2a..0bc6367d64 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -125,8 +125,8 @@ namespace osu.Game.Tests.Visual.UserInterface } protected override LocalisableString FooterText => @"Footer text. And it is pretty long. Cool."; - protected override LocalisableString CommitButtonText => @"Commit"; - protected override LocalisableString TextBoxPlaceholder => @"This text box is empty"; + protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => @"Commit"; + protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @"This text box is empty"; } private partial class TestCancellableCommentEditor : CancellableCommentEditor @@ -146,8 +146,8 @@ namespace osu.Game.Tests.Visual.UserInterface { } - protected override LocalisableString CommitButtonText => @"Save"; - protected override LocalisableString TextBoxPlaceholder => @"Multiline textboxes soon"; + protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => @"Save"; + protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @"Multiline textboxes soon"; } } } From 1e0e29847f3404d5f90d52bc467b6d0cf7a55fd9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 16:29:15 +0900 Subject: [PATCH 1300/1400] Apply NRT and hotkey support to save replay button at results screen --- .../Screens/Ranking/ReplayDownloadButton.cs | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index 5c5cb61b79..5a1e59403a 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -1,30 +1,31 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Input.Bindings; using osu.Game.Online; using osu.Game.Scoring; using osuTK; namespace osu.Game.Screens.Ranking { - public partial class ReplayDownloadButton : CompositeDrawable + public partial class ReplayDownloadButton : CompositeDrawable, IKeyBindingHandler { public readonly Bindable Score = new Bindable(); protected readonly Bindable State = new Bindable(); - private DownloadButton button; - private ShakeContainer shakeContainer; + private DownloadButton button = null!; + private ShakeContainer shakeContainer = null!; - private ScoreDownloadTracker downloadTracker; + private ScoreDownloadTracker? downloadTracker; private ReplayAvailability replayAvailability { @@ -46,8 +47,8 @@ namespace osu.Game.Screens.Ranking Size = new Vector2(50, 30); } - [BackgroundDependencyLoader(true)] - private void load(OsuGame game, ScoreModelDownloader scores) + [BackgroundDependencyLoader] + private void load(OsuGame? game, ScoreModelDownloader scores) { InternalChild = shakeContainer = new ShakeContainer { @@ -99,6 +100,22 @@ namespace osu.Game.Screens.Ranking }, true); } + public bool OnPressed(KeyBindingPressEvent e) + { + switch (e.Action) + { + case GlobalAction.SaveReplay: + button.TriggerClick(); + return true; + } + + return false; + } + + public void OnReleased(KeyBindingReleaseEvent e) + { + } + private void updateState() { switch (replayAvailability) From 7c5813c05af98212a4e6e4eb85ce9ea27dcf5a91 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 16:34:22 +0900 Subject: [PATCH 1301/1400] Fix `OsuAnimatedButton` not flashing when triggered via code --- osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 5ef590d253..69e8df0286 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -111,6 +111,10 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(ClickEvent e) { + // Handle case where a click is triggered via TriggerClick(). + if (!IsHovered) + hover.FadeOutFromOne(1600); + hover.FlashColour(FlashColour, 800, Easing.OutQuint); return base.OnClick(e); } From 4bd121d3b8eaf17b6df6bc9a8f19bb3c2ba11dfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 16:38:30 +0900 Subject: [PATCH 1302/1400] Also add hotkey to export replays --- .../Input/Bindings/GlobalActionContainer.cs | 6 ++++- .../GlobalActionKeyBindingStrings.cs | 5 ++++ .../Screens/Play/SaveFailedScoreButton.cs | 17 +++++++++++++- .../Screens/Ranking/ReplayDownloadButton.cs | 23 +++++++++++++++++-- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 0ae29ebc8e..64268c73d0 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -119,7 +119,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.MouseMiddle, GlobalAction.PauseGameplay), new KeyBinding(InputKey.Control, GlobalAction.HoldForHUD), new KeyBinding(InputKey.Tab, GlobalAction.ToggleChatFocus), - new KeyBinding(InputKey.F2, GlobalAction.SaveReplay), + new KeyBinding(InputKey.F1, GlobalAction.SaveReplay), + new KeyBinding(InputKey.F2, GlobalAction.ExportReplay), }; public IEnumerable ReplayKeyBindings => new[] @@ -370,5 +371,8 @@ namespace osu.Game.Input.Bindings [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.SaveReplay))] SaveReplay, + + [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.ExportReplay))] + ExportReplay, } } diff --git a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs index 708fdaa174..9e53b23180 100644 --- a/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs +++ b/osu.Game/Localisation/GlobalActionKeyBindingStrings.cs @@ -329,6 +329,11 @@ namespace osu.Game.Localisation /// public static LocalisableString SaveReplay => new TranslatableString(getKey(@"save_replay"), @"Save replay"); + /// + /// "Export replay" + /// + public static LocalisableString ExportReplay => new TranslatableString(getKey(@"export_replay"), @"Export replay"); + private static string getKey(string key) => $@"{prefix}:{key}"; } } diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index c5bb265dcb..dc0ac054cb 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -21,6 +21,12 @@ namespace osu.Game.Screens.Play { public partial class SaveFailedScoreButton : CompositeDrawable, IKeyBindingHandler { + [Resolved] + private RealmAccess realm { get; set; } = null!; + + [Resolved] + private ScoreManager scoreManager { get; set; } = null!; + private readonly Bindable state = new Bindable(); private readonly Func> importFailedScore; @@ -37,7 +43,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(OsuGame? game, Player? player, RealmAccess realm) + private void load(OsuGame? game, Player? player) { InternalChild = button = new DownloadButton { @@ -98,6 +104,15 @@ namespace osu.Game.Screens.Play case GlobalAction.SaveReplay: button.TriggerClick(); return true; + + case GlobalAction.ExportReplay: + Task.Run(importFailedScore).ContinueWith(t => + { + importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); + Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); + scoreManager.Export(importedScore); + }); + return true; } return false; diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index 5a1e59403a..0772f54860 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -27,6 +27,9 @@ namespace osu.Game.Screens.Ranking private ScoreDownloadTracker? downloadTracker; + [Resolved] + private ScoreManager scoreManager { get; set; } = null!; + private ReplayAvailability replayAvailability { get @@ -48,7 +51,7 @@ namespace osu.Game.Screens.Ranking } [BackgroundDependencyLoader] - private void load(OsuGame? game, ScoreModelDownloader scores) + private void load(OsuGame? game, ScoreModelDownloader scoreDownloader) { InternalChild = shakeContainer = new ShakeContainer { @@ -68,7 +71,7 @@ namespace osu.Game.Screens.Ranking break; case DownloadState.NotDownloaded: - scores.Download(Score.Value); + scoreDownloader.Download(Score.Value); break; case DownloadState.Importing: @@ -107,6 +110,22 @@ namespace osu.Game.Screens.Ranking case GlobalAction.SaveReplay: button.TriggerClick(); return true; + + case GlobalAction.ExportReplay: + if (State.Value == DownloadState.NotDownloaded) + { + button.TriggerClick(); + } + + State.ValueChanged += importAfterDownload; + + void importAfterDownload(ValueChangedEvent valueChangedEvent) + { + scoreManager.Export(Score.Value); + State.ValueChanged -= importAfterDownload; + } + + return true; } return false; From 7b69b92eab65b1692bd17b8a0796a796bdcf7cb4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 16:56:41 +0900 Subject: [PATCH 1303/1400] Allow notifications while the game is paused (or in break time) RFC. This is to allow notifications to show at the pause screen (specifically for #23967, where exports are now happening). Not sure about the break time part of this, but might be fine? The toasts are immediately flushed before break time ends. --- osu.Game/Overlays/NotificationOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 15e6c94b34..beebc9daaf 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -118,7 +118,7 @@ namespace osu.Game.Overlays private void updateProcessingMode() { - bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State.Value == Visibility.Visible; + bool enabled = OverlayActivationMode.Value != OverlayActivation.Disabled || State.Value == Visibility.Visible; notificationsEnabler?.Cancel(); From ff8350bac6977f701dca04c31a8f5888137609a4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 17:43:52 +0900 Subject: [PATCH 1304/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 522d28dca7..66f518f3d5 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d94c4a2df9..9cb20ee364 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 96396ca4ad..256d1e43c4 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From dc1b4a39aa1fd160a1877ce42da87c5604a0d8e1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 18:23:59 +0900 Subject: [PATCH 1305/1400] Fix presenting beatmaps while in a multiplayer room not working --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index a36c7e801e..c02237bdde 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -49,6 +49,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } + [Resolved] + private OsuGame game { get; set; } + private AddItemButton addItemButton; public MultiplayerMatchSubScreen(Room room) @@ -403,18 +406,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!this.IsCurrentScreen()) return; - if (client.Room == null) - return; + // If there's only one playlist item and we are the host, assume we want to change it. Else we're add a new one. + PlaylistItem itemToEdit = client.IsHost && Room.Playlist.Count == 1 ? Room.Playlist.Single() : null; - if (!client.IsHost) - { - // todo: should handle this when the request queue is implemented. - // if we decide that the presentation should exit the user from the multiplayer game, the PresentBeatmap - // flow may need to change to support an "unable to present" return value. - return; - } + OpenSongSelection(itemToEdit); - this.Push(new MultiplayerMatchSongSelect(Room, Room.Playlist.Single(item => item.ID == client.Room.Settings.PlaylistItemId))); + // Re-run PresentBeatmap now that we've pushed a song select that can handle it. + game?.PresentBeatmap(beatmap.BeatmapSetInfo, b => b.ID == beatmap.BeatmapInfo.ID); } protected override void Dispose(bool isDisposing) From 10ed3787a00ac6d277e9032a2566da060a801e15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 18:27:19 +0900 Subject: [PATCH 1306/1400] Don't show song select screen when local user doesn't have permission to add an item --- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index c02237bdde..5fc7099544 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -337,11 +337,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer updateCurrentItem(); - addItemButton.Alpha = client.IsHost || Room.QueueMode.Value != QueueMode.HostOnly ? 1 : 0; + addItemButton.Alpha = localUserCanAddItem ? 1 : 0; Scheduler.AddOnce(UpdateMods); } + private bool localUserCanAddItem => client.IsHost || Room.QueueMode.Value != QueueMode.HostOnly; + private void updateCurrentItem() { Debug.Assert(client.Room != null); @@ -406,6 +408,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!this.IsCurrentScreen()) return; + if (!localUserCanAddItem) + return; + // If there's only one playlist item and we are the host, assume we want to change it. Else we're add a new one. PlaylistItem itemToEdit = client.IsHost && Room.Playlist.Count == 1 ? Room.Playlist.Single() : null; From 2e02b4a85b628588bdc8af93d92095ddfabbd3fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 18:35:51 +0900 Subject: [PATCH 1307/1400] Apply more correct fix for double-playing menu track --- osu.Game/Overlays/MusicController.cs | 10 ++++------ osu.Game/Screens/Select/SongSelect.cs | 3 --- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 1ad5a8c08b..0d175a624c 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -316,6 +316,8 @@ namespace osu.Game.Overlays var queuedTrack = getQueuedTrack(); var lastTrack = CurrentTrack; + lastTrack.Completed -= onTrackCompleted; + CurrentTrack = queuedTrack; // At this point we may potentially be in an async context from tests. This is extremely dangerous but we have to make do for now. @@ -344,16 +346,12 @@ namespace osu.Game.Overlays // Important to keep this in its own method to avoid inadvertently capturing unnecessary variables in the callback. // Can lead to leaks. var queuedTrack = new DrawableTrack(current.LoadTrack()); - queuedTrack.Completed += () => onTrackCompleted(current); + queuedTrack.Completed += onTrackCompleted; return queuedTrack; } - private void onTrackCompleted(WorkingBeatmap workingBeatmap) + private void onTrackCompleted() { - // the source of track completion is the audio thread, so the beatmap may have changed before firing. - if (current != workingBeatmap) - return; - if (!CurrentTrack.Looping && !beatmap.Disabled) NextTrack(); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index c232b7f490..47e5325baf 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -813,9 +813,6 @@ namespace osu.Game.Screens.Select if (!ControlGlobalMusic) return; - if (Beatmap.Value is DummyWorkingBeatmap) - return; - ITrack track = music.CurrentTrack; bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track; From d7b486e2ac306a82e59a8958623c59b6aaed1384 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 19:18:17 +0900 Subject: [PATCH 1308/1400] Disable beatmap skinning when entering the skin editor --- .../Overlays/SkinEditor/SkinEditorOverlay.cs | 58 ++++++++++++++++--- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 1c0ece28fe..b120faa45f 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -3,16 +3,19 @@ using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; +using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using osu.Game.Screens; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Overlays.SkinEditor @@ -45,6 +48,12 @@ namespace osu.Game.Overlays.SkinEditor RelativeSizeAxes = Axes.Both; } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + } + public bool OnPressed(KeyBindingPressEvent e) { switch (e.Action) @@ -147,17 +156,24 @@ namespace osu.Game.Overlays.SkinEditor /// public void SetTarget(OsuScreen screen) { - lastTargetScreen = screen; + try + { + lastTargetScreen = screen; - if (skinEditor == null) return; + if (skinEditor == null) return; - skinEditor.Save(userTriggered: false); + skinEditor.Save(userTriggered: false); - // ensure the toolbar is re-hidden even if a new screen decides to try and show it. - updateComponentVisibility(); + // ensure the toolbar is re-hidden even if a new screen decides to try and show it. + updateComponentVisibility(); - // AddOnce with parameter will ensure the newest target is loaded if there is any overlap. - Scheduler.AddOnce(setTarget, screen); + // AddOnce with parameter will ensure the newest target is loaded if there is any overlap. + Scheduler.AddOnce(setTarget, screen); + } + finally + { + globallyReenableBeatmapSkinSetting(); + } } private void setTarget(OsuScreen? target) @@ -173,6 +189,9 @@ namespace osu.Game.Overlays.SkinEditor return; } + if (target is Player) + globallyDisableBeatmapSkinSetting(); + if (skinEditor.State.Value == Visibility.Visible) skinEditor.UpdateTargetScreen(target); else @@ -182,5 +201,30 @@ namespace osu.Game.Overlays.SkinEditor skinEditor = null; } } + + private readonly Bindable beatmapSkins = new Bindable(); + private bool beatmapSkinsOriginalState; + + private void globallyDisableBeatmapSkinSetting() + { + if (beatmapSkins.Disabled) + return; + + // The skin editor doesn't work well if beatmap skins are being applied to the player screen. + // To keep things simple, disable the setting game-wide while using the skin editor. + beatmapSkinsOriginalState = beatmapSkins.Value; + + beatmapSkins.Value = false; + beatmapSkins.Disabled = true; + } + + private void globallyReenableBeatmapSkinSetting() + { + if (!beatmapSkins.Disabled) + return; + + beatmapSkins.Disabled = false; + beatmapSkins.Value = beatmapSkinsOriginalState; + } } } From 555ce7684b9d57183a603f7469dc23bd36354d83 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 20:04:02 +0900 Subject: [PATCH 1309/1400] Adjust `GameplaySampleTriggerSource` to only switch samples when close enough to the next hit object Closes #23963. To simplify things, I've removed the optimisation of using `AliveObject`s because it would break the way this whole lookup works. --- .../UI/GameplaySampleTriggerSource.cs | 56 +++++++------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index fbb7a20a5d..909b633a72 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -7,7 +7,7 @@ using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; namespace osu.Game.Rulesets.UI @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.UI }; } - private HitObjectLifetimeEntry fallbackObject; + private HitObjectLifetimeEntry mostValidObject; /// /// Play the most appropriate hit sound for the current point in time. @@ -67,56 +67,38 @@ namespace osu.Game.Rulesets.UI protected HitObject GetMostValidObject() { - // The most optimal lookup case we have is when an object is alive. There are usually very few alive objects so there's no drawbacks in attempting this lookup each time. - var drawableHitObject = hitObjectContainer.AliveObjects.FirstOrDefault(h => h.Result?.HasResult != true); - - if (drawableHitObject != null) - { - // A hit object may have a more valid nested object. - drawableHitObject = getMostValidNestedDrawable(drawableHitObject); - - return drawableHitObject.HitObject; - } - - // In the case a next object isn't available in drawable form, we need to do a somewhat expensive traversal to get a valid sound to play. - // This lookup can be skipped if the last entry is still valid (in the future and not yet hit). - if (fallbackObject == null || fallbackObject.Result?.HasResult == true) + if (mostValidObject == null || isAlreadyHit(mostValidObject)) { // We need to use lifetime entries to find the next object (we can't just use `hitObjectContainer.Objects` due to pooling - it may even be empty). // If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager. - fallbackObject = hitObjectContainer.Entries - .Where(e => e.Result?.HasResult != true).MinBy(e => e.HitObject.StartTime); - - if (fallbackObject != null) - return getEarliestNestedObject(fallbackObject.HitObject); + var candidate = hitObjectContainer.Entries.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime); // In the case there are no non-judged objects, the last hit object should be used instead. - fallbackObject ??= hitObjectContainer.Entries.LastOrDefault(); + if (candidate == null) + mostValidObject = hitObjectContainer.Entries.LastOrDefault(); + else + { + if (isCloseEnoughToCurrentTime(candidate)) + mostValidObject = candidate; + else + mostValidObject ??= hitObjectContainer.Entries.FirstOrDefault(); + } } - if (fallbackObject == null) + if (mostValidObject == null) return null; - bool fallbackHasResult = fallbackObject.Result?.HasResult == true; - // If the fallback has been judged then we want the sample from the object itself. - if (fallbackHasResult) - return fallbackObject.HitObject; + if (isAlreadyHit(mostValidObject)) + return mostValidObject.HitObject; // Else we want the earliest (including nested). // In cases of nested objects, they will always have earlier sample data than their parent object. - return getEarliestNestedObject(fallbackObject.HitObject); + return getEarliestNestedObject(mostValidObject.HitObject); } - private DrawableHitObject getMostValidNestedDrawable(DrawableHitObject o) - { - var nestedWithoutResult = o.NestedHitObjects.FirstOrDefault(n => n.Result?.HasResult != true); - - if (nestedWithoutResult == null) - return o; - - return getMostValidNestedDrawable(nestedWithoutResult); - } + private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; + private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => Time.Current > h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 1.5; private HitObject getEarliestNestedObject(HitObject hitObject) { From 786d5a394b526db81e5e5435edc486d777a9787a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 20:30:07 +0900 Subject: [PATCH 1310/1400] Add back optimisation and increase time allowance slightly --- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index 909b633a72..bc410acd9a 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -71,17 +71,26 @@ namespace osu.Game.Rulesets.UI { // We need to use lifetime entries to find the next object (we can't just use `hitObjectContainer.Objects` due to pooling - it may even be empty). // If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager. - var candidate = hitObjectContainer.Entries.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime); + var candidate = + // Use alive entries first as an optimisation. + hitObjectContainer.AliveEntries.Select(tuple => tuple.Entry).Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime) + ?? hitObjectContainer.Entries.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime); // In the case there are no non-judged objects, the last hit object should be used instead. if (candidate == null) + { mostValidObject = hitObjectContainer.Entries.LastOrDefault(); + } else { if (isCloseEnoughToCurrentTime(candidate)) + { mostValidObject = candidate; + } else + { mostValidObject ??= hitObjectContainer.Entries.FirstOrDefault(); + } } } @@ -98,7 +107,7 @@ namespace osu.Game.Rulesets.UI } private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; - private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => Time.Current > h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 1.5; + private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => Time.Current >= h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 2; private HitObject getEarliestNestedObject(HitObject hitObject) { From 0e861026814443b4fff965674e2805b77e2f63d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 20:45:02 +0900 Subject: [PATCH 1311/1400] Fix nested lookups --- .../Rulesets/UI/GameplaySampleTriggerSource.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index bc410acd9a..8de686a0d6 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -3,6 +3,7 @@ #nullable disable +using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Audio; @@ -101,19 +102,23 @@ namespace osu.Game.Rulesets.UI if (isAlreadyHit(mostValidObject)) return mostValidObject.HitObject; - // Else we want the earliest (including nested). + // Else we want the earliest valid nested. // In cases of nested objects, they will always have earlier sample data than their parent object. - return getEarliestNestedObject(mostValidObject.HitObject); + return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > Time.Current) ?? mostValidObject.HitObject; } private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => Time.Current >= h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 2; - private HitObject getEarliestNestedObject(HitObject hitObject) + private IEnumerable getAllNested(HitObject hitObject) { - var nested = hitObject.NestedHitObjects.FirstOrDefault(); + foreach (var h in hitObject.NestedHitObjects) + { + yield return h; - return nested != null ? getEarliestNestedObject(nested) : hitObject; + foreach (var n in getAllNested(h)) + yield return n; + } } private SkinnableSound getNextSample() From 04dad6c6e8a60dad3e7bcceeb5a13e75c0ac0d61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 20:47:56 +0900 Subject: [PATCH 1312/1400] Use `IGameplayClock` to ensure our clock source is correct --- .../Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index e52ec6f8cc..ca4a608114 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.Gameplay { base.SetUpSteps(); - AddStep("Add trigger source", () => Player.HUDOverlay.Add(sampleTriggerSource = new TestGameplaySampleTriggerSource(Player.DrawableRuleset.Playfield.HitObjectContainer))); + AddStep("Add trigger source", () => Player.GameplayClockContainer.Add(sampleTriggerSource = new TestGameplaySampleTriggerSource(Player.DrawableRuleset.Playfield.HitObjectContainer))); } [Test] diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index 8de686a0d6..029cab65ab 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -5,10 +5,12 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play; using osu.Game.Skinning; namespace osu.Game.Rulesets.UI @@ -29,6 +31,9 @@ namespace osu.Game.Rulesets.UI private readonly Container hitSounds; + [Resolved] + private IGameplayClock gameplayClock { get; set; } + public GameplaySampleTriggerSource(HitObjectContainer hitObjectContainer) { this.hitObjectContainer = hitObjectContainer; @@ -104,11 +109,11 @@ namespace osu.Game.Rulesets.UI // Else we want the earliest valid nested. // In cases of nested objects, they will always have earlier sample data than their parent object. - return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > Time.Current) ?? mostValidObject.HitObject; + return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > gameplayClock.CurrentTime) ?? mostValidObject.HitObject; } private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; - private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => Time.Current >= h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 2; + private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => gameplayClock.CurrentTime >= h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 2; private IEnumerable getAllNested(HitObject hitObject) { From 92e89c7df7f3f5894bb0e22de59dec1d5ea1d2ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 21:02:34 +0900 Subject: [PATCH 1313/1400] Update test expectations --- .../TestSceneGameplaySampleTriggerSource.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index ca4a608114..ca76337568 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Storyboards; using osuTK; @@ -62,25 +63,30 @@ namespace osu.Game.Tests.Visual.Gameplay { new HitCircle { + HitWindows = new HitWindows(), StartTime = t += spacing, Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } }, new HitCircle { + HitWindows = new HitWindows(), StartTime = t += spacing, Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE) } }, new HitCircle { + HitWindows = new HitWindows(), StartTime = t += spacing, Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT) }, }, new HitCircle { + HitWindows = new HitWindows(), StartTime = t += spacing, }, new Slider { + HitWindows = new HitWindows(), StartTime = t += spacing, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 }), Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, HitSampleInfo.BANK_SOFT) }, @@ -131,7 +137,12 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("first object hit", () => getNextAliveObject()?.Entry?.Result?.HasResult == true); - checkValidObjectIndex(1); + // next object is too far away, so we still use the already hit object. + checkValidObjectIndex(0); + + // still too far away. + seekBeforeIndex(1, 400); + checkValidObjectIndex(0); // Still object 1 as it's not hit yet. seekBeforeIndex(1); @@ -168,9 +179,9 @@ namespace osu.Game.Tests.Visual.Gameplay checkValidObjectIndex(4); } - private void seekBeforeIndex(int index) + private void seekBeforeIndex(int index, double amount = 100) { - AddStep($"seek to just before object {index}", () => Player.GameplayClockContainer.Seek(beatmap.HitObjects[index].StartTime - 100)); + AddStep($"seek to {amount} ms before object {index}", () => Player.GameplayClockContainer.Seek(beatmap.HitObjects[index].StartTime - amount)); waitForCatchUp(); } From cb07f2399fc584069578e2791fb8ecf7f5fd5674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 20 Jun 2023 21:03:55 +0900 Subject: [PATCH 1314/1400] Apply NRT to `GameplaySampleTriggerSource` --- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index 029cab65ab..472f91ac27 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -31,8 +29,10 @@ namespace osu.Game.Rulesets.UI private readonly Container hitSounds; + private HitObjectLifetimeEntry? mostValidObject; + [Resolved] - private IGameplayClock gameplayClock { get; set; } + private IGameplayClock gameplayClock { get; set; } = null!; public GameplaySampleTriggerSource(HitObjectContainer hitObjectContainer) { @@ -45,14 +45,12 @@ namespace osu.Game.Rulesets.UI }; } - private HitObjectLifetimeEntry mostValidObject; - /// /// Play the most appropriate hit sound for the current point in time. /// public virtual void Play() { - var nextObject = GetMostValidObject(); + HitObject? nextObject = GetMostValidObject(); if (nextObject == null) return; @@ -71,7 +69,7 @@ namespace osu.Game.Rulesets.UI hitSound.Play(); }); - protected HitObject GetMostValidObject() + protected HitObject? GetMostValidObject() { if (mostValidObject == null || isAlreadyHit(mostValidObject)) { From 2f77675fe7f133bb60c26f9e8826f0ea534e2887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Jun 2023 21:57:32 +0200 Subject: [PATCH 1315/1400] Fix errors in tests due to mismatching NRT annotations --- .../TestSceneDrumSampleTriggerSource.cs | 2 +- .../Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index 287d90b406..23e85d1ae0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -331,7 +331,7 @@ namespace osu.Game.Rulesets.Taiko.Tests LastPlayedSamples = samples; } - public new HitObject GetMostValidObject() => base.GetMostValidObject(); + public new HitObject? GetMostValidObject() => base.GetMostValidObject(); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs index ca76337568..6701871e8d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplaySampleTriggerSource.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual.Gameplay { } - public new HitObject GetMostValidObject() => base.GetMostValidObject(); + public new HitObject? GetMostValidObject() => base.GetMostValidObject(); } } } From 29697d4999ab144c08a37bc26443f916fd66fd1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Jun 2023 22:00:02 +0200 Subject: [PATCH 1316/1400] Fix taiko test scene failing due to missing gameplay clock dependency `GameplayClock` is inscrutable. `TestManualClock` is lifted from another test scene because of `FramedBeatmapClock`'s intensely confusing tendency to not work if it is given a non-adjustable `ManuelClock` instead. --- .../TestSceneDrumSampleTriggerSource.cs | 141 ++++++++++++++---- 1 file changed, 112 insertions(+), 29 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index 23e85d1ae0..f45b4e23e4 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -6,7 +6,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -17,14 +16,13 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Play; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests { public partial class TestSceneDrumSampleTriggerSource : OsuTestScene { - private readonly ManualClock manualClock = new ManualClock(); - [Cached(typeof(IScrollingInfo))] private ScrollingTestContainer.TestScrollingInfo info = new ScrollingTestContainer.TestScrollingInfo { @@ -34,23 +32,25 @@ namespace osu.Game.Rulesets.Taiko.Tests private ScrollingHitObjectContainer hitObjectContainer = null!; private TestDrumSampleTriggerSource triggerSource = null!; + private readonly ManualClock manualClock = new TestManualClock(); + private GameplayClockContainer gameplayClock = null!; [SetUp] public void SetUp() => Schedule(() => { - hitObjectContainer = new ScrollingHitObjectContainer(); - manualClock.CurrentTime = 0; - - Child = new Container + gameplayClock = new GameplayClockContainer(manualClock) { - Clock = new FramedClock(manualClock), RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - hitObjectContainer, + hitObjectContainer = new ScrollingHitObjectContainer(), triggerSource = new TestDrumSampleTriggerSource(hitObjectContainer) } }; + gameplayClock.Reset(0); + + hitObjectContainer.Clock = gameplayClock; + Child = gameplayClock; }); [Test] @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek past hit", () => manualClock.CurrentTime = 200); + AddStep("seek past hit", () => gameplayClock.Seek(200)); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); @@ -103,12 +103,67 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); - AddStep("seek past hit", () => manualClock.CurrentTime = 200); + seekTo(200); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); } + [Test] + public void TestBetweenHits() + { + Hit first = null!, second = null!; + + AddStep("add hit with normal samples", () => + { + first = new Hit + { + StartTime = 100, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL) + } + }; + first.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableHit = new DrawableHit(first); + hitObjectContainer.Add(drawableHit); + }); + AddStep("add hit with soft samples", () => + { + second = new Hit + { + StartTime = 500, + Samples = new List + { + new HitSampleInfo(HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT), + new HitSampleInfo(HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT) + } + }; + second.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var drawableHit = new DrawableHit(second); + hitObjectContainer.Add(drawableHit); + }); + + AddAssert("most valid object is first hit", () => triggerSource.GetMostValidObject(), () => Is.EqualTo(first)); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_NORMAL); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_NORMAL); + + seekTo(120); + AddAssert("most valid object is first hit", () => triggerSource.GetMostValidObject(), () => Is.EqualTo(first)); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_NORMAL); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_NORMAL); + + seekTo(480); + AddAssert("most valid object is second hit", () => triggerSource.GetMostValidObject(), () => Is.EqualTo(second)); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); + + seekTo(700); + AddAssert("most valid object is second hit", () => triggerSource.GetMostValidObject(), () => Is.EqualTo(second)); + checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); + checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); + } + [Test] public void TestDrumStrongHit() { @@ -128,11 +183,11 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableHit); }); - AddAssert("most valid object is strong nested hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + AddAssert("most valid object is nested strong hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); - AddStep("seek past hit", () => manualClock.CurrentTime = 200); + seekTo(200); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); @@ -161,12 +216,12 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); + seekTo(600); AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + seekTo(1200); AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); @@ -195,12 +250,12 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); - AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); + seekTo(600); AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); - AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + seekTo(1200); AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, HitSampleInfo.BANK_SOFT); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, HitSampleInfo.BANK_SOFT); @@ -226,16 +281,16 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableDrumRoll); }); - AddAssert("most valid object is drum roll tick's nested strong hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); - AddStep("seek to middle of drum roll", () => manualClock.CurrentTime = 600); - AddAssert("most valid object is drum roll tick's nested strong hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + seekTo(600); + AddAssert("most valid object is drum roll tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); - AddStep("seek past drum roll", () => manualClock.CurrentTime = 1200); + seekTo(1200); AddAssert("most valid object is drum roll", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); @@ -260,16 +315,16 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableSwell); }); - AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek to middle of swell", () => manualClock.CurrentTime = 600); - AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + seekTo(600); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek past swell", () => manualClock.CurrentTime = 1200); + seekTo(1200); AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); @@ -294,16 +349,16 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableSwell); }); - AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); - AddStep("seek to middle of swell", () => manualClock.CurrentTime = 600); - AddAssert("most valid object is swell tick", () => triggerSource.GetMostValidObject(), Is.InstanceOf); + seekTo(600); + AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); - AddStep("seek past swell", () => manualClock.CurrentTime = 1200); + seekTo(1200); AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); @@ -316,6 +371,8 @@ namespace osu.Game.Rulesets.Taiko.Tests AddAssert($"last played sample has {expectedBank} bank", () => triggerSource.LastPlayedSamples!.OfType().Single().Bank, () => Is.EqualTo(expectedBank)); } + private void seekTo(double time) => AddStep($"seek to {time}", () => gameplayClock.Seek(time)); + private partial class TestDrumSampleTriggerSource : DrumSampleTriggerSource { public ISampleInfo[]? LastPlayedSamples { get; private set; } @@ -333,5 +390,31 @@ namespace osu.Game.Rulesets.Taiko.Tests public new HitObject? GetMostValidObject() => base.GetMostValidObject(); } + + private class TestManualClock : ManualClock, IAdjustableClock + { + public TestManualClock() + { + IsRunning = true; + } + + public void Start() => IsRunning = true; + + public void Stop() => IsRunning = false; + + public bool Seek(double position) + { + CurrentTime = position; + return true; + } + + public void Reset() + { + } + + public void ResetSpeedAdjustments() + { + } + } } } From a7172e74699265b34898083317c38632e94599b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Jun 2023 23:32:38 +0200 Subject: [PATCH 1317/1400] Fix one remaining seek --- .../TestSceneDrumSampleTriggerSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index f45b4e23e4..e8da7f6937 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Taiko.Tests checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); - AddStep("seek past hit", () => gameplayClock.Seek(200)); + seekTo(200); AddAssert("most valid object is hit", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); From 8460873e61e5b74e60cf2f39b817862f57a0f322 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Wed, 21 Jun 2023 00:37:54 -0400 Subject: [PATCH 1318/1400] move commitButton.Text update to appropriate method --- osu.Game/Overlays/Comments/CommentEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index b363fe5881..4898d8b7c7 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -169,13 +169,13 @@ namespace osu.Game.Overlays.Comments { bool textBoxValid = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); commitButton.Enabled.Value = textBoxValid || !API.IsLoggedIn; + commitButton.Text = GetCommitButtonText(API.IsLoggedIn); } private void updateStateForLoggedIn() { TextBox.PlaceholderText = GetPlaceholderText(API.IsLoggedIn); TextBox.ReadOnly = !API.IsLoggedIn; - commitButton.Text = GetCommitButtonText(API.IsLoggedIn); updateCommitButtonState(); } From cc764afe3e6d9c6fd9385ecf13de3314b6dd698c Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Wed, 21 Jun 2023 00:58:43 -0400 Subject: [PATCH 1319/1400] use two separate buttons for posting / login --- osu.Game/Overlays/Comments/CommentEditor.cs | 46 ++++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 4898d8b7c7..8f7c8ced57 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Comments protected readonly Bindable Current = new Bindable(string.Empty); private RoundedButton commitButton = null!; + private RoundedButton logInButton = null!; private LoadingSpinner loadingSpinner = null!; protected TextBox TextBox { get; private set; } = null!; @@ -122,9 +123,19 @@ namespace osu.Game.Overlays.Comments AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(5, 0), - Child = commitButton = new EditorButton + Children = new Drawable[] { - Action = () => commitOrLogIn(Current.Value) + commitButton = new EditorButton + { + Action = () => OnCommit(Current.Value), + Text = GetCommitButtonText(true) + }, + logInButton = new EditorButton + { + Width = 100, + Action = () => loginOverlay?.Show(), + Text = GetCommitButtonText(false) + } } }, loadingSpinner = new LoadingSpinner @@ -154,29 +165,24 @@ namespace osu.Game.Overlays.Comments protected abstract void OnCommit(string text); - private void commitOrLogIn(string text) - { - if (!API.IsLoggedIn) - { - loginOverlay?.Show(); - return; - } - - OnCommit(text); - } - - private void updateCommitButtonState() - { - bool textBoxValid = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); - commitButton.Enabled.Value = textBoxValid || !API.IsLoggedIn; - commitButton.Text = GetCommitButtonText(API.IsLoggedIn); - } + private void updateCommitButtonState() => + commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); private void updateStateForLoggedIn() { TextBox.PlaceholderText = GetPlaceholderText(API.IsLoggedIn); TextBox.ReadOnly = !API.IsLoggedIn; - updateCommitButtonState(); + + if (API.IsLoggedIn) + { + commitButton.Show(); + logInButton.Hide(); + } + else + { + commitButton.Hide(); + logInButton.Show(); + } } private partial class EditorTextBox : OsuTextBox From dd4f271158b26a739ace7a37d0134a54c2f999bd Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Wed, 21 Jun 2023 02:15:02 -0400 Subject: [PATCH 1320/1400] fix cancel test for new button layout --- osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index 0bc6367d64..97eaa5b9ec 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("click cancel button", () => { - InputManager.MoveMouseTo(cancellableCommentEditor.ButtonsContainer[1]); + InputManager.MoveMouseTo(cancellableCommentEditor.ButtonsContainer[2]); InputManager.Click(MouseButton.Left); }); From 6de7328fef4353feb90679bff3dff93c7d2a2d72 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Wed, 21 Jun 2023 02:17:51 -0400 Subject: [PATCH 1321/1400] add test for comment when logging in and out --- .../UserInterface/TestSceneCommentEditor.cs | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index 97eaa5b9ec..1dafa2ab0a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; @@ -11,6 +11,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Comments; using osuTK; @@ -25,6 +26,7 @@ namespace osu.Game.Tests.Visual.UserInterface private TestCommentEditor commentEditor = null!; private TestCancellableCommentEditor cancellableCommentEditor = null!; + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; [SetUp] public void SetUp() => Schedule(() => @@ -96,6 +98,37 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("button is not loading", () => !commentEditor.IsSpinnerShown); } + [Test] + public void TestLoggingInAndOut() + { + void addLoggedInAsserts() + { + AddAssert("commit button visible", () => commentEditor.ButtonsContainer[0].Alpha == 1); + AddAssert("login button hidden", () => commentEditor.ButtonsContainer[1].Alpha == 0); + AddAssert("text box editable", () => !commentEditor.TextBox.ReadOnly); + } + + void addLoggedOutAsserts() + { + AddAssert("commit button hidden", () => commentEditor.ButtonsContainer[0].Alpha == 0); + AddAssert("login button visible", () => commentEditor.ButtonsContainer[1].Alpha == 1); + AddAssert("text box readonly", () => commentEditor.TextBox.ReadOnly); + } + + // there's also the case of starting logged out, but more annoying to test. + + // starting logged in + addLoggedInAsserts(); + + // moving from logged in -> logged out + AddStep("log out", () => dummyAPI.Logout()); + addLoggedOutAsserts(); + + // moving from logged out -> logged in + AddStep("log back in", () => dummyAPI.Login("username", "password")); + addLoggedInAsserts(); + } + [Test] public void TestCancelAction() { @@ -112,6 +145,7 @@ namespace osu.Game.Tests.Visual.UserInterface { public new Bindable Current => base.Current; public new FillFlowContainer ButtonsContainer => base.ButtonsContainer; + public new TextBox TextBox => base.TextBox; public string CommittedText { get; private set; } = string.Empty; @@ -125,8 +159,12 @@ namespace osu.Game.Tests.Visual.UserInterface } protected override LocalisableString FooterText => @"Footer text. And it is pretty long. Cool."; - protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => @"Commit"; - protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @"This text box is empty"; + + protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + isLoggedIn ? @"Commit" : "You're logged out!"; + + protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => + isLoggedIn ? @"This text box is empty" : "Still empty, but now you can't type in it."; } private partial class TestCancellableCommentEditor : CancellableCommentEditor From 366dd96875f673f7da8c72ed27028143372715ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 16:09:54 +0900 Subject: [PATCH 1322/1400] Use bindable lease instead of reimplementing the same thing locally --- osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index b120faa45f..4f0028de64 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -203,7 +203,7 @@ namespace osu.Game.Overlays.SkinEditor } private readonly Bindable beatmapSkins = new Bindable(); - private bool beatmapSkinsOriginalState; + private LeasedBindable? leasedBeatmapSkins; private void globallyDisableBeatmapSkinSetting() { @@ -212,19 +212,14 @@ namespace osu.Game.Overlays.SkinEditor // The skin editor doesn't work well if beatmap skins are being applied to the player screen. // To keep things simple, disable the setting game-wide while using the skin editor. - beatmapSkinsOriginalState = beatmapSkins.Value; - - beatmapSkins.Value = false; - beatmapSkins.Disabled = true; + leasedBeatmapSkins = beatmapSkins.BeginLease(true); + leasedBeatmapSkins.Value = false; } private void globallyReenableBeatmapSkinSetting() { - if (!beatmapSkins.Disabled) - return; - - beatmapSkins.Disabled = false; - beatmapSkins.Value = beatmapSkinsOriginalState; + leasedBeatmapSkins?.Return(); + leasedBeatmapSkins = null; } } } From cb0f642ad786b6dba97b6cca042e9984000795dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 16:11:19 +0900 Subject: [PATCH 1323/1400] Change skin editor flow to always save on toggle This also moves the beatmap skin disable toggle to on toggle, in line with review feedback. I've decided to always apply the disable, not just on the `Player` screen. It should be assumed that if a user is in the skin editor they are never going to need access to this anyway. --- .../Overlays/SkinEditor/SkinEditorOverlay.cs | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 4f0028de64..2dd30ca633 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -71,6 +71,8 @@ namespace osu.Game.Overlays.SkinEditor protected override void PopIn() { + globallyDisableBeatmapSkinSetting(); + if (skinEditor != null) { skinEditor.Show(); @@ -96,7 +98,13 @@ namespace osu.Game.Overlays.SkinEditor }); } - protected override void PopOut() => skinEditor?.Hide(); + protected override void PopOut() + { + skinEditor?.Save(false); + skinEditor?.Hide(); + + globallyReenableBeatmapSkinSetting(); + } protected override void Update() { @@ -156,24 +164,15 @@ namespace osu.Game.Overlays.SkinEditor /// public void SetTarget(OsuScreen screen) { - try - { - lastTargetScreen = screen; + lastTargetScreen = screen; - if (skinEditor == null) return; + if (skinEditor == null) return; - skinEditor.Save(userTriggered: false); + // ensure the toolbar is re-hidden even if a new screen decides to try and show it. + updateComponentVisibility(); - // ensure the toolbar is re-hidden even if a new screen decides to try and show it. - updateComponentVisibility(); - - // AddOnce with parameter will ensure the newest target is loaded if there is any overlap. - Scheduler.AddOnce(setTarget, screen); - } - finally - { - globallyReenableBeatmapSkinSetting(); - } + // AddOnce with parameter will ensure the newest target is loaded if there is any overlap. + Scheduler.AddOnce(setTarget, screen); } private void setTarget(OsuScreen? target) @@ -189,9 +188,6 @@ namespace osu.Game.Overlays.SkinEditor return; } - if (target is Player) - globallyDisableBeatmapSkinSetting(); - if (skinEditor.State.Value == Visibility.Visible) skinEditor.UpdateTargetScreen(target); else From 4ff52752082f93906df68ef0d8cb1a1048d44f92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 17:33:42 +0900 Subject: [PATCH 1324/1400] Make `IGameplayClock` optional in `GameplaySampleTriggerSource` to ease testing --- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index 472f91ac27..b67e977822 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI private HitObjectLifetimeEntry? mostValidObject; [Resolved] - private IGameplayClock gameplayClock { get; set; } = null!; + private IGameplayClock? gameplayClock { get; set; } public GameplaySampleTriggerSource(HitObjectContainer hitObjectContainer) { @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.UI } else { - if (isCloseEnoughToCurrentTime(candidate)) + if (isCloseEnoughToCurrentTime(candidate.HitObject)) { mostValidObject = candidate; } @@ -107,11 +107,13 @@ namespace osu.Game.Rulesets.UI // Else we want the earliest valid nested. // In cases of nested objects, they will always have earlier sample data than their parent object. - return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > gameplayClock.CurrentTime) ?? mostValidObject.HitObject; + return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > getReferenceTime()) ?? mostValidObject.HitObject; } private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; - private bool isCloseEnoughToCurrentTime(HitObjectLifetimeEntry h) => gameplayClock.CurrentTime >= h.HitObject.StartTime - h.HitObject.HitWindows.WindowFor(HitResult.Miss) * 2; + private bool isCloseEnoughToCurrentTime(HitObject h) => getReferenceTime() >= h.StartTime - h.HitWindows.WindowFor(HitResult.Miss) * 2; + + private double getReferenceTime() => (gameplayClock?.CurrentTime ?? Clock.CurrentTime); private IEnumerable getAllNested(HitObject hitObject) { From 9ca772421d470c8a2a86448413fc15f2c38b2fd2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 17:48:12 +0900 Subject: [PATCH 1325/1400] Improve and combine logic that exists in two classes --- .../Screens/Play/SaveFailedScoreButton.cs | 25 +++++++++++++---- .../Screens/Ranking/ReplayDownloadButton.cs | 28 +++++++++++-------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index dc0ac054cb..dd3b2d676d 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -97,6 +97,8 @@ namespace osu.Game.Screens.Play }, true); } + #region Export via hotkey logic (also in ReplayDownloadButton) + public bool OnPressed(KeyBindingPressEvent e) { switch (e.Action) @@ -106,12 +108,12 @@ namespace osu.Game.Screens.Play return true; case GlobalAction.ExportReplay: - Task.Run(importFailedScore).ContinueWith(t => - { - importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); - Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); - scoreManager.Export(importedScore); - }); + state.BindValueChanged(exportWhenReady, true); + + // start the import via button + if (state.Value != DownloadState.LocallyAvailable) + button.TriggerClick(); + return true; } @@ -121,5 +123,16 @@ namespace osu.Game.Screens.Play public void OnReleased(KeyBindingReleaseEvent e) { } + + private void exportWhenReady(ValueChangedEvent state) + { + if (state.NewValue != DownloadState.LocallyAvailable) return; + + scoreManager.Export(importedScore); + + this.state.ValueChanged -= exportWhenReady; + } + + #endregion } } diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index 0772f54860..799041b7de 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -103,6 +103,8 @@ namespace osu.Game.Screens.Ranking }, true); } + #region Export via hotkey logic (also in SaveFailedScoreButton) + public bool OnPressed(KeyBindingPressEvent e) { switch (e.Action) @@ -112,18 +114,11 @@ namespace osu.Game.Screens.Ranking return true; case GlobalAction.ExportReplay: - if (State.Value == DownloadState.NotDownloaded) - { + State.BindValueChanged(exportWhenReady, true); + + // start the import via button + if (State.Value != DownloadState.LocallyAvailable) button.TriggerClick(); - } - - State.ValueChanged += importAfterDownload; - - void importAfterDownload(ValueChangedEvent valueChangedEvent) - { - scoreManager.Export(Score.Value); - State.ValueChanged -= importAfterDownload; - } return true; } @@ -135,6 +130,17 @@ namespace osu.Game.Screens.Ranking { } + private void exportWhenReady(ValueChangedEvent state) + { + if (state.NewValue != DownloadState.LocallyAvailable) return; + + scoreManager.Export(Score.Value); + + State.ValueChanged -= exportWhenReady; + } + + #endregion + private void updateState() { switch (replayAvailability) From 1907beb0c9b4c48b32da711c7f762895813f5704 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 17:48:55 +0900 Subject: [PATCH 1326/1400] Add `FireAndForget` to stray `Task.Run` --- osu.Game/Screens/Play/SaveFailedScoreButton.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SaveFailedScoreButton.cs b/osu.Game/Screens/Play/SaveFailedScoreButton.cs index dd3b2d676d..0a2696339c 100644 --- a/osu.Game/Screens/Play/SaveFailedScoreButton.cs +++ b/osu.Game/Screens/Play/SaveFailedScoreButton.cs @@ -15,6 +15,7 @@ using osu.Game.Scoring; using osu.Game.Graphics.UserInterface; using osu.Game.Input.Bindings; using osu.Game.Online; +using osu.Game.Online.Multiplayer; using osuTK; namespace osu.Game.Screens.Play @@ -63,7 +64,7 @@ namespace osu.Game.Screens.Play { importedScore = realm.Run(r => r.Find(t.GetResultSafely().ID)?.Detach()); Schedule(() => state.Value = importedScore != null ? DownloadState.LocallyAvailable : DownloadState.NotDownloaded); - }); + }).FireAndForget(); break; } } From 655491ae2d4532de479538d696229bb9095c82f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 17:50:06 +0900 Subject: [PATCH 1327/1400] Fix potential null ref in `ResultsScreen` --- osu.Game/Screens/Ranking/ResultsScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Ranking/ResultsScreen.cs b/osu.Game/Screens/Ranking/ResultsScreen.cs index 78239e0dbe..b9f3b65129 100644 --- a/osu.Game/Screens/Ranking/ResultsScreen.cs +++ b/osu.Game/Screens/Ranking/ResultsScreen.cs @@ -160,7 +160,7 @@ namespace osu.Game.Screens.Ranking if (allowWatchingReplay) { - buttons.Add(new ReplayDownloadButton(null) + buttons.Add(new ReplayDownloadButton(SelectedScore.Value) { Score = { BindTarget = SelectedScore }, Width = 300 From c3f772f0da35dd16589c993835a5e1da1824d53d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 18:29:34 +0900 Subject: [PATCH 1328/1400] Add method to queue a restart after app is exited (when supported) --- osu.Desktop/OsuGameDesktop.cs | 20 +++++++++++++++++++ .../Screens/Setup/TournamentSwitcher.cs | 6 +++++- osu.Game/OsuGameBase.cs | 6 ++++++ .../Sections/Graphics/RendererSettings.cs | 13 +++++++++--- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 21cea3ba76..efd3d358b7 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -17,6 +17,7 @@ using osu.Game.Updater; using osu.Desktop.Windows; using osu.Game.IO; using osu.Game.IPC; +using osu.Game.Online.Multiplayer; using osu.Game.Utils; using SDL2; @@ -108,6 +109,25 @@ namespace osu.Desktop } } + public override bool RestartAppWhenExited() + { + switch (RuntimeInfo.OS) + { + case RuntimeInfo.Platform.Windows: + Debug.Assert(OperatingSystem.IsWindows()); + + // Of note, this is an async method in squirrel that adds an arbitrary delay before returning + // likely to ensure the external process is in a good state. + // + // We're not waiting on that here, but the outro playing before the actual exit should be enough + // to cover this. + Squirrel.UpdateManager.RestartAppWhenExited().FireAndForget(); + return true; + } + + return base.RestartAppWhenExited(); + } + protected override void LoadComplete() { base.LoadComplete(); diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs index 7a8b03a7aa..01d86274d7 100644 --- a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -28,7 +28,11 @@ namespace osu.Game.Tournament.Screens.Setup dropdown.Items = storage.ListTournaments(); dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true); - Action = () => game.AttemptExit(); + Action = () => + { + game.RestartAppWhenExited(); + game.AttemptExit(); + }; folderButton.Action = () => storage.PresentExternally(); ButtonText = "Close osu!"; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 63efe0e2c8..6737caa5f9 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -515,6 +515,12 @@ namespace osu.Game Scheduler.AddDelayed(AttemptExit, 2000); } + /// + /// If supported by the platform, the game will automatically restart after the next exit. + /// + /// Whether a restart operation was queued. + public virtual bool RestartAppWhenExited() => false; + public bool Migrate(string path) { Logger.Log($@"Migrating osu! data from ""{Storage.GetFullPath(string.Empty)}"" to ""{path}""..."); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index a1f728ca87..d4cef3f4d1 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -67,10 +67,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics if (r.NewValue == RendererType.Automatic && automaticRendererInUse) return; - dialogOverlay?.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, () => game?.AttemptExit(), () => + if (game?.RestartAppWhenExited() == true) { - renderer.Value = automaticRendererInUse ? RendererType.Automatic : host.ResolvedRenderer; - })); + game.AttemptExit(); + } + else + { + dialogOverlay?.Push(new ConfirmDialog(GraphicsSettingsStrings.ChangeRendererConfirmation, () => game?.AttemptExit(), () => + { + renderer.Value = automaticRendererInUse ? RendererType.Automatic : host.ResolvedRenderer; + })); + } }); // TODO: remove this once we support SDL+android. From 59b1f08d530fa1fa254a102ac678d0f34830da6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 18:27:29 +0900 Subject: [PATCH 1329/1400] Don't require exit confirmation when there are no ongoing operations that could be interrupted --- osu.Game/OsuGame.cs | 16 +++++++++++++--- osu.Game/Overlays/NotificationOverlay.cs | 2 ++ osu.Game/Screens/Menu/MainMenu.cs | 2 ++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a80639d4ff..7bfe88f248 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -83,7 +83,7 @@ namespace osu.Game /// protected const float SIDE_OVERLAY_OFFSET_RATIO = 0.05f; - public Toolbar Toolbar; + public Toolbar Toolbar { get; private set; } private ChatOverlay chatOverlay; @@ -778,8 +778,18 @@ namespace osu.Game public override void AttemptExit() { - // Using PerformFromScreen gives the user a chance to interrupt the exit process if needed. - PerformFromScreen(menu => menu.Exit()); + bool requiresConfirmationToExit = Notifications.HasOngoingOperations; + + PerformFromScreen(menu => + { + var mainMenu = ((MainMenu)menu); + + // The main menu exit implementation gives the user a chance to interrupt the exit process if needed. + if (requiresConfirmationToExit) + mainMenu.Exit(); + else + mainMenu.ExitWithoutConfirmation(); + }, new[] { typeof(MainMenu) }); } /// diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 15e6c94b34..c53b6b667c 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -33,6 +33,8 @@ namespace osu.Game.Overlays public const float TRANSITION_LENGTH = 600; + public bool HasOngoingOperations => sections.Any(s => s.Children.OfType().Any()); + private FlowContainer sections = null!; [Resolved] diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 69b8596474..998e36c2be 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -154,6 +154,8 @@ namespace osu.Game.Screens.Menu public void ReturnToOsuLogo() => Buttons.State = ButtonSystemState.Initial; + public void ExitWithoutConfirmation() => confirmAndExit(); + private void confirmAndExit() { if (exitConfirmed) return; From 7b4cbea362e0d40fd7ca180f6f1146af655dcdb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Jun 2023 00:01:48 +0900 Subject: [PATCH 1330/1400] Allow nullable to fix test usages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 5fc7099544..1f9edfe97c 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer [Resolved] private MultiplayerClient client { get; set; } - [Resolved] + [Resolved(canBeNull: true)] private OsuGame game { get; set; } private AddItemButton addItemButton; From 07a00e8afd1aa50cffda6d980f8209d8b72a5973 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Jun 2023 00:02:02 +0900 Subject: [PATCH 1331/1400] Fix typo in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 1f9edfe97c..978d77b4f1 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -411,7 +411,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer if (!localUserCanAddItem) return; - // If there's only one playlist item and we are the host, assume we want to change it. Else we're add a new one. + // If there's only one playlist item and we are the host, assume we want to change it. Else add a new one. PlaylistItem itemToEdit = client.IsHost && Room.Playlist.Count == 1 ? Room.Playlist.Single() : null; OpenSongSelection(itemToEdit); From 4be8eede8834dc473f19629b2ba83c79d1f9003e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Jun 2023 18:46:42 +0900 Subject: [PATCH 1332/1400] Fix combo counter on legacy skins flipping when "Floating Fruits" mod is active Closes #23989. --- .../Skinning/Legacy/LegacyCatchComboCounter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs index eba837a52d..55b24b3ffa 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyCatchComboCounter.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Rulesets.Catch.UI; using osu.Game.Skinning; using osuTK; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy /// /// A combo counter implementation that visually behaves almost similar to stable's osu!catch combo counter. /// - public partial class LegacyCatchComboCounter : CompositeDrawable, ICatchComboCounter + public partial class LegacyCatchComboCounter : UprightAspectMaintainingContainer, ICatchComboCounter { private readonly LegacyRollingCounter counter; From 79606317ab671c93bc6c8d650f25240d1ed52cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Jun 2023 20:02:10 +0200 Subject: [PATCH 1333/1400] Remove redundant parentheses --- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index b67e977822..d8f421e54f 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.UI private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; private bool isCloseEnoughToCurrentTime(HitObject h) => getReferenceTime() >= h.StartTime - h.HitWindows.WindowFor(HitResult.Miss) * 2; - private double getReferenceTime() => (gameplayClock?.CurrentTime ?? Clock.CurrentTime); + private double getReferenceTime() => gameplayClock?.CurrentTime ?? Clock.CurrentTime; private IEnumerable getAllNested(HitObject hitObject) { From aea5eb37dca6e2ca7e5ad18e141d48fb49bc3b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Jun 2023 20:24:44 +0200 Subject: [PATCH 1334/1400] Remove unused using directive --- osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 2dd30ca633..68d6b7ced5 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -15,7 +15,6 @@ using osu.Game.Input.Bindings; using osu.Game.Screens; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Components; -using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Overlays.SkinEditor From 21bed336c681abf31577834ca2fb830ea6a61497 Mon Sep 17 00:00:00 2001 From: Liam DeVoe Date: Thu, 22 Jun 2023 16:01:12 -0400 Subject: [PATCH 1335/1400] adjust DummyAPIAccess to more closely match APIAccess wrt logging in and out --- osu.Game/Online/API/DummyAPIAccess.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 16afef8e30..896fa30ff8 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -34,7 +34,7 @@ namespace osu.Game.Online.API public string AccessToken => "token"; - public bool IsLoggedIn => State.Value == APIState.Online; + public bool IsLoggedIn => State.Value > APIState.Offline; public string ProvidedUsername => LocalUser.Value.Username; @@ -114,8 +114,8 @@ namespace osu.Game.Online.API public void Logout() { - LocalUser.Value = new GuestUser(); state.Value = APIState.Offline; + LocalUser.Value = new GuestUser(); } public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; From 786deec2964134b6a9ea5af897c0345e2159b090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Jun 2023 23:00:52 +0200 Subject: [PATCH 1336/1400] Rename and xmldoc members --- .../UserInterface/TestSceneCommentEditor.cs | 4 ++-- osu.Game/Overlays/Comments/CommentEditor.cs | 15 ++++++++++++--- osu.Game/Overlays/Comments/CommentsContainer.cs | 2 +- osu.Game/Overlays/Comments/ReplyCommentEditor.cs | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index 1dafa2ab0a..1c3c86442e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.UserInterface protected override LocalisableString FooterText => @"Footer text. And it is pretty long. Cool."; - protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + protected override LocalisableString GetButtonText(bool isLoggedIn) => isLoggedIn ? @"Commit" : "You're logged out!"; protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.UserInterface { } - protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => @"Save"; + protected override LocalisableString GetButtonText(bool isLoggedIn) => @"Save"; protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => @"Multiline textboxes soon"; } } diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 8f7c8ced57..8dbafc0ea8 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -44,8 +44,17 @@ namespace osu.Game.Overlays.Comments [Resolved] private LoginOverlay? loginOverlay { get; set; } - protected abstract LocalisableString GetCommitButtonText(bool isLoggedIn); + /// + /// Returns the text content of the main action button. + /// When is , the text will apply to a button that posts a comment. + /// When is , the text will apply to a button that directs the user to the login overlay. + /// + protected abstract LocalisableString GetButtonText(bool isLoggedIn); + /// + /// Returns the placeholder text for the comment box. + /// + /// Whether the current user is logged in. protected abstract LocalisableString GetPlaceholderText(bool isLoggedIn); protected bool ShowLoadingSpinner @@ -128,13 +137,13 @@ namespace osu.Game.Overlays.Comments commitButton = new EditorButton { Action = () => OnCommit(Current.Value), - Text = GetCommitButtonText(true) + Text = GetButtonText(true) }, logInButton = new EditorButton { Width = 100, Action = () => loginOverlay?.Show(), - Text = GetCommitButtonText(false) + Text = GetButtonText(false) } } }, diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index e6c69d2090..af5f4dd280 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -410,7 +410,7 @@ namespace osu.Game.Overlays.Comments //TODO should match web, left empty due to no multiline support protected override LocalisableString FooterText => default; - protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + protected override LocalisableString GetButtonText(bool isLoggedIn) => isLoggedIn ? CommonStrings.ButtonsPost : CommentsStrings.GuestButtonNew; protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => diff --git a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs index 0d210021b9..dd4c35ef20 100644 --- a/osu.Game/Overlays/Comments/ReplyCommentEditor.cs +++ b/osu.Game/Overlays/Comments/ReplyCommentEditor.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Comments protected override LocalisableString FooterText => default; - protected override LocalisableString GetCommitButtonText(bool isLoggedIn) => + protected override LocalisableString GetButtonText(bool isLoggedIn) => isLoggedIn ? CommonStrings.ButtonsReply : CommentsStrings.GuestButtonReply; protected override LocalisableString GetPlaceholderText(bool isLoggedIn) => From 1672608a87311bde31d35616389d5db9603aa17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Jun 2023 23:08:30 +0200 Subject: [PATCH 1337/1400] Document why things were done in `DummyAPIAccess` --- osu.Game/Online/API/DummyAPIAccess.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 896fa30ff8..bf9baa4414 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -34,6 +34,7 @@ namespace osu.Game.Online.API public string AccessToken => "token"; + /// public bool IsLoggedIn => State.Value > APIState.Offline; public string ProvidedUsername => LocalUser.Value.Username; @@ -115,6 +116,8 @@ namespace osu.Game.Online.API public void Logout() { state.Value = APIState.Offline; + // must happen after `state.Value` is changed such that subscribers to that bindable's value changes see the correct user. + // compare: `APIAccess.Logout()`. LocalUser.Value = new GuestUser(); } From 2c1c20e0a7b95b2b9805a1126d3ceb5157e3140f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Thu, 22 Jun 2023 23:10:16 +0200 Subject: [PATCH 1338/1400] Rename test helpers --- .../Visual/UserInterface/TestSceneCommentEditor.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs index 1c3c86442e..b17024ae8f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentEditor.cs @@ -101,14 +101,14 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestLoggingInAndOut() { - void addLoggedInAsserts() + void assertLoggedInState() { AddAssert("commit button visible", () => commentEditor.ButtonsContainer[0].Alpha == 1); AddAssert("login button hidden", () => commentEditor.ButtonsContainer[1].Alpha == 0); AddAssert("text box editable", () => !commentEditor.TextBox.ReadOnly); } - void addLoggedOutAsserts() + void assertLoggedOutState() { AddAssert("commit button hidden", () => commentEditor.ButtonsContainer[0].Alpha == 0); AddAssert("login button visible", () => commentEditor.ButtonsContainer[1].Alpha == 1); @@ -118,15 +118,15 @@ namespace osu.Game.Tests.Visual.UserInterface // there's also the case of starting logged out, but more annoying to test. // starting logged in - addLoggedInAsserts(); + assertLoggedInState(); // moving from logged in -> logged out AddStep("log out", () => dummyAPI.Logout()); - addLoggedOutAsserts(); + assertLoggedOutState(); // moving from logged out -> logged in AddStep("log back in", () => dummyAPI.Login("username", "password")); - addLoggedInAsserts(); + assertLoggedInState(); } [Test] From 64b726d5ecaaf1ef6c3b71bed4523990117300e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 13:48:13 +0900 Subject: [PATCH 1339/1400] Fix nested logic not being completely correct (favouring already-passed rather than near-future) --- osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs index d8f421e54f..c554318357 100644 --- a/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs +++ b/osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs @@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.UI // Else we want the earliest valid nested. // In cases of nested objects, they will always have earlier sample data than their parent object. - return getAllNested(mostValidObject.HitObject).OrderBy(h => h.StartTime).FirstOrDefault(h => h.StartTime > getReferenceTime()) ?? mostValidObject.HitObject; + return getAllNested(mostValidObject.HitObject).OrderBy(h => h.GetEndTime()).SkipWhile(h => h.GetEndTime() <= getReferenceTime()).FirstOrDefault() ?? mostValidObject.HitObject; } private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.Result?.HasResult == true; From d53996336cb81a217e06f998ebdc440c17cf1145 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:01:10 +0900 Subject: [PATCH 1340/1400] Add note about swells and their ticks --- .../TestSceneDrumSampleTriggerSource.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs index e8da7f6937..bce855ae45 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumSampleTriggerSource.cs @@ -315,6 +315,9 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableSwell); }); + // You might think that this should be a SwellTick since we're before the swell, but SwellTicks get no StartTime (ie. they are zero). + // This works fine in gameplay because they are judged whenever the user pressed, rather than being timed hits. + // But for sample playback purposes they can be ignored as noise. AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, SampleControlPoint.DEFAULT_BANK); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, SampleControlPoint.DEFAULT_BANK); @@ -349,6 +352,9 @@ namespace osu.Game.Rulesets.Taiko.Tests hitObjectContainer.Add(drawableSwell); }); + // You might think that this should be a SwellTick since we're before the swell, but SwellTicks get no StartTime (ie. they are zero). + // This works fine in gameplay because they are judged whenever the user pressed, rather than being timed hits. + // But for sample playback purposes they can be ignored as noise. AddAssert("most valid object is swell", () => triggerSource.GetMostValidObject(), Is.InstanceOf); checkSound(HitType.Centre, HitSampleInfo.HIT_NORMAL, "drum"); checkSound(HitType.Rim, HitSampleInfo.HIT_CLAP, "drum"); From ce1579f2fead9c2c84ff160dff5025ee41603998 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:05:02 +0900 Subject: [PATCH 1341/1400] Bind to `API.State` instead of `API.User` --- osu.Game/Overlays/Comments/CommentEditor.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 8dbafc0ea8..05bdac5966 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osuTK; using osuTK.Graphics; @@ -36,14 +35,14 @@ namespace osu.Game.Overlays.Comments protected TextBox TextBox { get; private set; } = null!; - protected readonly IBindable User = new Bindable(); - [Resolved] protected IAPIProvider API { get; private set; } = null!; [Resolved] private LoginOverlay? loginOverlay { get; set; } + private readonly IBindable apiState = new Bindable(); + /// /// Returns the text content of the main action button. /// When is , the text will apply to a button that posts a comment. @@ -162,14 +161,14 @@ namespace osu.Game.Overlays.Comments }); TextBox.OnCommit += (_, _) => commitButton.TriggerClick(); - User.BindTo(API.LocalUser); + apiState.BindTo(API.State); } protected override void LoadComplete() { base.LoadComplete(); Current.BindValueChanged(_ => updateCommitButtonState(), true); - User.BindValueChanged(_ => updateStateForLoggedIn(), true); + apiState.BindValueChanged(updateStateForLoggedIn, true); } protected abstract void OnCommit(string text); @@ -177,12 +176,14 @@ namespace osu.Game.Overlays.Comments private void updateCommitButtonState() => commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); - private void updateStateForLoggedIn() + private void updateStateForLoggedIn(ValueChangedEvent state) { - TextBox.PlaceholderText = GetPlaceholderText(API.IsLoggedIn); - TextBox.ReadOnly = !API.IsLoggedIn; + bool isAvailable = state.NewValue > APIState.Offline; - if (API.IsLoggedIn) + TextBox.PlaceholderText = GetPlaceholderText(isAvailable); + TextBox.ReadOnly = !isAvailable; + + if (isAvailable) { commitButton.Show(); logInButton.Hide(); From 343271751add838bdd6047e5a8c6cfba0bf0e5b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:07:33 +0900 Subject: [PATCH 1342/1400] Add `Schedule` to ensure correct thread for UI code --- osu.Game/Overlays/Comments/CommentEditor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentEditor.cs b/osu.Game/Overlays/Comments/CommentEditor.cs index 05bdac5966..02bcbb9d05 100644 --- a/osu.Game/Overlays/Comments/CommentEditor.cs +++ b/osu.Game/Overlays/Comments/CommentEditor.cs @@ -176,7 +176,7 @@ namespace osu.Game.Overlays.Comments private void updateCommitButtonState() => commitButton.Enabled.Value = loadingSpinner.State.Value == Visibility.Hidden && !string.IsNullOrEmpty(Current.Value); - private void updateStateForLoggedIn(ValueChangedEvent state) + private void updateStateForLoggedIn(ValueChangedEvent state) => Schedule(() => { bool isAvailable = state.NewValue > APIState.Offline; @@ -193,7 +193,7 @@ namespace osu.Game.Overlays.Comments commitButton.Hide(); logInButton.Show(); } - } + }); private partial class EditorTextBox : OsuTextBox { From 08b3c0cce0ba40f250fbc88b86076337b0462d92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:18:11 +0900 Subject: [PATCH 1343/1400] Change "floating fruits" mod to only apply adjustments to the playfield Avoids things like touch screen inputs also being flipped. Note that these adjustments can't be applied directly to the playfield due to how playfields are used in various rulesets (basically relying on the `PlayfieldAdjustContainer` to get things in the right place). Closes #24000. --- osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs | 6 +++--- osu.Game/Rulesets/UI/DrawableRuleset.cs | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs index e12181d051..dd6757eac9 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs @@ -21,10 +21,10 @@ namespace osu.Game.Rulesets.Catch.Mods public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.Anchor = Anchor.Centre; - drawableRuleset.Origin = Anchor.Centre; + drawableRuleset.PlayfieldAdjustmentContainer.Anchor = Anchor.Centre; + drawableRuleset.PlayfieldAdjustmentContainer.Origin = Anchor.Centre; - drawableRuleset.Scale = new Vector2(1, -1); + drawableRuleset.PlayfieldAdjustmentContainer.Scale = new Vector2(1, -1); } } } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 4f22c0c617..cecd6cb26c 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -71,6 +71,12 @@ namespace osu.Game.Rulesets.UI private readonly AudioContainer audioContainer = new AudioContainer { RelativeSizeAxes = Axes.Both }; + /// + /// A container which encapsulates the and provides any adjustments to + /// ensure correct scale and position. + /// + public virtual PlayfieldAdjustmentContainer PlayfieldAdjustmentContainer { get; private set; } + public override Container FrameStableComponents { get; } = new Container { RelativeSizeAxes = Axes.Both }; public override IFrameStableClock FrameStableClock => frameStabilityContainer; @@ -178,7 +184,7 @@ namespace osu.Game.Rulesets.UI audioContainer.WithChild(KeyBindingInputManager .WithChildren(new Drawable[] { - CreatePlayfieldAdjustmentContainer() + PlayfieldAdjustmentContainer = CreatePlayfieldAdjustmentContainer() .WithChild(Playfield), Overlays })), From 11a97e1bb88f39571333837385f442ceb21a7b47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Jun 2023 19:06:47 +0900 Subject: [PATCH 1344/1400] Move confirmation bypass implementation to `MainMenu` to allow for more correct logic --- .../Visual/Menus/TestSceneToolbar.cs | 2 + .../TestSceneFirstRunSetupOverlay.cs | 2 + osu.Game/OsuGame.cs | 14 +----- osu.Game/Overlays/INotificationOverlay.cs | 5 ++ osu.Game/Screens/Menu/MainMenu.cs | 47 ++++++++++++++----- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 22c7bb64b2..471700988c 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -250,6 +250,8 @@ namespace osu.Game.Tests.Visual.Menus } public virtual IBindable UnreadCount => null; + + public bool HasOngoingOperations => false; } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 77ed97e3ed..0b0c29acf6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -214,6 +214,8 @@ namespace osu.Game.Tests.Visual.UserInterface } public virtual IBindable UnreadCount => null; + + public bool HasOngoingOperations => false; } // interface mocks break hot reload, mocking this stub implementation instead works around it. diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7bfe88f248..160dc26790 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -778,18 +778,8 @@ namespace osu.Game public override void AttemptExit() { - bool requiresConfirmationToExit = Notifications.HasOngoingOperations; - - PerformFromScreen(menu => - { - var mainMenu = ((MainMenu)menu); - - // The main menu exit implementation gives the user a chance to interrupt the exit process if needed. - if (requiresConfirmationToExit) - mainMenu.Exit(); - else - mainMenu.ExitWithoutConfirmation(); - }, new[] { typeof(MainMenu) }); + // The main menu exit implementation gives the user a chance to interrupt the exit process if needed. + PerformFromScreen(menu => menu.Exit(), new[] { typeof(MainMenu) }); } /// diff --git a/osu.Game/Overlays/INotificationOverlay.cs b/osu.Game/Overlays/INotificationOverlay.cs index b9ac466229..0d8f73a1d7 100644 --- a/osu.Game/Overlays/INotificationOverlay.cs +++ b/osu.Game/Overlays/INotificationOverlay.cs @@ -30,5 +30,10 @@ namespace osu.Game.Overlays /// Current number of unread notifications. /// IBindable UnreadCount { get; } + + /// + /// Whether there are any ongoing operations, such as imports or downloads. + /// + bool HasOngoingOperations { get; } } } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 998e36c2be..5078751823 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -53,6 +53,9 @@ namespace osu.Game.Screens.Menu [Resolved] private GameHost host { get; set; } + [Resolved] + private INotificationOverlay notifications { get; set; } + [Resolved] private MusicController musicController { get; set; } @@ -74,6 +77,9 @@ namespace osu.Game.Screens.Menu private ExitConfirmOverlay exitConfirmOverlay; + private bool exitConfirmedViaDialog; + private bool exitConfirmedViaHoldOrClick; + private ParallaxContainer buttonsContainer; private SongTicker songTicker; @@ -89,10 +95,8 @@ namespace osu.Game.Screens.Menu { Action = () => { - if (holdDelay.Value > 0) - confirmAndExit(); - else - this.Exit(); + exitConfirmedViaHoldOrClick = holdDelay.Value > 0; + this.Exit(); } }); } @@ -114,7 +118,11 @@ namespace osu.Game.Screens.Menu OnSolo = loadSoloSongSelect, OnMultiplayer = () => this.Push(new Multiplayer()), OnPlaylists = () => this.Push(new Playlists()), - OnExit = confirmAndExit, + OnExit = () => + { + exitConfirmedViaHoldOrClick = true; + this.Exit(); + } } } }, @@ -154,13 +162,11 @@ namespace osu.Game.Screens.Menu public void ReturnToOsuLogo() => Buttons.State = ButtonSystemState.Initial; - public void ExitWithoutConfirmation() => confirmAndExit(); - private void confirmAndExit() { - if (exitConfirmed) return; + if (exitConfirmedViaDialog) return; - exitConfirmed = true; + exitConfirmedViaDialog = true; performer?.PerformFromScreen(menu => menu.Exit()); } @@ -203,8 +209,6 @@ namespace osu.Game.Screens.Menu dialogOverlay?.Push(new StorageErrorDialog(osuStorage, osuStorage.Error)); } - private bool exitConfirmed; - protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); @@ -281,12 +285,29 @@ namespace osu.Game.Screens.Menu public override bool OnExiting(ScreenExitEvent e) { - if (!exitConfirmed && dialogOverlay != null) + bool requiresConfirmation = + // we need to have a dialog overlay to confirm in the first place. + dialogOverlay != null + // if the dialog has already displayed and been accepted by the user, we are good. + && !exitConfirmedViaDialog + // Only require confirmation if there is either an ongoing operation or the user exited via a non-hold escape press. + && (notifications.HasOngoingOperations || !exitConfirmedViaHoldOrClick); + + if (requiresConfirmation) { if (dialogOverlay.CurrentDialog is ConfirmExitDialog exitDialog) exitDialog.PerformOkAction(); else - dialogOverlay.Push(new ConfirmExitDialog(confirmAndExit, () => exitConfirmOverlay.Abort())); + { + dialogOverlay.Push(new ConfirmExitDialog(() => + { + exitConfirmedViaDialog = true; + this.Exit(); + }, () => + { + exitConfirmOverlay.Abort(); + })); + } return true; } From 6df617d5366b3a8f15ecaa03c9ce52e1d97f71eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:46:38 +0900 Subject: [PATCH 1345/1400] Rename `ExitConfirmOverlay` to be more explicit about purpose --- .../Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs | 4 ++-- .../{ExitConfirmOverlay.cs => HoldToExitGameOverlay.cs} | 6 ++---- osu.Game/Screens/Menu/MainMenu.cs | 8 ++++---- 3 files changed, 8 insertions(+), 10 deletions(-) rename osu.Game/Screens/Menu/{ExitConfirmOverlay.cs => HoldToExitGameOverlay.cs} (86%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index 801bef62c8..9c29f17382 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.UserInterface Alpha = 0, }; - var overlay = new TestHoldToConfirmOverlay + var overlay = new TestHoldToExitGameOverlay { Action = () => { @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait until fired again", () => overlay.Fired); } - private partial class TestHoldToConfirmOverlay : ExitConfirmOverlay + private partial class TestHoldToExitGameOverlay : HoldToExitGameOverlay { public void Begin() => BeginConfirm(); } diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/HoldToExitGameOverlay.cs similarity index 86% rename from osu.Game/Screens/Menu/ExitConfirmOverlay.cs rename to osu.Game/Screens/Menu/HoldToExitGameOverlay.cs index bc2f6ea00f..a8f4913368 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/HoldToExitGameOverlay.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. -#nullable disable - using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; @@ -10,13 +8,13 @@ using osu.Game.Overlays; namespace osu.Game.Screens.Menu { - public partial class ExitConfirmOverlay : HoldToConfirmOverlay, IKeyBindingHandler + public partial class HoldToExitGameOverlay : HoldToConfirmOverlay, IKeyBindingHandler { protected override bool AllowMultipleFires => true; public void Abort() => AbortConfirm(); - public ExitConfirmOverlay() + public HoldToExitGameOverlay() : base(0.7f) { } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 5078751823..2946425998 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -75,7 +75,7 @@ namespace osu.Game.Screens.Menu private Bindable holdDelay; private Bindable loginDisplayed; - private ExitConfirmOverlay exitConfirmOverlay; + private HoldToExitGameOverlay holdToExitGameOverlay; private bool exitConfirmedViaDialog; private bool exitConfirmedViaHoldOrClick; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Menu if (host.CanExit) { - AddInternal(exitConfirmOverlay = new ExitConfirmOverlay + AddInternal(holdToExitGameOverlay = new HoldToExitGameOverlay { Action = () => { @@ -133,7 +133,7 @@ namespace osu.Game.Screens.Menu Origin = Anchor.TopRight, Margin = new MarginPadding { Right = 15, Top = 5 } }, - exitConfirmOverlay?.CreateProxy() ?? Empty() + holdToExitGameOverlay?.CreateProxy() ?? Empty() }); Buttons.StateChanged += state => @@ -305,7 +305,7 @@ namespace osu.Game.Screens.Menu this.Exit(); }, () => { - exitConfirmOverlay.Abort(); + holdToExitGameOverlay.Abort(); })); } From 20aedc82ac674b441ee01c31d5b76cf32232564d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:47:32 +0900 Subject: [PATCH 1346/1400] Remove unused code --- osu.Game/Screens/Menu/MainMenu.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 2946425998..f55c44d427 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -157,19 +157,8 @@ namespace osu.Game.Screens.Menu preloadSongSelect(); } - [Resolved(canBeNull: true)] - private IPerformFromScreenRunner performer { get; set; } - public void ReturnToOsuLogo() => Buttons.State = ButtonSystemState.Initial; - private void confirmAndExit() - { - if (exitConfirmedViaDialog) return; - - exitConfirmedViaDialog = true; - performer?.PerformFromScreen(menu => menu.Exit()); - } - private void preloadSongSelect() { if (songSelect == null) From 7fa07805b0bffb300ff1e071868294d3fb7d16cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 14:58:19 +0900 Subject: [PATCH 1347/1400] Expose all notifications from `INotificationOverlay` Also fixes `HasOngoingOperations` not actually working. --- osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs | 3 ++- .../UserInterface/TestSceneFirstRunSetupOverlay.cs | 2 +- osu.Game/Overlays/INotificationOverlay.cs | 14 +++++++++++++- osu.Game/Overlays/NotificationOverlay.cs | 4 +++- osu.Game/Overlays/NotificationOverlayToastTray.cs | 5 +++++ .../Overlays/Notifications/NotificationSection.cs | 5 +++++ 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs index 471700988c..ce9f80a84f 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneToolbar.cs @@ -3,6 +3,7 @@ #nullable disable +using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using Moq; @@ -251,7 +252,7 @@ namespace osu.Game.Tests.Visual.Menus public virtual IBindable UnreadCount => null; - public bool HasOngoingOperations => false; + public IEnumerable AllNotifications => Enumerable.Empty(); } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs index 0b0c29acf6..9275f9755f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunSetupOverlay.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual.UserInterface public virtual IBindable UnreadCount => null; - public bool HasOngoingOperations => false; + public IEnumerable AllNotifications => Enumerable.Empty(); } // interface mocks break hot reload, mocking this stub implementation instead works around it. diff --git a/osu.Game/Overlays/INotificationOverlay.cs b/osu.Game/Overlays/INotificationOverlay.cs index 0d8f73a1d7..1dd6dd2c6c 100644 --- a/osu.Game/Overlays/INotificationOverlay.cs +++ b/osu.Game/Overlays/INotificationOverlay.cs @@ -3,6 +3,8 @@ #nullable disable +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Overlays.Notifications; @@ -34,6 +36,16 @@ namespace osu.Game.Overlays /// /// Whether there are any ongoing operations, such as imports or downloads. /// - bool HasOngoingOperations { get; } + public bool HasOngoingOperations => OngoingOperations.Any(); + + /// + /// All current displayed notifications, whether in the toast tray or a section. + /// + IEnumerable AllNotifications { get; } + + /// + /// All ongoing operations (ie. any not in a completed state). + /// + public IEnumerable OngoingOperations => AllNotifications.OfType().Where(p => p.State != ProgressNotificationState.Completed); } } diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index c53b6b667c..6ef93fac9e 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.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 System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -33,7 +34,8 @@ namespace osu.Game.Overlays public const float TRANSITION_LENGTH = 600; - public bool HasOngoingOperations => sections.Any(s => s.Children.OfType().Any()); + public IEnumerable AllNotifications => + toastTray.Notifications.Concat(sections.SelectMany(s => s.Notifications)); private FlowContainer sections = null!; diff --git a/osu.Game/Overlays/NotificationOverlayToastTray.cs b/osu.Game/Overlays/NotificationOverlayToastTray.cs index 7a793ee092..0ebaff9437 100644 --- a/osu.Game/Overlays/NotificationOverlayToastTray.cs +++ b/osu.Game/Overlays/NotificationOverlayToastTray.cs @@ -28,6 +28,11 @@ namespace osu.Game.Overlays public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => toastFlow.ReceivePositionalInputAt(screenSpacePos); + /// + /// All notifications currently being displayed by the toast tray. + /// + public IEnumerable Notifications => toastFlow; + public bool IsDisplayingToasts => toastFlow.Count > 0; private FillFlowContainer toastFlow = null!; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index de4c72e473..4e28ade802 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -19,6 +19,11 @@ namespace osu.Game.Overlays.Notifications { public partial class NotificationSection : AlwaysUpdateFillFlowContainer { + /// + /// All notifications currently being displayed in this section. + /// + public IEnumerable Notifications => notifications; + private OsuSpriteText countDrawable = null!; private FlowContainer notifications = null!; From 693b7c99067c64f6daa10da3300041a0be0a91b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 15:19:47 +0900 Subject: [PATCH 1348/1400] Reorganise resolved fields in `MainMenu` --- osu.Game/Screens/Menu/MainMenu.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index f55c44d427..f34a1954a5 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -59,12 +59,15 @@ namespace osu.Game.Screens.Menu [Resolved] private MusicController musicController { get; set; } - [Resolved(canBeNull: true)] - private LoginOverlay login { get; set; } - [Resolved] private IAPIProvider api { get; set; } + [Resolved] + private Storage storage { get; set; } + + [Resolved(canBeNull: true)] + private LoginOverlay login { get; set; } + [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } @@ -174,9 +177,6 @@ namespace osu.Game.Screens.Menu return s; } - [Resolved] - private Storage storage { get; set; } - public override void OnEntering(ScreenTransitionEvent e) { base.OnEntering(e); From f66b787b12d5f0a449d3d0c1f8bf497d15c7a216 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 15:20:19 +0900 Subject: [PATCH 1349/1400] Show ongoing operations in exit confirmation dialog Also changes the button to a dangerous button, forcing user acknowledgement --- osu.Game/Screens/Menu/ConfirmExitDialog.cs | 63 ++++++++++++++++++---- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/osu.Game/Screens/Menu/ConfirmExitDialog.cs b/osu.Game/Screens/Menu/ConfirmExitDialog.cs index 4906232d21..fb22f7eff8 100644 --- a/osu.Game/Screens/Menu/ConfirmExitDialog.cs +++ b/osu.Game/Screens/Menu/ConfirmExitDialog.cs @@ -2,38 +2,79 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays; using osu.Game.Overlays.Dialog; namespace osu.Game.Screens.Menu { public partial class ConfirmExitDialog : PopupDialog { + private readonly Action onConfirm; + private readonly Action? onCancel; + /// /// Construct a new exit confirmation dialog. /// /// An action to perform on confirmation. /// An optional action to perform on cancel. public ConfirmExitDialog(Action onConfirm, Action? onCancel = null) + { + this.onConfirm = onConfirm; + this.onCancel = onCancel; + } + + [BackgroundDependencyLoader] + private void load(INotificationOverlay notifications) { HeaderText = "Are you sure you want to exit osu!?"; - BodyText = "Last chance to turn back"; Icon = FontAwesome.Solid.ExclamationTriangle; - Buttons = new PopupDialogButton[] + if (notifications.HasOngoingOperations) { - new PopupDialogOkButton + string text = "There are currently some background operations which will be aborted if you continue:\n\n"; + + foreach (var n in notifications.OngoingOperations) + text += $"{n.Text} ({n.Progress:0%})\n"; + + text += "\nLast chance to turn back"; + + BodyText = text; + + Buttons = new PopupDialogButton[] { - Text = @"Let me out!", - Action = onConfirm - }, - new PopupDialogCancelButton + new PopupDialogDangerousButton + { + Text = @"Let me out!", + Action = onConfirm + }, + new PopupDialogCancelButton + { + Text = @"Cancel", + Action = onCancel + }, + }; + } + else + { + BodyText = "Last chance to turn back"; + + Buttons = new PopupDialogButton[] { - Text = @"Just a little more...", - Action = onCancel - }, - }; + new PopupDialogOkButton + { + Text = @"Let me out!", + Action = onConfirm + }, + new PopupDialogCancelButton + { + Text = @"Just a little more...", + Action = onCancel + }, + }; + } } } } From a76037b6433951f8e5dbe5ab7d6534edb5f37a4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 15:30:21 +0900 Subject: [PATCH 1350/1400] Add test coverage of confirm-for-operations --- .../Navigation/TestSceneScreenNavigation.cs | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs index 18aef99ccd..c3b668f591 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs @@ -22,6 +22,7 @@ using osu.Game.Online.Leaderboards; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; using osu.Game.Overlays.Mods; +using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Toolbar; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; @@ -683,6 +684,44 @@ namespace osu.Game.Tests.Visual.Navigation AddStep("center cursor", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre)); } + [Test] + public void TestExitWithOperationInProgress() + { + AddUntilStep("wait for dialog overlay", () => Game.ChildrenOfType().SingleOrDefault() != null); + + ProgressNotification progressNotification = null!; + + AddStep("start ongoing operation", () => + { + progressNotification = new ProgressNotification + { + Text = "Something is still running", + Progress = 0.5f, + State = ProgressNotificationState.Active, + }; + Game.Notifications.Post(progressNotification); + }); + + AddStep("Hold escape", () => InputManager.PressKey(Key.Escape)); + AddUntilStep("confirmation dialog shown", () => Game.ChildrenOfType().Single().CurrentDialog is ConfirmExitDialog); + AddStep("Release escape", () => InputManager.ReleaseKey(Key.Escape)); + + AddStep("cancel exit", () => InputManager.Key(Key.Escape)); + AddAssert("dialog dismissed", () => Game.ChildrenOfType().Single().CurrentDialog == null); + + AddStep("complete operation", () => + { + progressNotification.Progress = 100; + progressNotification.State = ProgressNotificationState.Completed; + }); + + AddStep("Hold escape", () => InputManager.PressKey(Key.Escape)); + AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroScreen); + AddStep("Release escape", () => InputManager.ReleaseKey(Key.Escape)); + + AddUntilStep("Wait for game exit", () => Game.ScreenStack.CurrentScreen == null); + } + [Test] public void TestExitGameFromSongSelect() { @@ -699,7 +738,7 @@ namespace osu.Game.Tests.Visual.Navigation } [Test] - public void TestRapidBackButtonExit() + public void TestExitWithHoldDisabled() { AddStep("set hold delay to 0", () => Game.LocalConfig.SetValue(OsuSetting.UIHoldActivationDelay, 0.0)); @@ -711,7 +750,7 @@ namespace osu.Game.Tests.Visual.Navigation pushEscape(); - AddAssert("exit dialog is shown", () => Game.Dependencies.Get().CurrentDialog != null); + AddAssert("exit dialog is shown", () => Game.Dependencies.Get().CurrentDialog is ConfirmExitDialog); } private Func playToResults() From 0ab0c52ad577b3e7b406d09fa6056a56ff997c3e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 23 Jun 2023 01:37:25 +0900 Subject: [PATCH 1351/1400] Automated pass --- osu.Android/GameplayScreenRotationLocker.cs | 4 +--- osu.Android/OsuGameActivity.cs | 2 -- osu.Android/OsuGameAndroid.cs | 2 -- osu.Android/Properties/AssemblyInfo.cs | 4 +--- .../MainActivity.cs | 2 -- .../CatchBeatmapConversionTest.cs | 2 -- .../CatchDifficultyCalculatorTest.cs | 4 +--- .../CatchLegacyModConversionTest.cs | 2 -- .../CatchSkinColourDecodingTest.cs | 4 +--- .../CatchSkinnableTestScene.cs | 4 +--- .../Editor/CatchEditorTestSceneContainer.cs | 4 +--- .../CatchSelectionBlueprintTestScene.cs | 4 +--- ...TestSceneBananaShowerPlacementBlueprint.cs | 4 +--- .../Editor/TestSceneCatchDistanceSnapGrid.cs | 4 +--- .../Editor/TestSceneEditor.cs | 4 +--- .../TestSceneFruitPlacementBlueprint.cs | 4 +--- .../JuiceStreamPathTest.cs | 4 +--- .../TestSceneAutoJuiceStream.cs | 2 -- .../TestSceneBananaShower.cs | 2 -- .../TestSceneCatchModHidden.cs | 4 +--- .../TestSceneCatchPlayer.cs | 2 -- .../TestSceneCatchPlayerLegacySkin.cs | 4 +--- .../TestSceneCatchReplay.cs | 4 +--- .../TestSceneCatchStacker.cs | 2 -- .../TestSceneDrawableHitObjectsHidden.cs | 4 +--- .../TestSceneFruitObjects.cs | 2 -- .../TestSceneFruitRandomness.cs | 4 +--- .../TestSceneFruitVisualChange.cs | 2 -- .../TestSceneHyperDash.cs | 2 -- .../TestSceneJuiceStream.cs | 4 +--- .../TestSceneLegacyBeatmapSkin.cs | 6 ++--- .../MainActivity.cs | 2 -- .../ManiaSelectionBlueprintTestScene.cs | 4 +--- .../Editor/TestSceneEditor.cs | 2 -- .../TestSceneHoldNotePlacementBlueprint.cs | 4 +--- .../TestSceneHoldNoteSelectionBlueprint.cs | 4 +--- .../Editor/TestSceneManiaBeatSnapGrid.cs | 4 +--- .../Editor/TestSceneManiaComposeScreen.cs | 6 ++--- .../Editor/TestSceneNoteSelectionBlueprint.cs | 4 +--- .../ManiaDifficultyCalculatorTest.cs | 4 +--- .../ManiaInputTestScene.cs | 2 -- .../ManiaLegacyModConversionTest.cs | 2 -- .../ManiaLegacyReplayTest.cs | 4 +--- .../ManiaSpecialColumnTest.cs | 4 +--- .../Skinning/ColumnTestContainer.cs | 4 +--- .../Skinning/ManiaHitObjectTestScene.cs | 4 +--- .../Skinning/ManiaSkinnableTestScene.cs | 4 +--- .../Skinning/TestSceneColumnBackground.cs | 4 +--- .../Skinning/TestSceneColumnHitObjectArea.cs | 4 +--- .../Skinning/TestSceneDrawableJudgement.cs | 4 +--- .../Skinning/TestSceneHitExplosion.cs | 4 +--- .../Skinning/TestSceneHoldNote.cs | 4 +--- .../Skinning/TestSceneNote.cs | 4 +--- .../Skinning/TestScenePlayfield.cs | 4 +--- .../Skinning/TestSceneStage.cs | 4 +--- .../Skinning/TestSceneStageBackground.cs | 4 +--- .../TestSceneAutoGeneration.cs | 4 +--- .../TestSceneColumn.cs | 2 -- .../TestSceneManiaHitObjectSamples.cs | 4 +--- .../TestSceneManiaPlayer.cs | 4 +--- .../TestScenePlayfieldCoveringContainer.cs | 4 +--- .../Beatmaps/ManiaBeatmap.cs | 2 -- .../Legacy/EndTimeObjectPatternGenerator.cs | 2 -- .../Legacy/HitObjectPatternGenerator.cs | 4 +--- .../Beatmaps/Patterns/Legacy/PatternType.cs | 2 -- .../Beatmaps/Patterns/PatternGenerator.cs | 2 -- .../Beatmaps/StageDefinition.cs | 2 -- .../Difficulty/ManiaDifficultyCalculator.cs | 4 +--- .../Difficulty/ManiaPerformanceAttributes.cs | 2 -- .../Difficulty/ManiaPerformanceCalculator.cs | 2 -- .../Preprocessing/ManiaDifficultyHitObject.cs | 4 +--- .../Difficulty/Skills/Strain.cs | 4 +--- .../DualStageVariantGenerator.cs | 4 +--- .../Blueprints/Components/EditBodyPiece.cs | 4 +--- .../Blueprints/Components/EditNotePiece.cs | 4 +--- .../Blueprints/HoldNotePlacementBlueprint.cs | 6 ++--- .../Blueprints/ManiaSelectionBlueprint.cs | 8 +++---- .../Edit/Blueprints/NotePlacementBlueprint.cs | 4 +--- .../Edit/Blueprints/NoteSelectionBlueprint.cs | 2 -- .../Edit/DrawableManiaEditorRuleset.cs | 2 -- .../Edit/HoldNoteCompositionTool.cs | 4 +--- .../Edit/ManiaBeatSnapGrid.cs | 12 +++++----- .../Edit/ManiaBlueprintContainer.cs | 4 +--- .../Edit/ManiaEditorPlayfield.cs | 2 -- .../Edit/ManiaSelectionHandler.cs | 6 ++--- .../Edit/NoteCompositionTool.cs | 4 +--- .../Judgements/HoldNoteTickJudgement.cs | 4 +--- .../Judgements/ManiaJudgement.cs | 2 -- osu.Game.Rulesets.Mania/ManiaInputManager.cs | 2 -- .../Objects/HoldNoteTick.cs | 4 +--- .../Objects/ManiaHitObject.cs | 2 -- osu.Game.Rulesets.Mania/Objects/Note.cs | 2 -- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 4 +--- .../Properties/AssemblyInfo.cs | 2 -- .../Scoring/ManiaHealthProcessor.cs | 4 +--- .../Scoring/ManiaHitWindows.cs | 2 -- .../SingleStageVariantGenerator.cs | 4 +--- .../UI/Components/ColumnHitObjectArea.cs | 2 -- .../UI/Components/DefaultStageBackground.cs | 4 +--- .../UI/Components/HitObjectArea.cs | 4 +--- osu.Game.Rulesets.Mania/UI/IHitExplosion.cs | 4 +--- .../UI/ManiaPlayfieldAdjustmentContainer.cs | 4 +--- .../UI/ManiaReplayRecorder.cs | 4 +--- .../UI/OrderedHitPolicy.cs | 4 +--- .../UI/PlayfieldCoveringWrapper.cs | 4 +--- .../MainActivity.cs | 2 -- .../TestSceneHitCirclePlacementBlueprint.cs | 4 +--- .../Editor/TestSceneOsuEditor.cs | 2 -- .../Editor/TestSceneOsuEditorGrids.cs | 4 +--- .../TestSceneOsuEditorSelectInvalidPath.cs | 4 +--- .../TestSceneSpinnerPlacementBlueprint.cs | 4 +--- .../TestSceneSpinnerSelectionBlueprint.cs | 4 +--- .../OsuBeatmapConversionTest.cs | 2 -- .../OsuDifficultyCalculatorTest.cs | 4 +--- .../OsuLegacyModConversionTest.cs | 2 -- osu.Game.Rulesets.Osu.Tests/StackingTest.cs | 4 +--- .../TestPlayfieldBorder.cs | 4 +--- .../TestSceneDrawableJudgement.cs | 4 +--- .../TestSceneHitCircle.cs | 4 +--- .../TestSceneHitCircleComboChange.cs | 4 +--- .../TestSceneHitCircleHidden.cs | 2 -- .../TestSceneHitCircleLongCombo.cs | 4 +--- .../TestSceneMissHitWindowJudgements.cs | 4 +--- .../TestSceneNoSpinnerStacking.cs | 2 -- .../TestSceneOsuHitObjectSamples.cs | 4 +--- .../TestSceneOsuPlayer.cs | 4 +--- .../TestSceneResumeOverlay.cs | 4 +--- .../TestSceneShaking.cs | 4 +--- .../TestSceneSliderComboChange.cs | 4 +--- .../TestSceneSliderHidden.cs | 2 -- .../TestSceneSpinnerHidden.cs | 2 -- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs | 2 -- .../Beatmaps/OsuBeatmapConverter.cs | 2 -- .../Beatmaps/OsuBeatmapProcessor.cs | 2 -- .../Difficulty/Evaluators/AimEvaluator.cs | 4 +--- .../Evaluators/FlashlightEvaluator.cs | 4 +--- .../Difficulty/Evaluators/RhythmEvaluator.cs | 4 +--- .../Difficulty/Evaluators/SpeedEvaluator.cs | 4 +--- .../Difficulty/OsuPerformanceAttributes.cs | 2 -- .../Difficulty/OsuPerformanceCalculator.cs | 4 +--- .../Preprocessing/OsuDifficultyHitObject.cs | 4 +--- .../Difficulty/Skills/Aim.cs | 2 -- .../Difficulty/Skills/Flashlight.cs | 2 -- .../Difficulty/Skills/OsuStrainSkill.cs | 2 -- .../Difficulty/Skills/Speed.cs | 2 -- .../Edit/Blueprints/BlueprintPiece.cs | 4 +--- .../HitCircles/Components/HitCirclePiece.cs | 4 +--- .../HitCircles/HitCirclePlacementBlueprint.cs | 4 +--- .../HitCircles/HitCircleSelectionBlueprint.cs | 2 -- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 6 ++--- .../Sliders/Components/SliderBodyPiece.cs | 4 +--- .../Blueprints/Sliders/SliderCircleOverlay.cs | 4 +--- .../Spinners/Components/SpinnerPiece.cs | 4 +--- .../Spinners/SpinnerSelectionBlueprint.cs | 4 +--- .../Edit/HitCircleCompositionTool.cs | 4 +--- .../Edit/OsuBeatmapVerifier.cs | 4 +--- .../Edit/OsuBlueprintContainer.cs | 4 +--- .../Edit/OsuRectangularPositionSnapGrid.cs | 6 ++--- .../Edit/SliderCompositionTool.cs | 4 +--- .../Edit/SpinnerCompositionTool.cs | 4 +--- .../Judgements/ComboResult.cs | 4 +--- .../Judgements/OsuHitCircleJudgementResult.cs | 4 +--- .../Judgements/OsuIgnoreJudgement.cs | 4 +--- .../Judgements/OsuJudgement.cs | 2 -- .../Judgements/OsuJudgementResult.cs | 4 +--- .../Judgements/OsuSpinnerJudgementResult.cs | 4 +--- .../Judgements/SliderTickJudgement.cs | 4 +--- .../Drawables/Connections/FollowPoint.cs | 2 -- .../Drawables/DrawableSpinnerBonusTick.cs | 4 +--- .../Objects/Drawables/ITrackSnaking.cs | 2 -- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 2 -- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 -- .../Objects/SliderEndCircle.cs | 2 -- .../Objects/SliderHeadCircle.cs | 4 +--- osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs | 2 -- .../Objects/SliderTailCircle.cs | 4 +--- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 -- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 -- .../Objects/SpinnerBonusTick.cs | 4 +--- osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs | 4 +--- .../Properties/AssemblyInfo.cs | 2 -- osu.Game.Rulesets.Osu/UI/IHitPolicy.cs | 4 +--- .../UI/OsuPlayfieldAdjustmentContainer.cs | 4 +--- osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs | 4 +--- .../Utils/OsuHitObjectGenerationUtils.cs | 4 +--- .../MainActivity.cs | 2 -- .../DrawableTestHit.cs | 4 +--- .../DrawableTestStrongHit.cs | 4 +--- .../Editor/TestSceneEditor.cs | 4 +--- .../Editor/TestSceneTaikoEditorSaving.cs | 4 +--- .../Editor/TestSceneTaikoHitObjectComposer.cs | 4 +--- .../Skinning/TaikoSkinnableTestScene.cs | 4 +--- .../Skinning/TestSceneDrawableBarLine.cs | 4 +--- .../Skinning/TestSceneDrawableDrumRoll.cs | 4 +--- .../Skinning/TestSceneDrawableHit.cs | 4 +--- .../Skinning/TestSceneHitExplosion.cs | 4 +--- .../Skinning/TestSceneInputDrum.cs | 4 +--- .../Skinning/TestSceneKiaiHitExplosion.cs | 4 +--- .../Skinning/TestSceneTaikoPlayfield.cs | 4 +--- .../Skinning/TestSceneTaikoScroller.cs | 4 +--- .../TaikoBeatmapConversionTest.cs | 2 -- .../TaikoDifficultyCalculatorTest.cs | 4 +--- .../TaikoLegacyModConversionTest.cs | 2 -- .../TestSceneBarLineApplication.cs | 4 +--- .../TestSceneDrumRollApplication.cs | 4 +--- .../TestSceneHitApplication.cs | 4 +--- .../TestSceneHits.cs | 2 -- .../TestSceneSampleOutput.cs | 4 +--- .../TestSceneTaikoPlayer.cs | 4 +--- .../TestSceneTaikoSuddenDeath.cs | 4 +--- .../Beatmaps/TaikoBeatmap.cs | 2 -- .../Beatmaps/TaikoBeatmapConverter.cs | 2 -- .../Difficulty/Skills/Rhythm.cs | 2 -- .../Difficulty/Skills/Stamina.cs | 2 -- .../Difficulty/TaikoDifficultyCalculator.cs | 4 +--- .../Difficulty/TaikoPerformanceAttributes.cs | 2 -- .../Difficulty/TaikoPerformanceCalculator.cs | 2 -- .../Blueprints/DrumRollPlacementBlueprint.cs | 4 +--- .../Edit/Blueprints/HitPiece.cs | 4 +--- .../Edit/Blueprints/LengthPiece.cs | 4 +--- .../Blueprints/SwellPlacementBlueprint.cs | 4 +--- .../Blueprints/TaikoSelectionBlueprint.cs | 4 +--- .../Edit/DrumRollCompositionTool.cs | 4 +--- .../Edit/HitCompositionTool.cs | 4 +--- .../Edit/SwellCompositionTool.cs | 4 +--- .../Edit/TaikoBlueprintContainer.cs | 4 +--- .../Edit/TaikoSelectionHandler.cs | 4 +--- .../Judgements/TaikoDrumRollTickJudgement.cs | 2 -- .../Judgements/TaikoJudgement.cs | 2 -- .../Judgements/TaikoStrongJudgement.cs | 2 -- .../Judgements/TaikoSwellJudgement.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 2 -- .../Objects/Drawables/DrawableFlyingHit.cs | 4 +--- .../Drawables/DrawableStrongNestedHit.cs | 4 +--- .../Objects/DrumRollTick.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs | 2 -- .../Objects/StrongNestedHitObject.cs | 4 +--- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 2 -- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 4 +--- .../Objects/TaikoHitObject.cs | 2 -- .../Objects/TaikoStrongableHitObject.cs | 4 +--- .../Properties/AssemblyInfo.cs | 2 -- .../Scoring/TaikoHealthProcessor.cs | 4 +--- .../Scoring/TaikoHitWindows.cs | 2 -- osu.Game.Rulesets.Taiko/TaikoInputManager.cs | 2 -- osu.Game.Tests.Android/MainActivity.cs | 2 -- .../Formats/LegacyBeatmapEncoderTest.cs | 4 +--- .../Beatmaps/Formats/LegacyDecoderTest.cs | 4 +--- .../Beatmaps/IO/LineBufferedReaderTest.cs | 2 -- .../Beatmaps/IO/OszArchiveReaderTest.cs | 2 -- .../Beatmaps/SliderEventGenerationTest.cs | 4 +--- .../Beatmaps/ToStringFormattingTest.cs | 4 +--- .../Collections/IO/ImportCollectionsTest.cs | 4 +--- .../Database/LegacyBeatmapImporterTest.cs | 4 +--- .../Gameplay/TestSceneHitObjectSamples.cs | 4 +--- .../Gameplay/TestSceneScoreProcessor.cs | 4 +--- osu.Game.Tests/ImportTest.cs | 4 +--- .../Input/ConfineMouseTrackerTest.cs | 6 ++--- .../BeatmapMetadataRomanisationTest.cs | 2 -- .../NonVisual/BarLineGeneratorTest.cs | 4 +--- .../NonVisual/ClosestBeatDivisorTest.cs | 4 +--- .../NonVisual/ControlPointInfoTest.cs | 4 +--- ...DifficultyAdjustmentModCombinationsTest.cs | 2 -- osu.Game.Tests/NonVisual/FormatUtilsTest.cs | 4 +--- .../StatefulMultiplayerClientTest.cs | 4 +--- osu.Game.Tests/NonVisual/PeriodTrackerTest.cs | 4 +--- .../NonVisual/RulesetInfoOrderingTest.cs | 4 +--- osu.Game.Tests/NonVisual/ScoreInfoTest.cs | 4 +--- .../NonVisual/TimeDisplayExtensionTest.cs | 4 +--- .../Online/Chat/MessageNotifierTest.cs | 4 +--- ...TestMultiplayerMessagePackSerialization.cs | 4 +--- .../TestSoloScoreInfoJsonSerialization.cs | 4 +--- .../OnlinePlay/PlaylistExtensionsTest.cs | 4 +--- osu.Game.Tests/Scores/IO/TestScoreEquality.cs | 4 +--- osu.Game.Tests/Skins/IO/ImportSkinTest.cs | 4 +--- .../Skins/LegacyManiaSkinDecoderTest.cs | 4 +--- .../TestSceneBeatmapCardDifficultyList.cs | 4 +--- .../TestSceneBeatmapSetOnlineStatusPill.cs | 4 +--- .../Colours/TestSceneStarDifficultyColours.cs | 6 ++--- .../Editing/TestSceneBlueprintOrdering.cs | 4 +--- .../TestSceneEditorComposeRadioButtons.cs | 4 +--- .../Visual/Editing/TestSceneEditorMenuBar.cs | 4 +--- .../Editing/TestSceneEditorScreenModes.cs | 4 +--- .../Visual/Editing/TestSceneEditorSeeking.cs | 4 +--- .../Editing/TestSceneEditorSummaryTimeline.cs | 4 +--- ...ceneHitObjectDifficultyPointAdjustments.cs | 4 +--- .../TestSceneHitObjectSampleAdjustments.cs | 4 +--- .../Visual/Editing/TestSceneSetupScreen.cs | 4 +--- .../TestSceneTimelineBlueprintContainer.cs | 4 +--- .../TestSceneTimelineHitObjectBlueprint.cs | 2 -- .../Editing/TestSceneTimelineTickDisplay.cs | 4 +--- .../Visual/Editing/TestSceneTimelineZoom.cs | 4 +--- .../Visual/Gameplay/OsuPlayerTestScene.cs | 4 +--- .../Visual/Gameplay/TestSceneFailAnimation.cs | 4 +--- .../Visual/Gameplay/TestSceneFailJudgement.cs | 4 +--- .../Visual/Gameplay/TestSceneKeyCounter.cs | 2 -- .../Visual/Gameplay/TestSceneMedalOverlay.cs | 4 +--- .../TestSceneNightcoreBeatContainer.cs | 4 +--- .../TestSceneSkinEditorComponentsList.cs | 4 +--- .../TestSceneSkinnableAccuracyCounter.cs | 4 +--- .../TestSceneSkinnableComboCounter.cs | 4 +--- .../TestSceneSkinnableHealthDisplay.cs | 4 +--- .../TestSceneSkinnableScoreCounter.cs | 4 +--- .../Visual/Gameplay/TestSceneSpectatorHost.cs | 4 +--- .../Visual/Gameplay/TestSceneStarCounter.cs | 4 +--- .../Visual/Gameplay/TestSceneUnknownMod.cs | 4 +--- .../Visual/Menus/TestSceneDisclaimer.cs | 4 +--- .../Visual/Menus/TestSceneIntroCircles.cs | 2 -- .../Visual/Menus/TestSceneIntroTriangles.cs | 4 +--- .../Visual/Menus/TestSceneIntroWelcome.cs | 2 -- .../Visual/Menus/TestSceneSideOverlays.cs | 4 +--- .../Visual/Menus/TestSceneSongTicker.cs | 4 +--- .../Visual/Mods/TestSceneModFailCondition.cs | 4 +--- .../TestSceneMatchBeatmapDetailArea.cs | 4 +--- .../Multiplayer/TestSceneMatchLeaderboard.cs | 4 +--- .../Multiplayer/TestSceneMultiHeader.cs | 2 -- ...TestSceneMultiplayerGameplayLeaderboard.cs | 4 +--- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 4 +--- .../TestSceneMultiplayerMatchFooter.cs | 4 +--- .../Multiplayer/TestSceneRankRangePill.cs | 4 +--- .../TestSceneStarRatingRangeDisplay.cs | 4 +--- .../TestSceneButtonSystemNavigation.cs | 4 +--- .../Navigation/TestSceneEditDefaultSkin.cs | 4 +--- .../TestSceneStartupBeatmapSetDisplay.cs | 4 +--- .../Navigation/TestSceneStartupRuleset.cs | 2 -- .../Navigation/TestSettingsMigration.cs | 4 +--- .../Online/TestSceneBeatmapAvailability.cs | 2 -- .../Online/TestSceneBeatmapSetOverlay.cs | 4 +--- .../TestSceneChangelogSupporterPromo.cs | 4 +--- .../Visual/Online/TestSceneCommentsHeader.cs | 2 -- .../Online/TestSceneDashboardOverlay.cs | 2 -- .../Online/TestSceneExternalLinkButton.cs | 2 -- .../Visual/Online/TestSceneGraph.cs | 2 -- .../Visual/Online/TestSceneHomeNewsPanel.cs | 2 -- .../TestSceneLeaderboardScopeSelector.cs | 2 -- .../Visual/Online/TestSceneNewsCard.cs | 2 -- .../TestSceneOnlineBeatmapListingOverlay.cs | 2 -- .../TestSceneOnlineBeatmapSetOverlay.cs | 2 -- .../Online/TestSceneOnlineViewContainer.cs | 2 -- .../Online/TestSceneRankingsCountryFilter.cs | 2 -- .../Visual/Online/TestSceneRankingsHeader.cs | 2 -- .../Online/TestSceneSpotlightsLayout.cs | 2 -- .../Online/TestSceneTotalCommentsCounter.cs | 2 -- .../Visual/Online/TestSceneWikiMainPage.cs | 4 +--- .../TestScenePlaylistsParticipantsList.cs | 4 +--- .../Playlists/TestScenePlaylistsScreen.cs | 2 -- .../Visual/Ranking/TestSceneAccuracyCircle.cs | 4 +--- .../TestSceneContractedPanelMiddleContent.cs | 4 +--- .../TestSceneExpandedPanelTopContent.cs | 4 +--- .../Settings/TestSceneDirectorySelector.cs | 4 +--- .../Visual/Settings/TestSceneFileSelector.cs | 6 ++--- .../Settings/TestSceneMigrationScreens.cs | 4 +--- .../Settings/TestSceneSettingsSource.cs | 2 -- .../TestSceneBeatmapOptionsOverlay.cs | 2 -- .../TestSceneUserTopScoreContainer.cs | 2 -- .../UserInterface/TestSceneBackButton.cs | 4 +--- .../TestSceneBeatmapListingSortTabControl.cs | 2 -- .../TestSceneBeatmapSearchFilter.cs | 2 -- .../TestSceneBreadcrumbControl.cs | 2 -- .../UserInterface/TestSceneColourPicker.cs | 4 +--- .../TestSceneCommentRepliesButton.cs | 2 -- .../UserInterface/TestSceneContextMenu.cs | 2 -- .../Visual/UserInterface/TestSceneCursors.cs | 2 -- .../TestSceneDashboardBeatmapListing.cs | 2 -- .../UserInterface/TestSceneDrawableDate.cs | 4 +--- .../UserInterface/TestSceneEditorSidebar.cs | 4 +--- .../UserInterface/TestSceneExpandingBar.cs | 2 -- .../TestSceneFirstRunScreenBehaviour.cs | 4 +--- .../TestSceneFirstRunScreenBundledBeatmaps.cs | 4 +--- ...TestSceneFirstRunScreenImportFromStable.cs | 4 +--- .../TestSceneFirstRunScreenUIScale.cs | 4 +--- .../TestSceneFooterButtonMods.cs | 4 +--- .../TestSceneHoldToConfirmOverlay.cs | 2 -- .../UserInterface/TestSceneIconButton.cs | 4 +--- .../TestSceneLabelledDropdown.cs | 4 +--- .../TestSceneLabelledSliderBar.cs | 4 +--- .../TestSceneLabelledSwitchButton.cs | 4 +--- .../UserInterface/TestSceneLabelledTextBox.cs | 2 -- .../UserInterface/TestSceneLoadingSpinner.cs | 2 -- .../UserInterface/TestSceneLogoAnimation.cs | 4 +--- .../UserInterface/TestSceneModDisplay.cs | 4 +--- .../UserInterface/TestSceneModSwitchSmall.cs | 4 +--- .../UserInterface/TestSceneModSwitchTiny.cs | 4 +--- .../UserInterface/TestSceneOnScreenDisplay.cs | 2 -- .../UserInterface/TestSceneOsuDropdown.cs | 4 +--- .../Visual/UserInterface/TestSceneOsuLogo.cs | 4 +--- .../UserInterface/TestSceneOsuPopover.cs | 4 +--- .../UserInterface/TestSceneOsuTextBox.cs | 4 +--- .../UserInterface/TestSceneOverlayHeader.cs | 2 -- .../TestSceneOverlayHeaderBackground.cs | 2 -- .../TestSceneOverlayRulesetSelector.cs | 2 -- .../UserInterface/TestScenePageSelector.cs | 2 -- .../TestSceneParallaxContainer.cs | 2 -- .../TestSceneRankingsSortTabControl.cs | 2 -- .../UserInterface/TestSceneRoundedButton.cs | 4 +--- .../TestSceneScreenBreadcrumbControl.cs | 2 -- .../TestSceneSettingsCheckbox.cs | 4 +--- .../TestSceneShearedOverlayHeader.cs | 4 +--- .../TestSceneShearedSearchTextBox.cs | 4 +--- .../UserInterface/TestSceneTabControl.cs | 2 -- .../UserInterface/TestSceneToggleMenuItem.cs | 4 +--- .../UserInterface/TestSceneTwoLayerButton.cs | 2 -- .../UserInterface/TestSceneUserListToolbar.cs | 2 -- .../UserInterface/TestSceneVolumePieces.cs | 2 -- .../UserInterface/TestSceneWaveContainer.cs | 2 -- .../UserInterface/ThemeComparisonTestScene.cs | 4 +--- .../TestSceneDrawableTournamentMatch.cs | 4 +--- .../TestSceneDrawableTournamentTeam.cs | 4 +--- .../Components/TestSceneMatchHeader.cs | 4 +--- .../Components/TestSceneMatchScoreDisplay.cs | 4 +--- .../Components/TestSceneRoundDisplay.cs | 4 +--- .../TestSceneTournamentBeatmapPanel.cs | 6 ++--- .../TestSceneTournamentMatchChatDisplay.cs | 4 +--- .../NonVisual/CustomTourneyDirectoryTest.cs | 4 +--- .../NonVisual/LadderInfoSerialisationTest.cs | 4 +--- .../Screens/TestSceneDrawingsScreen.cs | 4 +--- .../Screens/TestSceneLadderEditorScreen.cs | 4 +--- .../Screens/TestSceneLadderScreen.cs | 4 +--- .../Screens/TestSceneRoundEditorScreen.cs | 4 +--- .../Screens/TestSceneSeedingEditorScreen.cs | 4 +--- .../Screens/TestSceneSeedingScreen.cs | 4 +--- .../Screens/TestSceneSetupScreen.cs | 4 +--- .../Screens/TestSceneShowcaseScreen.cs | 4 +--- .../TestSceneStablePathSelectScreen.cs | 4 +--- .../Screens/TestSceneTeamEditorScreen.cs | 4 +--- .../Screens/TestSceneTeamIntroScreen.cs | 4 +--- .../Screens/TestSceneTeamWinScreen.cs | 4 +--- .../TestSceneTournamentSceneManager.cs | 4 +--- .../TournamentTestBrowser.cs | 4 +--- .../TournamentTestRunner.cs | 4 +--- .../Components/ControlPanel.cs | 2 -- osu.Game.Tournament/Components/DateTextBox.cs | 4 +--- .../Components/DrawableTeamHeader.cs | 4 +--- .../Components/DrawableTeamTitleWithHeader.cs | 4 +--- .../Components/DrawableTeamWithPlayers.cs | 4 +--- .../DrawableTournamentHeaderLogo.cs | 4 +--- .../DrawableTournamentHeaderText.cs | 4 +--- .../Components/IPCErrorDialog.cs | 4 +--- .../Components/RoundDisplay.cs | 4 +--- .../Components/TournamentModIcon.cs | 6 ++--- .../TournamentSpriteTextWithBackground.cs | 4 +--- .../Configuration/TournamentConfigManager.cs | 4 +--- .../IO/TournamentVideoResourceStore.cs | 4 +--- osu.Game.Tournament/IPC/MatchIPCInfo.cs | 4 +--- osu.Game.Tournament/Models/BeatmapChoice.cs | 4 +--- .../Models/LadderEditorInfo.cs | 4 +--- osu.Game.Tournament/Models/LadderInfo.cs | 4 +--- osu.Game.Tournament/Models/SeedingResult.cs | 4 +--- .../Models/TournamentProgression.cs | 4 +--- osu.Game.Tournament/Models/TournamentRound.cs | 4 +--- .../Properties/AssemblyInfo.cs | 2 -- .../Screens/BeatmapInfoScreen.cs | 4 +--- .../Components/DrawingsConfigManager.cs | 2 -- .../Screens/Drawings/Components/Group.cs | 2 -- .../Drawings/Components/GroupContainer.cs | 2 -- .../Screens/Drawings/Components/GroupTeam.cs | 4 +--- .../Screens/Drawings/Components/ITeamList.cs | 2 -- .../Screens/Editors/IModelBacked.cs | 4 +--- .../Screens/Editors/RoundEditorScreen.cs | 8 +++---- .../Screens/Editors/SeedingEditorScreen.cs | 6 ++--- .../Screens/Editors/TeamEditorScreen.cs | 14 +++++------- .../Gameplay/Components/MatchRoundDisplay.cs | 4 +--- .../Gameplay/Components/TeamDisplay.cs | 4 +--- .../Screens/Gameplay/Components/TeamScore.cs | 4 +--- .../Ladder/Components/ProgressionPath.cs | 4 +--- .../Ladder/Components/SettingsTeamDropdown.cs | 4 +--- .../Screens/Ladder/LadderDragContainer.cs | 4 +--- .../Screens/Showcase/ShowcaseScreen.cs | 4 +--- .../Screens/Showcase/TournamentLogo.cs | 4 +--- .../Screens/TournamentScreen.cs | 6 ++--- osu.Game.Tournament/TournamentSpriteText.cs | 4 +--- osu.Game.Tournament/TourneyButton.cs | 4 +--- osu.Game.Tournament/WarningBox.cs | 4 +--- osu.Game/Beatmaps/APIFailTimes.cs | 2 -- .../Beatmaps/BeatmapMetadataInfoExtensions.cs | 4 +--- osu.Game/Beatmaps/BeatmapOnlineStatus.cs | 2 -- osu.Game/Beatmaps/BeatmapSetHypeStatus.cs | 4 +--- .../Beatmaps/BeatmapSetNominationStatus.cs | 4 +--- .../Beatmaps/BeatmapSetOnlineAvailability.cs | 4 +--- osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs | 2 -- osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs | 4 +--- osu.Game/Beatmaps/BeatmapStatisticIcon.cs | 4 +--- osu.Game/Beatmaps/CountdownType.cs | 4 +--- .../Drawables/BeatmapBackgroundSprite.cs | 2 -- .../Cards/BeatmapCardDifficultyList.cs | 4 +--- .../Cards/BeatmapCardDownloadProgressBar.cs | 8 +++---- .../Drawables/Cards/BeatmapCardThumbnail.cs | 4 +--- .../Cards/BeatmapSetFavouriteState.cs | 4 +--- .../Cards/Buttons/BeatmapCardIconButton.cs | 4 +--- .../Cards/ExpandedContentScrollContainer.cs | 4 +--- osu.Game/Beatmaps/Drawables/Cards/IconPill.cs | 2 -- .../Cards/Statistics/FavouritesStatistic.cs | 4 +--- .../Cards/Statistics/PlayCountStatistic.cs | 4 +--- .../Drawables/Cards/StoryboardIconPill.cs | 4 +--- .../Beatmaps/Drawables/Cards/VideoIconPill.cs | 4 +--- .../Drawables/DifficultySpectrumDisplay.cs | 4 +--- .../Beatmaps/Drawables/DownloadProgressBar.cs | 4 +--- .../Beatmaps/Drawables/StarRatingDisplay.cs | 10 ++++----- .../UpdateableBeatmapBackgroundSprite.cs | 6 ++--- osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs | 4 +--- .../Beatmaps/Formats/IHasCustomColours.cs | 4 +--- .../Beatmaps/Formats/JsonBeatmapDecoder.cs | 2 -- ...egacyDifficultyCalculatorBeatmapDecoder.cs | 4 +--- osu.Game/Beatmaps/Formats/Parsing.cs | 4 +--- osu.Game/Beatmaps/IBeatmap.cs | 4 +--- osu.Game/Beatmaps/IBeatmapConverter.cs | 2 -- osu.Game/Beatmaps/IBeatmapProcessor.cs | 2 -- osu.Game/Beatmaps/IBeatmapResourceProvider.cs | 4 +--- .../Beatmaps/Legacy/LegacyControlPointInfo.cs | 4 +--- osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs | 4 +--- osu.Game/Beatmaps/Legacy/LegacyEventType.cs | 4 +--- .../Beatmaps/Legacy/LegacyHitObjectType.cs | 4 +--- .../Beatmaps/Legacy/LegacyHitSoundType.cs | 4 +--- osu.Game/Beatmaps/Legacy/LegacyMods.cs | 2 -- osu.Game/Beatmaps/Legacy/LegacySampleBank.cs | 4 +--- osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs | 4 +--- osu.Game/Beatmaps/Timing/BreakPeriod.cs | 2 -- osu.Game/Configuration/BackgroundSource.cs | 4 +--- .../DevelopmentOsuConfigManager.cs | 4 +--- .../Configuration/DiscordRichPresenceMode.cs | 4 +--- osu.Game/Configuration/HUDVisibilityMode.cs | 4 +--- .../Configuration/InMemoryConfigManager.cs | 2 -- osu.Game/Configuration/OsuConfigManager.cs | 4 +--- .../Configuration/RandomSelectAlgorithm.cs | 2 -- osu.Game/Configuration/ScalingMode.cs | 4 +--- osu.Game/Configuration/ScreenshotFormat.cs | 2 -- .../ScrollVisualisationMethod.cs | 2 -- .../Configuration/SeasonalBackgroundMode.cs | 4 +--- osu.Game/Configuration/SettingsStore.cs | 2 -- .../Configuration/StorageConfigManager.cs | 4 +--- osu.Game/Database/ICanAcceptFiles.cs | 2 -- osu.Game/Database/IHasFiles.cs | 2 -- osu.Game/Database/IHasGuidPrimaryKey.cs | 4 +--- osu.Game/Database/IHasNamedFiles.cs | 4 +--- osu.Game/Database/IHasPrimaryKey.cs | 2 -- osu.Game/Database/IModelFileManager.cs | 2 -- osu.Game/Database/IModelManager.cs | 4 +--- osu.Game/Database/INamedFileInfo.cs | 2 -- osu.Game/Database/IPostNotifications.cs | 4 +--- .../Graphics/Backgrounds/BeatmapBackground.cs | 4 +--- .../Graphics/Backgrounds/SkinBackground.cs | 4 +--- .../Containers/ConstrainedIconContainer.cs | 2 -- .../Containers/ExpandingButtonContainer.cs | 4 +--- osu.Game/Graphics/Containers/IExpandable.cs | 4 +--- .../Containers/IExpandingContainer.cs | 4 +--- .../Markdown/OsuMarkdownContainer.cs | 4 +--- .../Markdown/OsuMarkdownFencedCodeBlock.cs | 4 +--- .../Containers/Markdown/OsuMarkdownHeading.cs | 4 +--- .../Containers/Markdown/OsuMarkdownImage.cs | 4 +--- .../Markdown/OsuMarkdownOrderedListItem.cs | 4 +--- .../Markdown/OsuMarkdownQuoteBlock.cs | 4 +--- .../Markdown/OsuMarkdownSeparator.cs | 4 +--- .../Containers/Markdown/OsuMarkdownTable.cs | 4 +--- .../Markdown/OsuMarkdownTableCell.cs | 4 +--- .../Markdown/OsuMarkdownUnorderedListItem.cs | 4 +--- .../Graphics/Containers/OsuHoverContainer.cs | 2 -- .../ReverseChildIDFillFlowContainer.cs | 4 +--- .../Graphics/Containers/ShakeContainer.cs | 2 -- .../Containers/UserTrackingScrollContainer.cs | 4 +--- osu.Game/Graphics/Containers/WaveContainer.cs | 2 -- .../Cursor/OsuContextMenuContainer.cs | 2 -- .../Graphics/Cursor/OsuTooltipContainer.cs | 2 -- osu.Game/Graphics/DateTooltip.cs | 2 -- osu.Game/Graphics/DrawableDate.cs | 2 -- osu.Game/Graphics/ErrorTextFlowContainer.cs | 4 +--- osu.Game/Graphics/IHasAccentColour.cs | 2 -- .../Vertices/PositionAndColourVertex.cs | 4 +--- osu.Game/Graphics/OsuColour.cs | 2 -- osu.Game/Graphics/OsuIcon.cs | 4 +--- osu.Game/Graphics/ParticleExplosion.cs | 4 +--- .../Graphics/Sprites/GlowingSpriteText.cs | 2 -- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 2 -- osu.Game/Graphics/UserInterface/Bar.cs | 2 -- osu.Game/Graphics/UserInterface/BarGraph.cs | 4 +--- .../UserInterface/BasicSearchTextBox.cs | 4 +--- .../CommaSeparatedScoreCounter.cs | 4 +--- .../UserInterface/DangerousRoundedButton.cs | 4 +--- .../Graphics/UserInterface/DialogButton.cs | 2 -- .../UserInterface/DrawableStatefulMenuItem.cs | 4 +--- .../UserInterface/ExpandableSlider.cs | 8 +++---- .../Graphics/UserInterface/ExpandingBar.cs | 2 -- .../Graphics/UserInterface/HoverSampleSet.cs | 4 +--- osu.Game/Graphics/UserInterface/IconButton.cs | 2 -- .../Graphics/UserInterface/LoadingButton.cs | 2 -- .../Graphics/UserInterface/LoadingSpinner.cs | 2 -- .../UserInterface/OsuAnimatedButton.cs | 4 +--- .../Graphics/UserInterface/OsuContextMenu.cs | 4 +--- .../Graphics/UserInterface/OsuEnumDropdown.cs | 2 -- .../Graphics/UserInterface/OsuNumberBox.cs | 4 +--- .../UserInterface/OsuPasswordTextBox.cs | 4 +--- .../Graphics/UserInterface/OsuTabDropdown.cs | 2 -- .../PageSelector/PageEllipsis.cs | 4 +--- .../PageSelector/PageSelector.cs | 2 -- .../UserInterface/PercentageCounter.cs | 2 -- .../Graphics/UserInterface/SearchTextBox.cs | 2 -- .../UserInterface/SeekLimitedSearchTextBox.cs | 2 -- .../UserInterface/ShearedSearchTextBox.cs | 4 +--- .../UserInterface/SlimEnumDropdown.cs | 2 -- .../Graphics/UserInterface/StarCounter.cs | 2 -- osu.Game/Graphics/UserInterface/TimeSlider.cs | 4 +--- .../Graphics/UserInterface/TwoLayerButton.cs | 2 -- .../UserInterfaceV2/LabelledColourPalette.cs | 4 +--- .../UserInterfaceV2/LabelledComponent.cs | 4 +--- .../UserInterfaceV2/LabelledDropdown.cs | 4 +--- .../UserInterfaceV2/LabelledEnumDropdown.cs | 4 +--- .../UserInterfaceV2/LabelledNumberBox.cs | 4 +--- .../UserInterfaceV2/LabelledSliderBar.cs | 4 +--- .../UserInterfaceV2/LabelledSwitchButton.cs | 4 +--- .../UserInterfaceV2/OsuColourPicker.cs | 4 +--- .../OsuDirectorySelectorParentDirectory.cs | 4 +--- .../UserInterfaceV2/OsuHSVColourPicker.cs | 4 +--- .../UserInterfaceV2/OsuHexColourPicker.cs | 4 +--- .../Graphics/UserInterfaceV2/OsuPopover.cs | 4 +--- osu.Game/IO/Archives/LegacyByteArrayReader.cs | 4 +--- .../Archives/LegacyDirectoryArchiveReader.cs | 2 -- .../IO/Archives/LegacyFileArchiveReader.cs | 4 +--- .../FileAbstraction/StreamFileAbstraction.cs | 4 +--- osu.Game/IO/Legacy/ILegacySerializable.cs | 4 +--- osu.Game/IO/OsuStorage.cs | 4 +--- .../SnakeCaseStringEnumConverter.cs | 4 +--- .../SnakeCaseKeyContractResolver.cs | 2 -- osu.Game/Input/IdleTracker.cs | 4 +--- osu.Game/Input/OsuConfineMouseMode.cs | 4 +--- osu.Game/Input/OsuUserInputManager.cs | 4 +--- osu.Game/Online/API/APIException.cs | 4 +--- osu.Game/Online/API/APIMessagesRequest.cs | 2 -- .../API/ModSettingsDictionaryFormatter.cs | 4 +--- osu.Game/Online/API/OsuJsonWebRequest.cs | 4 +--- osu.Game/Online/API/OsuWebRequest.cs | 4 +--- .../Online/API/Requests/CommentVoteRequest.cs | 2 -- .../API/Requests/CreateChannelRequest.cs | 4 +--- .../CreateNewPrivateMessageRequest.cs | 2 -- osu.Game/Online/API/Requests/Cursor.cs | 4 +--- .../API/Requests/DownloadBeatmapSetRequest.cs | 2 -- .../API/Requests/DownloadReplayRequest.cs | 2 -- .../API/Requests/GetBeatmapSetRequest.cs | 2 -- .../Online/API/Requests/GetBeatmapsRequest.cs | 4 +--- .../API/Requests/GetChangelogBuildRequest.cs | 2 -- .../API/Requests/GetChangelogRequest.cs | 2 -- .../Online/API/Requests/GetCommentsRequest.cs | 2 -- .../API/Requests/GetCountryRankingsRequest.cs | 2 -- .../Online/API/Requests/GetFriendsRequest.cs | 2 -- .../Online/API/Requests/GetMessagesRequest.cs | 2 -- .../Online/API/Requests/GetRankingsRequest.cs | 2 -- .../Requests/GetSeasonalBackgroundsRequest.cs | 2 -- .../Requests/GetSpotlightRankingsRequest.cs | 2 -- .../Online/API/Requests/GetTopUsersRequest.cs | 2 -- .../API/Requests/GetUserBeatmapsRequest.cs | 2 -- .../Requests/GetUserKudosuHistoryRequest.cs | 2 -- .../GetUserMostPlayedBeatmapsRequest.cs | 2 -- .../API/Requests/GetUserRankingsRequest.cs | 2 -- .../GetUserRecentActivitiesRequest.cs | 2 -- .../Online/API/Requests/GetWikiRequest.cs | 4 +--- .../Online/API/Requests/JoinChannelRequest.cs | 2 -- .../API/Requests/LeaveChannelRequest.cs | 2 -- .../API/Requests/ListChannelsRequest.cs | 2 -- .../API/Requests/MarkChannelAsReadRequest.cs | 2 -- .../API/Requests/PaginatedAPIRequest.cs | 4 +--- .../API/Requests/PaginationParameters.cs | 4 +--- .../Requests/PostBeatmapFavouriteRequest.cs | 2 -- .../Online/API/Requests/PostMessageRequest.cs | 2 -- .../API/Requests/Responses/APIPlayStyle.cs | 4 +--- .../Requests/Responses/APIUserAchievement.cs | 4 +--- .../Requests/Responses/APIUserHistoryCount.cs | 4 +--- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 6 ++--- osu.Game/Online/Chat/ErrorMessage.cs | 4 +--- .../DevelopmentEndpointConfiguration.cs | 4 +--- osu.Game/Online/Leaderboards/DrawableRank.cs | 2 -- .../Multiplayer/IMultiplayerLoungeServer.cs | 4 +--- .../Multiplayer/IMultiplayerRoomServer.cs | 4 +--- .../Multiplayer/InvalidPasswordException.cs | 4 +--- .../InvalidStateChangeException.cs | 4 +--- .../Multiplayer/InvalidStateException.cs | 4 +--- .../Online/Multiplayer/MatchUserRequest.cs | 4 +--- .../Online/Multiplayer/NotHostException.cs | 4 +--- .../Multiplayer/NotJoinedRoomException.cs | 4 +--- osu.Game/Online/Multiplayer/QueueMode.cs | 4 +--- .../Online/Placeholders/LoginPlaceholder.cs | 6 ++--- .../Online/Placeholders/MessagePlaceholder.cs | 2 -- osu.Game/Online/Rooms/APIScoreToken.cs | 4 +--- osu.Game/Online/Rooms/CreateRoomRequest.cs | 4 +--- .../Online/Rooms/CreateRoomScoreRequest.cs | 4 +--- .../Online/Rooms/GetRoomLeaderboardRequest.cs | 4 +--- osu.Game/Online/Rooms/GetRoomRequest.cs | 4 +--- osu.Game/Online/Rooms/GetRoomsRequest.cs | 4 +--- osu.Game/Online/Rooms/IndexScoresParams.cs | 4 +--- osu.Game/Online/Rooms/ItemAttemptsCount.cs | 4 +--- osu.Game/Online/Rooms/JoinRoomRequest.cs | 4 +--- osu.Game/Online/Rooms/MatchType.cs | 4 +--- osu.Game/Online/Rooms/MultiplayerScores.cs | 4 +--- osu.Game/Online/Rooms/PartRoomRequest.cs | 4 +--- osu.Game/Online/Rooms/RoomAvailability.cs | 2 -- osu.Game/Online/Rooms/RoomCategory.cs | 4 +--- .../Rooms/RoomStatuses/RoomStatusEnded.cs | 4 +--- .../Rooms/RoomStatuses/RoomStatusOpen.cs | 4 +--- .../Rooms/RoomStatuses/RoomStatusPlaying.cs | 4 +--- .../Rooms/ShowPlaylistUserScoreRequest.cs | 4 +--- .../Online/Rooms/SubmitRoomScoreRequest.cs | 4 +--- osu.Game/Online/Rooms/SubmitScoreRequest.cs | 4 +--- osu.Game/Online/SignalRWorkaroundTypes.cs | 4 +--- .../Online/Solo/CreateSoloScoreRequest.cs | 4 +--- .../Online/Solo/SubmitSoloScoreRequest.cs | 4 +--- osu.Game/Online/Spectator/ISpectatorClient.cs | 4 +--- osu.Game/Online/Spectator/ISpectatorServer.cs | 4 +--- osu.Game/OsuGameBase_Importing.cs | 4 +--- .../AccountCreationBackground.cs | 4 +--- .../AccountCreation/AccountCreationScreen.cs | 4 +--- .../BeatmapListingSortTabControl.cs | 2 -- .../BeatmapListing/BeatmapSearchFilterRow.cs | 2 -- .../BeatmapSearchRulesetFilterRow.cs | 2 -- .../BeatmapSearchScoreFilterRow.cs | 2 -- .../Overlays/BeatmapListing/SearchCategory.cs | 4 +--- .../Overlays/BeatmapListing/SearchExplicit.cs | 4 +--- .../Overlays/BeatmapListing/SearchExtra.cs | 2 -- .../Overlays/BeatmapListing/SearchGeneral.cs | 4 +--- .../Overlays/BeatmapListing/SearchGenre.cs | 4 +--- .../Overlays/BeatmapListing/SearchLanguage.cs | 4 +--- .../Overlays/BeatmapListing/SearchPlayed.cs | 2 -- .../Overlays/BeatmapListing/SortCriteria.cs | 4 +--- .../BeatmapSet/BeatmapRulesetSelector.cs | 2 -- .../BeatmapSet/BeatmapSetLayoutSection.cs | 2 -- .../BeatmapSet/Buttons/PreviewButton.cs | 2 -- osu.Game/Overlays/BeatmapSet/Info.cs | 2 -- .../BeatmapSet/LeaderboardScopeSelector.cs | 2 -- osu.Game/Overlays/BeatmapSet/MetadataType.cs | 4 +--- .../BeatmapSet/Scores/NoScoresPlaceholder.cs | 2 -- .../Scores/NotSupporterPlaceholder.cs | 2 -- .../Scores/ScoreTableRowBackground.cs | 4 +--- .../BeatmapSet/Scores/ScoreboardTime.cs | 4 +--- .../BeatmapSet/Scores/TopScoreUserSection.cs | 4 +--- .../BreadcrumbControlOverlayHeader.cs | 2 -- osu.Game/Overlays/Changelog/ChangelogEntry.cs | 8 +++---- .../Overlays/Changelog/ChangelogListing.cs | 4 +--- .../Changelog/ChangelogSupporterPromo.cs | 4 +--- .../Changelog/ChangelogUpdateStreamControl.cs | 2 -- .../Overlays/Chat/ChannelScrollContainer.cs | 4 +--- .../Comments/Buttons/ChevronButton.cs | 2 -- .../Comments/Buttons/CommentRepliesButton.cs | 4 +--- .../Comments/CommentMarkdownContainer.cs | 4 +--- .../Comments/CommentsShowMoreButton.cs | 2 -- .../Comments/DeletedCommentsCounter.cs | 2 -- osu.Game/Overlays/Comments/HeaderButton.cs | 2 -- .../Dashboard/DashboardOverlayHeader.cs | 2 -- .../Dashboard/Friends/FriendStream.cs | 2 -- .../Friends/FriendsOnlineStatusItem.cs | 2 -- .../Dashboard/Friends/OnlineStatus.cs | 4 +--- .../Dashboard/Friends/UserListToolbar.cs | 2 -- .../Dashboard/Friends/UserSortTabControl.cs | 2 -- .../Dashboard/Home/DashboardBeatmapListing.cs | 2 -- .../Home/DashboardNewBeatmapPanel.cs | 2 -- .../Home/DashboardPopularBeatmapPanel.cs | 2 -- .../Dashboard/Home/DrawableBeatmapList.cs | 2 -- .../Dashboard/Home/DrawableNewBeatmapList.cs | 2 -- .../Home/DrawablePopularBeatmapList.cs | 2 -- osu.Game/Overlays/Dashboard/Home/HomePanel.cs | 2 -- .../Home/News/FeaturedNewsItemPanel.cs | 2 -- .../Dashboard/Home/News/NewsGroupItem.cs | 2 -- .../Dashboard/Home/News/NewsItemGroupPanel.cs | 2 -- .../Dashboard/Home/News/NewsTitleLink.cs | 2 -- osu.Game/Overlays/DashboardOverlay.cs | 2 -- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 -- osu.Game/Overlays/Dialog/PopupDialogButton.cs | 2 -- .../Dialog/PopupDialogCancelButton.cs | 2 -- .../Overlays/Dialog/PopupDialogOkButton.cs | 2 -- osu.Game/Overlays/FullscreenOverlay.cs | 6 ++--- osu.Game/Overlays/INamedOverlayComponent.cs | 4 +--- osu.Game/Overlays/INotificationOverlay.cs | 4 +--- osu.Game/Overlays/IOverlayManager.cs | 4 +--- osu.Game/Overlays/Login/UserDropdown.cs | 4 +--- .../Overlays/Mods/DeselectAllModsButton.cs | 4 +--- .../Mods/DifficultyMultiplierDisplay.cs | 4 +--- .../Mods/IncompatibilityDisplayingModPanel.cs | 6 ++--- .../Mods/IncompatibilityDisplayingTooltip.cs | 6 ++--- osu.Game/Overlays/Mods/ModSettingsArea.cs | 6 ++--- .../Overlays/Music/MusicKeyBindingHandler.cs | 16 ++++++-------- .../Music/NowPlayingCollectionDropdown.cs | 2 -- osu.Game/Overlays/News/NewsPostBackground.cs | 2 -- .../Notifications/SimpleErrorNotification.cs | 4 +--- osu.Game/Overlays/OSD/Toast.cs | 2 -- osu.Game/Overlays/OnlineOverlay.cs | 2 -- osu.Game/Overlays/OverlayColourProvider.cs | 2 -- osu.Game/Overlays/OverlayHeader.cs | 4 +--- osu.Game/Overlays/OverlayHeaderBackground.cs | 2 -- osu.Game/Overlays/OverlayRulesetSelector.cs | 2 -- osu.Game/Overlays/OverlayRulesetTabItem.cs | 4 +--- osu.Game/Overlays/OverlaySidebar.cs | 4 +--- osu.Game/Overlays/Rankings/CountryFilter.cs | 4 +--- osu.Game/Overlays/Rankings/CountryPill.cs | 2 -- osu.Game/Overlays/Rankings/RankingsScope.cs | 4 +--- .../Rankings/RankingsSortTabControl.cs | 2 -- .../Rankings/Tables/CountriesTable.cs | 8 +++---- .../Rankings/Tables/PerformanceTable.cs | 2 -- .../Overlays/Rankings/Tables/ScoresTable.cs | 2 -- .../Rankings/Tables/TableRowBackground.cs | 4 +--- .../Settings/DangerousSettingsButton.cs | 2 -- osu.Game/Overlays/Settings/ISettingsItem.cs | 4 +--- osu.Game/Overlays/Settings/OutlinedTextBox.cs | 4 +--- .../Settings/Sections/Audio/OffsetSettings.cs | 2 -- .../Settings/Sections/Audio/VolumeSettings.cs | 2 -- .../Settings/Sections/AudioSection.cs | 2 -- .../Settings/Sections/DebugSection.cs | 2 -- .../Sections/DebugSettings/GeneralSettings.cs | 2 -- .../Sections/DebugSettings/MemorySettings.cs | 2 -- .../Sections/Gameplay/AudioSettings.cs | 4 +--- .../Sections/Gameplay/BackgroundSettings.cs | 4 +--- .../Sections/Gameplay/BeatmapSettings.cs | 4 +--- .../Sections/Gameplay/GeneralSettings.cs | 4 +--- .../Settings/Sections/Gameplay/HUDSettings.cs | 2 -- .../Sections/Gameplay/InputSettings.cs | 4 +--- .../Sections/Gameplay/ModsSettings.cs | 2 -- .../Settings/Sections/GameplaySection.cs | 2 -- .../Sections/Graphics/ScreenshotSettings.cs | 2 -- .../Settings/Sections/GraphicsSection.cs | 2 -- .../Sections/Input/BindingSettings.cs | 2 -- .../Sections/Input/KeyBindingPanel.cs | 4 +--- .../Sections/Input/RulesetBindingsSection.cs | 4 +--- .../Settings/Sections/InputSection.cs | 2 -- .../StableDirectoryLocationDialog.cs | 4 +--- .../StableDirectorySelectScreen.cs | 2 -- .../Online/AlertsAndPrivacySettings.cs | 2 -- .../Sections/Online/IntegrationSettings.cs | 4 +--- .../Settings/Sections/Online/WebSettings.cs | 2 -- .../Settings/Sections/OnlineSection.cs | 2 -- .../Overlays/Settings/Sections/SizeSlider.cs | 4 +--- .../Sections/UserInterface/GeneralSettings.cs | 2 -- .../UserInterface/SongSelectSettings.cs | 2 -- .../Settings/Sections/UserInterfaceSection.cs | 4 +--- .../Overlays/Settings/SettingsCheckbox.cs | 4 +--- .../Overlays/Settings/SettingsEnumDropdown.cs | 2 -- osu.Game/Overlays/Settings/SettingsFooter.cs | 4 +--- osu.Game/Overlays/Settings/SettingsHeader.cs | 2 -- .../Overlays/Settings/SettingsNumberBox.cs | 4 +--- osu.Game/Overlays/Settings/SettingsSidebar.cs | 2 -- osu.Game/Overlays/Settings/SettingsSlider.cs | 2 -- .../Overlays/Settings/SettingsSubsection.cs | 2 -- osu.Game/Overlays/Settings/SettingsTextBox.cs | 2 -- osu.Game/Overlays/Settings/SidebarButton.cs | 6 ++--- osu.Game/Overlays/TabControlOverlayHeader.cs | 2 -- osu.Game/Overlays/Toolbar/ClockDisplay.cs | 4 +--- .../Toolbar/ToolbarBeatmapListingButton.cs | 4 +--- osu.Game/Overlays/Toolbar/ToolbarButton.cs | 8 +++---- .../Toolbar/ToolbarChangelogButton.cs | 4 +--- .../Overlays/Toolbar/ToolbarChatButton.cs | 4 +--- .../Overlays/Toolbar/ToolbarHomeButton.cs | 2 -- .../Overlays/Toolbar/ToolbarNewsButton.cs | 2 -- .../Toolbar/ToolbarNotificationButton.cs | 2 -- .../Overlays/Toolbar/ToolbarRankingsButton.cs | 2 -- .../Toolbar/ToolbarRulesetTabButton.cs | 2 -- .../Overlays/Toolbar/ToolbarSettingsButton.cs | 2 -- .../Overlays/Toolbar/ToolbarSocialButton.cs | 4 +--- .../Overlays/Toolbar/ToolbarWikiButton.cs | 4 +--- osu.Game/Overlays/VersionManager.cs | 2 -- osu.Game/Overlays/Volume/MuteButton.cs | 2 -- osu.Game/Overlays/WaveOverlayContainer.cs | 2 -- .../Wiki/Markdown/WikiMarkdownContainer.cs | 4 +--- .../Wiki/Markdown/WikiMarkdownImage.cs | 4 +--- .../Wiki/Markdown/WikiMarkdownImageBlock.cs | 6 ++--- .../Wiki/Markdown/WikiNoticeContainer.cs | 6 ++--- .../Performance/HighPerformanceSession.cs | 4 +--- osu.Game/Properties/AssemblyInfo.cs | 2 -- .../Difficulty/PerformanceAttributes.cs | 2 -- .../Difficulty/PerformanceCalculator.cs | 4 +--- .../Difficulty/PerformanceDisplayAttribute.cs | 4 +--- osu.Game/Rulesets/Difficulty/Skills/Skill.cs | 4 +--- .../Difficulty/Skills/StrainDecaySkill.cs | 4 +--- .../Rulesets/Difficulty/Skills/StrainSkill.cs | 4 +--- osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 4 +--- .../Edit/DrawableEditorRulesetWrapper.cs | 10 ++++----- osu.Game/Rulesets/Edit/EditorToolboxGroup.cs | 4 +--- .../Edit/ExpandingToolboxContainer.cs | 4 +--- osu.Game/Rulesets/Edit/IBeatmapVerifier.cs | 4 +--- .../Rulesets/Edit/IDistanceSnapProvider.cs | 4 +--- .../Rulesets/Edit/IPositionSnapProvider.cs | 4 +--- osu.Game/Rulesets/Edit/SnapType.cs | 4 +--- .../Rulesets/Judgements/IgnoreJudgement.cs | 4 +--- osu.Game/Rulesets/Judgements/Judgement.cs | 2 -- .../Rulesets/Judgements/JudgementResult.cs | 4 +--- osu.Game/Rulesets/Objects/HitObjectParser.cs | 2 -- .../Objects/Legacy/Catch/ConvertHit.cs | 2 -- .../Objects/Legacy/Catch/ConvertSlider.cs | 2 -- .../Objects/Legacy/Catch/ConvertSpinner.cs | 2 -- .../Objects/Legacy/ConvertHitObject.cs | 4 +--- .../Legacy/Mania/ConvertHitObjectParser.cs | 2 -- .../Objects/Legacy/Mania/ConvertHold.cs | 2 -- .../Objects/Legacy/Mania/ConvertSpinner.cs | 2 -- .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 -- .../Objects/Legacy/Osu/ConvertSlider.cs | 2 -- .../Objects/Legacy/Osu/ConvertSpinner.cs | 2 -- .../Objects/Legacy/Taiko/ConvertSpinner.cs | 2 -- .../Rulesets/Objects/SliderEventGenerator.cs | 4 +--- osu.Game/Rulesets/Objects/SliderPath.cs | 4 +--- .../Objects/SyntheticHitObjectEntry.cs | 4 +--- .../Objects/Types/IHasDisplayColour.cs | 4 +--- osu.Game/Rulesets/Objects/Types/IHasPath.cs | 4 +--- .../Objects/Types/IHasPathWithRepeats.cs | 2 -- .../Rulesets/Objects/Types/IHasPosition.cs | 2 -- .../Rulesets/Objects/Types/IHasRepeats.cs | 2 -- osu.Game/Rulesets/RulesetLoadException.cs | 4 +--- .../Scoring/AccumulatingHealthProcessor.cs | 4 +--- .../Rulesets/Scoring/HitEventExtensions.cs | 4 +--- osu.Game/Rulesets/Scoring/HitWindows.cs | 2 -- .../Rulesets/UI/GameplayCursorContainer.cs | 4 +--- osu.Game/Rulesets/UI/IHitObjectContainer.cs | 4 +--- .../Rulesets/UI/IPooledHitObjectProvider.cs | 4 +--- osu.Game/Rulesets/UI/JudgementContainer.cs | 2 -- .../UI/PlayfieldAdjustmentContainer.cs | 4 +--- osu.Game/Rulesets/UI/PlayfieldBorder.cs | 2 -- osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs | 4 +--- .../Algorithms/ConstantScrollAlgorithm.cs | 2 -- .../Rulesets/UI/Scrolling/IScrollingInfo.cs | 2 -- .../UI/Scrolling/ScrollingPlayfield.cs | 6 ++--- osu.Game/Scoring/HitResultDisplayStatistic.cs | 4 +--- osu.Game/Scoring/IScoreInfo.cs | 4 +--- .../Scoring/Legacy/ScoreInfoExtensions.cs | 4 +--- osu.Game/Scoring/Score.cs | 4 +--- osu.Game/Scoring/ScoreRank.cs | 2 -- osu.Game/Screens/BackgroundScreenStack.cs | 4 +--- .../Backgrounds/BackgroundScreenBlack.cs | 2 -- .../Backgrounds/BackgroundScreenCustom.cs | 2 -- .../Components/BeatDivisorPresetCollection.cs | 4 +--- .../Components/CircularDistanceSnapGrid.cs | 12 +++++----- .../Components/EditorSelectionHandler.cs | 6 ++--- .../HitObjectOrderedSelectionContainer.cs | 6 ++--- .../Compose/Components/MoveSelectionEvent.cs | 4 +--- .../Components/RectangularPositionSnapGrid.cs | 4 +--- .../Components/Timeline/CentreMarker.cs | 2 -- .../Components/Timeline/TimelineButton.cs | 2 -- .../Timeline/TimelineControlPointDisplay.cs | 4 +--- .../Timeline/TimelineControlPointGroup.cs | 4 +--- .../Components/Timeline/TimelineDragBox.cs | 6 ++--- .../Timeline/TimelineTickDisplay.cs | 22 +++++++++---------- .../Components/Timeline/TimingPointPiece.cs | 4 +--- .../Timeline/ZoomableScrollContainer.cs | 6 ++--- .../Screens/Edit/Compose/IPlacementHandler.cs | 4 +--- osu.Game/Screens/Edit/EditorClipboard.cs | 4 +--- .../Edit/EditorRoundedScreenSettings.cs | 4 +--- osu.Game/Screens/Edit/EditorScreen.cs | 6 ++--- .../Edit/GameplayTest/EditorPlayerLoader.cs | 6 ++--- .../SaveBeforeGameplayTestDialog.cs | 4 +--- .../Screens/Edit/HitAnimationsMenuItem.cs | 4 +--- .../Edit/Verify/InterpretationSection.cs | 4 +--- osu.Game/Screens/Edit/Verify/IssueSettings.cs | 4 +--- .../Screens/Edit/WaveformOpacityMenuItem.cs | 4 +--- osu.Game/Screens/IHandlePresentBeatmap.cs | 4 +--- osu.Game/Screens/IHasSubScreenStack.cs | 4 +--- osu.Game/Screens/IOsuScreen.cs | 4 +--- osu.Game/Screens/Menu/ExitConfirmOverlay.cs | 4 +--- osu.Game/Screens/Menu/SongTicker.cs | 4 +--- osu.Game/Screens/Menu/StorageErrorDialog.cs | 6 ++--- .../BeatmapDetailAreaPlaylistTabItem.cs | 4 +--- .../OnlinePlay/Components/BeatmapTitle.cs | 4 +--- .../Components/DisableableTabControl.cs | 4 +--- .../OnlinePlay/Components/DrawableGameType.cs | 6 ++--- .../OnlinePlay/Components/OverlinedHeader.cs | 4 +--- .../Components/OverlinedPlaylistHeader.cs | 4 +--- .../Components/ParticipantsDisplay.cs | 4 +--- .../OnlinePlay/Components/ReadyButton.cs | 4 +--- .../Components/RoomPollingComponent.cs | 8 +++---- .../OnlinePlay/FooterButtonFreeMods.cs | 4 +--- .../OnlinePlay/IOnlinePlaySubScreen.cs | 4 +--- .../Lounge/Components/EndDateInfo.cs | 4 +--- .../Lounge/Components/MatchTypePill.cs | 4 +--- .../Lounge/Components/PillContainer.cs | 4 +--- .../Lounge/Components/PlaylistCountPill.cs | 4 +--- .../Lounge/Components/QueueModePill.cs | 4 +--- .../Components/RoomSpecialCategoryPill.cs | 6 ++--- .../Lounge/Components/RoomStatusFilter.cs | 4 +--- .../Lounge/Components/RoomStatusPill.cs | 6 ++--- .../Match/Components/CreateRoomButton.cs | 4 +--- .../Match/Components/MatchChatDisplay.cs | 8 +++---- .../OnlinePlay/Match/RoomBackgroundScreen.cs | 4 +--- .../Multiplayer/GameplayMatchScoreDisplay.cs | 4 +--- .../Match/Playlist/MultiplayerHistoryList.cs | 4 +--- .../Playlist/MultiplayerPlaylistTabControl.cs | 2 -- .../OnlinePlay/Multiplayer/Multiplayer.cs | 6 ++--- .../Multiplayer/MultiplayerResultsScreen.cs | 4 +--- .../Participants/ParticipantsListHeader.cs | 6 ++--- .../Spectate/MultiSpectatorPlayerLoader.cs | 4 +--- .../Multiplayer/Spectate/PlayerGrid.cs | 4 +--- .../Multiplayer/Spectate/PlayerGrid_Facade.cs | 4 +--- .../OnlinePlay/OnlinePlaySubScreenStack.cs | 4 +--- .../Playlists/CreatePlaylistsRoomButton.cs | 4 +--- .../Screens/OnlinePlay/Playlists/Playlists.cs | 4 +--- .../PlaylistsRoomSettingsPlaylist.cs | 4 +--- osu.Game/Screens/OsuScreenStack.cs | 4 +--- osu.Game/Screens/Play/Break/BlurredIcon.cs | 2 -- osu.Game/Screens/Play/Break/BreakArrows.cs | 2 -- osu.Game/Screens/Play/Break/BreakInfo.cs | 2 -- osu.Game/Screens/Play/Break/GlowIcon.cs | 2 -- .../Play/Break/RemainingTimeCounter.cs | 2 -- .../Play/HUD/DefaultAccuracyCounter.cs | 4 +--- .../Screens/Play/HUD/DefaultHealthDisplay.cs | 2 -- .../Screens/Play/HUD/DefaultScoreCounter.cs | 4 +--- osu.Game/Screens/Play/HUD/HealthDisplay.cs | 8 +++---- osu.Game/Screens/Play/HUD/ModDisplay.cs | 2 -- osu.Game/Screens/Play/HUD/ModFlowDisplay.cs | 4 +--- .../Screens/Play/HUD/PlayerSettingsOverlay.cs | 2 -- .../Screens/Play/HUD/UnstableRateCounter.cs | 6 ++--- osu.Game/Screens/Play/HotkeyExitOverlay.cs | 2 -- osu.Game/Screens/Play/HotkeyRetryOverlay.cs | 2 -- osu.Game/Screens/Play/ILocalUserPlayInfo.cs | 4 +--- osu.Game/Screens/Play/PlayerConfiguration.cs | 4 +--- .../Play/PlayerSettings/DiscussionSettings.cs | 2 -- .../Play/PlayerSettings/InputSettings.cs | 2 -- .../Play/PlayerSettings/PlaybackSettings.cs | 2 -- .../Play/PlayerSettings/PlayerSliderBar.cs | 4 +--- osu.Game/Screens/Play/ReplayPlayerLoader.cs | 4 +--- .../Screens/Play/SpectatorPlayerLoader.cs | 4 +--- .../Screens/Play/SpectatorResultsScreen.cs | 6 ++--- osu.Game/Screens/Ranking/AspectContainer.cs | 4 +--- .../ContractedPanelMiddleContent.cs | 6 ++--- .../Ranking/Expanded/Accuracy/RankNotch.cs | 4 +--- .../Expanded/Statistics/HitResultStatistic.cs | 4 +--- .../Expanded/Statistics/StatisticCounter.cs | 2 -- osu.Game/Screens/Ranking/RetryButton.cs | 6 ++--- .../Ranking/ScorePanelTrackingContainer.cs | 4 +--- .../Ranking/Statistics/AverageHitError.cs | 4 +--- .../Ranking/Statistics/StatisticContainer.cs | 4 +--- .../Ranking/Statistics/StatisticItem.cs | 4 +--- .../Ranking/Statistics/UnstableRate.cs | 4 +--- .../Select/BeatmapDetailAreaDetailTabItem.cs | 4 +--- .../BeatmapDetailAreaLeaderboardTabItem.cs | 4 +--- .../Select/BeatmapInfoWedgeBackground.cs | 2 -- osu.Game/Screens/Select/Filter/GroupMode.cs | 2 -- osu.Game/Screens/Select/Filter/SortMode.cs | 2 -- .../Screens/Select/FooterButtonOptions.cs | 4 +--- .../Leaderboards/BeatmapLeaderboardScope.cs | 2 -- .../Select/Options/BeatmapOptionsButton.cs | 2 -- .../Spectate/SpectatorGameplayState.cs | 4 +--- osu.Game/Screens/StartupScreen.cs | 4 +--- .../Skinning/LegacyManiaSkinConfiguration.cs | 4 +--- osu.Game/Storyboards/CommandLoop.cs | 2 -- osu.Game/Storyboards/CommandTimelineGroup.cs | 2 -- osu.Game/Storyboards/CommandTrigger.cs | 2 -- .../Drawables/DrawableStoryboardLayer.cs | 2 -- .../Drawables/DrawableStoryboardSample.cs | 6 ++--- .../Drawables/DrawableStoryboardSprite.cs | 4 +--- .../Drawables/DrawablesExtensions.cs | 2 -- osu.Game/Storyboards/Drawables/IFlippable.cs | 2 -- .../Storyboards/Drawables/IVectorScalable.cs | 4 +--- osu.Game/Storyboards/IStoryboardElement.cs | 2 -- .../IStoryboardElementWithDuration.cs | 4 +--- osu.Game/Storyboards/StoryboardExtensions.cs | 4 +--- osu.Game/Storyboards/StoryboardLayer.cs | 2 -- osu.Game/Storyboards/StoryboardSample.cs | 2 -- osu.Game/Storyboards/StoryboardVideo.cs | 2 -- osu.Game/Storyboards/StoryboardVideoLayer.cs | 4 +--- .../Tests/Beatmaps/LegacyModConversionTest.cs | 2 -- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 2 -- osu.Game/Tests/CleanRunHeadlessGameHost.cs | 2 -- osu.Game/Tests/OsuTestBrowser.cs | 2 -- .../Visual/DependencyProvidingContainer.cs | 4 +--- osu.Game/Tests/Visual/ModPerfectTestScene.cs | 4 +--- .../IMultiplayerTestSceneDependencies.cs | 4 +--- .../MultiplayerTestSceneDependencies.cs | 4 +--- .../IOnlinePlayTestSceneDependencies.cs | 4 +--- .../OnlinePlayTestSceneDependencies.cs | 4 +--- osu.Game/Tests/Visual/OsuGridTestScene.cs | 4 +--- .../Visual/OsuManualInputManagerTestScene.cs | 2 -- osu.Game/Tests/Visual/ScreenTestScene.cs | 2 -- osu.Game/Tests/Visual/TestReplayPlayer.cs | 4 +--- osu.Game/Tests/VisualTestRunner.cs | 2 -- osu.Game/Users/CountryStatistics.cs | 2 -- osu.Game/Users/Drawables/DrawableFlag.cs | 2 -- osu.Game/Users/UserActivity.cs | 2 -- osu.Game/Users/UserBrickPanel.cs | 2 -- osu.Game/Users/UserGridPanel.cs | 2 -- osu.Game/Users/UserListPanel.cs | 2 -- osu.Game/Users/UserStatus.cs | 4 +--- osu.Game/Utils/LimitedCapacityQueue.cs | 4 +--- osu.iOS/OsuGameIOS.cs | 2 -- 1072 files changed, 786 insertions(+), 2930 deletions(-) diff --git a/osu.Android/GameplayScreenRotationLocker.cs b/osu.Android/GameplayScreenRotationLocker.cs index 3c39a820cc..d77b24722a 100644 --- a/osu.Android/GameplayScreenRotationLocker.cs +++ b/osu.Android/GameplayScreenRotationLocker.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. -#nullable disable - using Android.Content.PM; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -16,7 +14,7 @@ namespace osu.Android private Bindable localUserPlaying; [Resolved] - private OsuGameActivity gameActivity { get; set; } + private OsuGameActivity gameActivity { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuGame game) diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index f0a6e4733c..81b218436e 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index 0227d2aec2..96f81c209c 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.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. -#nullable disable - using System; using Android.App; using Microsoft.Maui.Devices; diff --git a/osu.Android/Properties/AssemblyInfo.cs b/osu.Android/Properties/AssemblyInfo.cs index f65b1b239f..1632087fb1 100644 --- a/osu.Android/Properties/AssemblyInfo.cs +++ b/osu.Android/Properties/AssemblyInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Android; using Android.App; diff --git a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs index 64c71c9ecd..d8b729576d 100644 --- a/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Catch.Tests.Android/MainActivity.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. -#nullable disable - using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index b6cb351c1e..baca8166d1 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.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. -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs index cf030f6e13..880316f177 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Difficulty; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs index b9d6f28228..b74120fa3c 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs index f30b216d8d..72011042bc 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinColourDecodingTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.IO.Stores; using osu.Game.Rulesets.Catch.Skinning; diff --git a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs index 2af851a561..4306cc7d9d 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchSkinnableTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs index 39508359a4..058d4eb6b9 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchEditorTestSceneContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs index 033dca587e..6dfc74e75c 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/CatchSelectionBlueprintTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs index 2db4102513..ed37ff4ef3 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneBananaShowerPlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs index 1e057cf3fb..8052b8e3f7 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneCatchDistanceSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs index 5593f3d319..c9ba127569 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneEditor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs index 93b24d92fb..75d3c3753a 100644 --- a/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch.Tests/Editor/TestSceneFruitPlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs b/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs index 0de992c1df..95b4fdc07e 100644 --- a/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/JuiceStreamPathTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index f21825668f..3261fb656e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index 402f8f548d..569c69a633 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs index 05d3361dc3..a44575a46e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs index 01cce88d9d..a82edc1df8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayer.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. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs index 4c1ba33aa2..5406230359 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchPlayerLegacySkin.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs index cbf900ebc0..1d2ea4610d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchReplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index c8979381fe..af38956002 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index 007f309f3f..23fcd49863 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Catch.Mods; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs index 223c4e57fc..fda4136a37 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitObjects.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 995daaceb1..de3d9d6530 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs index 4b2873e0a8..1534d91e77 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitVisualChange.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index f8c43a221e..3c222662f5 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index c91f07891c..c31a7ca99f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs index aa66fc8741..871da28142 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -21,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Tests public partial class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest { [Resolved] - private AudioManager audio { get; set; } + private AudioManager audio { get; set; } = null!; [BackgroundDependencyLoader] private void load(OsuConfigManager config) diff --git a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs index 789fc9e22d..518071fd49 100644 --- a/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Mania.Tests.Android/MainActivity.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. -#nullable disable - using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 2fda012f07..281dec3c79 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs index 0a21098d0d..762238be47 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneEditor.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs index 4b332c3faa..b79bcb7682 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNotePlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs index a65f949cec..c75095237e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneHoldNoteSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs index aca555552f..fbc0ed1785 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaBeatSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs index a1f4b234c4..8f623d1fc6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneManiaComposeScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor public partial class TestSceneManiaComposeScreen : EditorClockTestScene { [Resolved] - private SkinManager skins { get; set; } + private SkinManager skins { get; set; } = null!; [Cached] private EditorClipboard clipboard = new EditorClipboard(); diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs index 86e87e7486..9d56d31329 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/TestSceneNoteSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs index 4ae6cb9c7c..7b0171a9ee 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index c85583c1fd..ec249f6ae9 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.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. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs index 9dee861e66..3a9639e04d 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs index 7d1a934456..641631d05e 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyReplayTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Replays; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs index 3bd654e75e..ff1f9e6894 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSpecialColumnTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Mania.Beatmaps; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs index 0c55cebf0d..465d4a49f0 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ColumnTestContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs index 25e120edc5..dd494dfc82 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaHitObjectTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs index 30bd600d9d..ba0c97a121 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/ManiaSkinnableTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs index 3881aae22e..47923d0733 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs index 9cccc2dd86..d4bbc8acb6 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneColumnHitObjectArea.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs index 2a9727dbd4..c993ba0e0a 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using osu.Framework.Extensions; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs index 30dd83123d..483c468c1e 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHitExplosion.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs index 0b9ca42af8..a9d18ba401 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneHoldNote.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs index d049d88ea8..2c978c1148 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneNote.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs index 6485cbb76b..29c47ca93a 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestScenePlayfield.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs index 25e24929c9..d44a38fdec 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs index 0557a201c8..11c3ab3cd3 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneStageBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.UI.Components; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 9fdd93bcc9..e3846e8213 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs index b96fab9ec0..cb9fcca5b0 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneColumn.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. -#nullable disable - using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs index 7021c081b7..36ecbdb098 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectSamples.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Reflection; using NUnit.Framework; using osu.Framework.IO.Stores; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs index 4e50fd924c..073bef5061 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaPlayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs index f497c88bcc..2a8dc715f9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestScenePlayfieldCoveringContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index b5655a4579..28cdf8907e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 630fdf7ae2..2265d3d347 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 912cac4fe4..27cb681300 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs index bf54dc3179..e4a28167ec 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.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. -#nullable disable - using System; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 931673f337..3d3c35773b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.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. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs index 898b558eb3..48b3ce010f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.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. -#nullable disable - using System; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 63e61f17e3..bbb31ab98c 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs index 01474e6e00..64f8b026c2 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.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. -#nullable disable - using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 440dec82af..d9f9479247 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs index df95654319..a67d38b29f 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs index 2c7c84de97..06c825e37d 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Utils; using osu.Game.Rulesets.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs b/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs index 262247e244..e9d26b4aa1 100644 --- a/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs +++ b/osu.Game.Rulesets.Mania/DualStageVariantGenerator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index be1cc9a7fe..6a12ec5088 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs index ef7ce9073c..48dde29a9f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 381af8be7f..cb275a9aa4 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -23,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private readonly EditNotePiece tailPiece; [Resolved] - private IScrollingInfo scrollingInfo { get; set; } + private IScrollingInfo scrollingInfo { get; set; } = null!; protected override bool IsValidForPlacement => HitObject.Duration > 0; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index cf4bca0030..4c356367d3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; @@ -17,10 +15,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints where T : ManiaHitObject { [Resolved] - private Playfield playfield { get; set; } + private Playfield playfield { get; set; } = null!; [Resolved] - private IScrollingInfo scrollingInfo { get; set; } + private IScrollingInfo scrollingInfo { get; set; } = null!; protected ScrollingHitObjectContainer HitObjectContainer => ((ManiaPlayfield)playfield).GetColumn(HitObject.Column).HitObjectContainer; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index d77abca350..b3ec3ef3e4 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index a1392f09fa..01c7bd502a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs index 4a070e70b4..1e9085bb2f 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; using osuTK; diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index 960a08eeeb..99e1ce04b1 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 2d4b5f718c..9cc84450cc 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -45,13 +43,13 @@ namespace osu.Game.Rulesets.Mania.Edit } [Resolved] - private EditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } = null!; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Resolved] - private BindableBeatDivisor beatDivisor { get; set; } + private BindableBeatDivisor beatDivisor { get; set; } = null!; private readonly List grids = new List(); @@ -169,7 +167,7 @@ namespace osu.Game.Rulesets.Mania.Edit private partial class DrawableGridLine : DrawableHitObject { [Resolved] - private IScrollingInfo scrollingInfo { get; set; } + private IScrollingInfo scrollingInfo { get; set; } = null!; private readonly IBindable direction = new Bindable(); diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index 05d8ccc73f..fb3e2d494e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs index 0a697ca986..77e372d1d6 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditorPlayfield.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. -#nullable disable - using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 5e6ae9bb11..8fdbada04f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using osu.Framework.Allocation; @@ -16,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Edit public partial class ManiaSelectionHandler : EditorSelectionHandler { [Resolved] - private HitObjectComposer composer { get; set; } + private HitObjectComposer composer { get; set; } = null!; public override bool HandleMovement(MoveSelectionEvent moveEvent) { diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index 179f920c2f..08ee05ad3f 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 4b94198c4d..ae9e8bd287 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Judgements diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 32f9689d7e..d28b7bdf58 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index 9ad24d6256..a41e72660b 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 9117c60dcd..e5c5260a49 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index ebff5cf4e9..25ad6b997d 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 578b46a7aa..0035960c63 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index d6dc25079a..71a594c6ce 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs index 1bc20f7ef3..ca1f7036c7 100644 --- a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.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. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs index 16f7af0d0a..e63a037ca9 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHealthProcessor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs index c46a1b5ab6..289f8a00ef 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaHitWindows.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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania.Scoring diff --git a/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs b/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs index 765fd11dd5..44ffeb5ec2 100644 --- a/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs +++ b/osu.Game.Rulesets.Mania/SingleStageVariantGenerator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index c93be91a84..91e0f2c19b 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs index ef34fc04ee..a5c6f10907 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/DefaultStageBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs index 41b2dba173..2ad6e4f076 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/HitObjectArea.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs b/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs index 74ddceeeef..bbae055b84 100644 --- a/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/IHitExplosion.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Mania.UI diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs index d4621ab8f3..1183b616f5 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfieldAdjustmentContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs index 56ac38a737..65dc43af0b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaReplayRecorder.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs index c39e21bace..b6e8fb7191 100644 --- a/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs +++ b/osu.Game.Rulesets.Mania/UI/OrderedHitPolicy.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mania.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs index 46cba01771..92f471e36b 100644 --- a/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs +++ b/osu.Game.Rulesets.Mania/UI/PlayfieldCoveringWrapper.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs index 9b4226d5b6..46c60f06a5 100644 --- a/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Osu.Tests.Android/MainActivity.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. -#nullable disable - using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs index 587bd2de44..a49afd82f3 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneHitCirclePlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs index 41a099e6e9..03ab7ebbf7 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditor.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. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs index 59146bc05e..d14e593587 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorGrids.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs index bb29504ec3..37a109de18 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorSelectInvalidPath.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs index 6378097800..0e8673319e 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerPlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs index c899f58c5a..8468995e86 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSpinnerSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index bee46da1ba..4c11efcc7c 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.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. -#nullable disable - using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index 7e995f2dde..cda330afe5 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs index b4727b3c02..05366e9444 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index a2ab7b564c..e370807bca 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.IO; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs index 5366a86bc0..323df75daf 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestPlayfieldBorder.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index ff71300733..5da54f8fcf 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Tests public partial class TestSceneDrawableJudgement : OsuSkinnableTestScene { [Resolved] - private OsuConfigManager config { get; set; } + private OsuConfigManager config { get; set; } = null!; private readonly List> pools; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index 50f9c5e775..0314afc1ac 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Tests private int depthIndex; [Resolved] - private OsuConfigManager config { get; set; } + private OsuConfigManager config { get; set; } = null!; [Test] public void TestHits() diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs index 34c67e8b9c..b7c3097864 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleComboChange.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index b3498b9651..c113993d31 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 93f1123341..bfb31d5b31 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs index 0d3fd77568..c37660831b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs index 1f0e264cf7..30d9aff83a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneNoSpinnerStacking.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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs index 4d0b2cc406..61cc10f284 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuHitObjectSamples.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Reflection; using NUnit.Framework; using osu.Framework.IO.Stores; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs index 53c4e49807..44efc94d7b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuPlayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs index b66974d4b1..0bb27cff0f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneResumeOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs index bee7831625..0599517899 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneShaking.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Threading; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs index dc8842a20a..863cc24920 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderComboChange.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index eb13995ad0..671285831f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index 1aaba23e56..42cbb96813 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Osu.Mods; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index df146a9511..a5282877ee 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index d03ee81f0d..9e786caf0c 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.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. -#nullable disable - using osuTK; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index da66669550..f51f04bf87 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs index 6d1b4d1a15..cf35b08822 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/AimEvaluator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs index dabbfcd2fb..5cb5a8f934 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/FlashlightEvaluator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs index 3bec2346ce..05939bb3ab 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/RhythmEvaluator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs index c98f875eb5..1ae500ec78 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs index efb3ade220..0aeaf7669f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.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. -#nullable disable - using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 30b56ff769..b31f4ff519 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 6aea00fd35..5215920ea0 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 38e0e5b677..3f6b22bbb1 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs index 40448c444c..3d6d3f99c1 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.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. -#nullable disable - using System; using System.Linq; using osu.Game.Rulesets.Difficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index d6683ade05..15b20a5572 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.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. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Skills; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index efe0e136bf..40aac013ab 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs index 41ab5a81b8..cdd11c53d2 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/BlueprintPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 1fed19da03..670e98ca50 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index 26d18c7a17..20ad99baa2 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index 1b3e7f3a8f..0608f8c929 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index d6409279a4..bdd19f9106 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -17,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints where T : OsuHitObject { [Resolved] - private EditorClock editorClock { get; set; } + private EditorClock editorClock { get; set; } = null!; protected new DrawableOsuHitObject DrawableObject => (DrawableOsuHitObject)base.DrawableObject; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 68a44eb2f8..075e9e6aa1 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs index 3341a632c1..d47cf6bf23 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index cc58acdc80..17e838b4e7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index a80ec68c10..b273292f8a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs index 69187875d7..c41ae10b2e 100644 --- a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs index 2c67f0bf97..325e9ed4cb 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBeatmapVerifier.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index 173a664902..ed149d004c 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs index 3234b03a3e..efc6668ebf 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuRectangularPositionSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; @@ -22,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit private int currentGridSizeIndex = grid_sizes.Length - 1; [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; public OsuRectangularPositionSnapGrid() : base(OsuPlayfield.BASE_SIZE / 2) diff --git a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs index 0a3fc176ad..676205c8d7 100644 --- a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs index 3c0cf34010..c8160617c9 100644 --- a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs index 9762c676c5..556eb94f38 100644 --- a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs index 5f9faaceb2..7a9a868b9b 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuHitCircleJudgementResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs index 1bdb74cd3b..7c7f16779e 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuIgnoreJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index a5503d3273..1a88e2a8b2 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs index 50d73fa19d..3bc2cacb43 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs index 4229c87b58..941cb667cf 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSpinnerJudgementResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs index 270c1f31fb..21b024a720 100644 --- a/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/SliderTickJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Judgements diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index d588127cb9..52edfb1422 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.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. -#nullable disable - using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs index f1f4ec983e..889a9bd816 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerBonusTick.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Rulesets.Osu.Objects.Drawables { public partial class DrawableSpinnerBonusTick : DrawableSpinnerTick diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs index 9e8035a1ee..cae2a7c36d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.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. -#nullable disable - using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index 5f43e57ed8..d652db0fd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 7b98fc48e0..fd5741698a 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.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. -#nullable disable - using System; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs index f52c3ab382..ddbbb300ca 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs index 2a84b04030..73c222653e 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderHeadCircle.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs index 7b9316f8ac..cca86361c2 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 87c8117b6b..b4574791d2 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 676ff62455..74ec4d6eb3 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index ba0981e781..b800b03c92 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs index 00ceccaf7b..8d53100529 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerBonusTick.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs index c890f3771b..7989c9b7ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs index 7fffb1871f..c842874635 100644 --- a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.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. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs b/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs index 0dac3307c2..b509796742 100644 --- a/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs +++ b/osu.Game.Rulesets.Osu/UI/IHitPolicy.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs index b45d552c7f..2c3a77a6bc 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfieldAdjustmentContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.UI; diff --git a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs index 66a4f467a9..545b31bf29 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuReplayRecorder.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs index aa4cd0af14..e936c24c08 100644 --- a/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs +++ b/osu.Game.Rulesets.Osu/Utils/OsuHitObjectGenerationUtils.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs index a55b461876..e4f4bbfd53 100644 --- a/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.cs +++ b/osu.Game.Rulesets.Taiko.Tests.Android/MainActivity.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. -#nullable disable - using Android.App; using osu.Framework.Android; using osu.Game.Tests; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs index 157a96eec8..68517166e7 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Input.Events; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs index 747c599721..878f451fd2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestStrongHit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Input.Events; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs index 3ee9171e7e..822219db29 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneEditor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs index 93b26624de..af7db2251b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoEditorSaving.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Rulesets.Taiko.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs index ed73730c4a..64a29ce866 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Editor/TestSceneTaikoHitObjectComposer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs index 38530282b7..b11501535f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TaikoSkinnableTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests.Skinning diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs index 7fd90685e3..497c788ce8 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableBarLine.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs index 3b2f4f2fb2..bef8be4cb5 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableDrumRoll.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs index 9567eac80f..863ca4a07d 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableHit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs index 924f903ce9..f8dd53c834 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneHitExplosion.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs index cb5d0d1f91..3c6319ddf9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneInputDrum.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs index 5f98f2f27a..fbdc4132ec 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneKiaiHitExplosion.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs index eb2762cb2d..c89e2b727b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoPlayfield.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs index 826cf2acab..2535058c29 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneTaikoScroller.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Testing; using osu.Framework.Timing; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 781a686700..a528a7f9d1 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.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. -#nullable disable - using System; using System.Collections.Generic; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs index 5685ac0f60..09d6540f72 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs index c86f8cb8d2..541987d63e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs index 00292d5473..44bc611d92 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneBarLineApplication.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs index b01bd11149..0a178ec69f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneDrumRollApplication.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs index 301620edc9..24aa4f2ef0 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHitApplication.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index 91209e5ec5..fd850a9a67 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs index dcdda6014c..2429b71095 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSampleOutput.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Testing; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs index 8c903f748c..d2cf691c7f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Taiko.Tests diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index 08c06b08f2..9e45197b04 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs index 6ff5cdf7e5..41fe63a553 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 1c2e7abafe..dddd1e3c5a 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs index ff187a133a..e76af13686 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs index d04c028fec..e528c70699 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.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. -#nullable disable - using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 24b5f5939a..8e988c4154 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs index b61c13a2df..b12c0ca29d 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.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. -#nullable disable - using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 2d1b2903c9..a193bacde5 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs index 4b4e2b5847..2f3c722fda 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/DrumRollPlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs index 84bc547372..3401f944e4 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/HitPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs index af02522a05..a56f92a026 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/LengthPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs index 2080293428..9b5ef640d7 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/SwellPlacementBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Edit.Blueprints diff --git a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs index 34695cbdd6..93b7c7061b 100644 --- a/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Taiko/Edit/Blueprints/TaikoSelectionBlueprint.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs index acb17fc455..f332441875 100644 --- a/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/DrumRollCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs index e52dae4b0c..fa50841893 100644 --- a/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/HitCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs index dd0ff61c10..4d4ee8effe 100644 --- a/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs +++ b/osu.Game.Rulesets.Taiko/Edit/SwellCompositionTool.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs index 6be22f3af0..027723c02c 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoBlueprintContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs index b727c0a61b..7ab8a54b02 100644 --- a/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs +++ b/osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index de56c76f56..4fc455fb23 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index f8e3303752..e272c1a4ef 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index bafe7dfbaf..1fc50c8751 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index 146621997d..d22ac6bf5e 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index d2eba0eb54..46b3f13501 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs index 0cd265ecab..a039ce3407 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 4ea30453d1..6ee29fa014 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 206e8ecb5a..eb333d9ec5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index ec23079ed9..156e890607 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.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. -#nullable disable - using System.Linq; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs index 18f47b7cff..302f940ef4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/IgnoreHit.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. -#nullable disable - using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs index 316115f44d..14cbe338ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongNestedHitObject.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 9ad783ba7e..a8db8df021 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.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. -#nullable disable - using System.Threading; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 43830cb528..41fb9cac7e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 3aba5c571b..1a1fde1990 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs index 479ad8369a..228179f94b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoStrongableHitObject.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using System.Threading; using osu.Framework.Bindables; diff --git a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs index 5b66e18a6d..ca7d04876e 100644 --- a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.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. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs index 7c70beb0a4..d75906f3aa 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs index 896af24772..cf806c0c97 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoHitWindows.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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Scoring diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index ca06a0a77e..4292d461bf 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index bdb947fbb4..ab43a6766c 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.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. -#nullable disable - using System.Reflection; using Android.App; using Android.OS; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs index fac5e098b9..5d9049ead7 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs index c1c9e0d118..39bb616563 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyDecoderTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps.Formats; diff --git a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs index 8f20fd7a68..5e37f01c81 100644 --- a/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/LineBufferedReaderTest.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. -#nullable disable - using System; using System.IO; using System.Text; diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 04eb9a3fa2..810ea5dbd0 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.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. -#nullable disable - using System.IO; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs index d30ab3dea1..a26c8121dd 100644 --- a/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs +++ b/osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs b/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs index b4a205b478..f3c05d8970 100644 --- a/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs +++ b/osu.Game.Tests/Beatmaps/ToStringFormattingTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Models; diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index 9079ecdc48..d034e69957 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs index e7fdb52d2f..b237556d11 100644 --- a/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs +++ b/osu.Game.Tests/Database/LegacyBeatmapImporterTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs index 769ca1f9a9..d198ef5074 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectSamples.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.IO.Stores; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs index a261185473..1cf72cf937 100644 --- a/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneScoreProcessor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/ImportTest.cs b/osu.Game.Tests/ImportTest.cs index 9e2c9cd7e0..3f0f8a4f14 100644 --- a/osu.Game.Tests/ImportTest.cs +++ b/osu.Game.Tests/ImportTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs index 3c296b2ff5..6b43ab83c5 100644 --- a/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs +++ b/osu.Game.Tests/Input/ConfineMouseTrackerTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -18,7 +16,7 @@ namespace osu.Game.Tests.Input public partial class ConfineMouseTrackerTest : OsuGameTestScene { [Resolved] - private FrameworkConfigManager frameworkConfigManager { get; set; } + private FrameworkConfigManager frameworkConfigManager { get; set; } = null!; [TestCase(WindowMode.Windowed)] [TestCase(WindowMode.Borderless)] diff --git a/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs b/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs index d01eaca714..9926acf772 100644 --- a/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.cs +++ b/osu.Game.Tests/Localisation/BeatmapMetadataRomanisationTest.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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs index e7827a7398..0f5c13ca0e 100644 --- a/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs +++ b/osu.Game.Tests/NonVisual/BarLineGeneratorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Utils; diff --git a/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs b/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs index 8ebf34b1ca..8a53759323 100644 --- a/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs +++ b/osu.Game.Tests/NonVisual/ClosestBeatDivisorTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs index a2ded643fa..2d5d425ee8 100644 --- a/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ControlPointInfoTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 6637d640b2..6b1b883ce7 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs index 4d2fc53bc3..a12658bd8b 100644 --- a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs +++ b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Utils; diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index ae6a76f6cd..b4bbe274a5 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs b/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs index b589f7c9f1..664a499cc3 100644 --- a/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs +++ b/osu.Game.Tests/NonVisual/PeriodTrackerTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs b/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs index 8654abd49d..335e7d25a2 100644 --- a/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs +++ b/osu.Game.Tests/NonVisual/RulesetInfoOrderingTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/NonVisual/ScoreInfoTest.cs b/osu.Game.Tests/NonVisual/ScoreInfoTest.cs index dcc4f91dba..ad3b5b6f66 100644 --- a/osu.Game.Tests/NonVisual/ScoreInfoTest.cs +++ b/osu.Game.Tests/NonVisual/ScoreInfoTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Online.API; using osu.Game.Rulesets.Mania; diff --git a/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs index 861e342cdb..10d592364d 100644 --- a/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs +++ b/osu.Game.Tests/NonVisual/TimeDisplayExtensionTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Extensions; diff --git a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs index 13f1ed5c57..e4118a23b4 100644 --- a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs +++ b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Online.Chat; diff --git a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs index aea579a82d..c440f375fd 100644 --- a/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs +++ b/osu.Game.Tests/Online/TestMultiplayerMessagePackSerialization.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using MessagePack; using NUnit.Framework; using osu.Game.Online; diff --git a/osu.Game.Tests/Online/TestSoloScoreInfoJsonSerialization.cs b/osu.Game.Tests/Online/TestSoloScoreInfoJsonSerialization.cs index 8ff0b67b5b..19bc96c677 100644 --- a/osu.Game.Tests/Online/TestSoloScoreInfoJsonSerialization.cs +++ b/osu.Game.Tests/Online/TestSoloScoreInfoJsonSerialization.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; using NUnit.Framework; using osu.Game.IO.Serialization; diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs index 73ed2bb868..274681b413 100644 --- a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs +++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs index d44fd786d7..5aa07260ef 100644 --- a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs +++ b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Game.Scoring; diff --git a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs index 0c25934d52..1c1ebe271e 100644 --- a/osu.Game.Tests/Skins/IO/ImportSkinTest.cs +++ b/osu.Game.Tests/Skins/IO/ImportSkinTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.IO; using System.Linq; diff --git a/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs index 6da335a9b7..b96bf09255 100644 --- a/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs +++ b/osu.Game.Tests/Skins/LegacyManiaSkinDecoderTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.IO; using osu.Game.Skinning; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs index 9f3e36ad76..9e5bd53b13 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCardDifficultyList.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs index 8a11d60875..88e47ea560 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapSetOnlineStatusPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs index 55a2efa89d..7f07563dfd 100644 --- a/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs +++ b/osu.Game.Tests/Visual/Colours/TestSceneStarDifficultyColours.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -19,7 +17,7 @@ namespace osu.Game.Tests.Visual.Colours public partial class TestSceneStarDifficultyColours : OsuTestScene { [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Test] public void TestColours() diff --git a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs index 8b598a6a24..fdb3513e66 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs index e11d2e9dbf..2a822b3f1f 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorComposeRadioButtons.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs index 699b99c57f..dbcf66f005 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorMenuBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs index a9d054881b..c0d64f4030 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs index b2b3dd9632..da4f159cae 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSeeking.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs index f255dd08a8..ddca2f8553 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSummaryTimeline.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs index c874b39028..c78f50c821 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectDifficultyPointAdjustments.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using Humanizer; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index b0b51a5dbd..29de0bff79 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using System.Collections.Generic; using Humanizer; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs index c0e681b8b4..534b813ddc 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneSetupScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs index b63296a48d..79ca8ee20c 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineBlueprintContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Edit.Compose.Components.Timeline; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs index 08e036248b..7a5243f6e8 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineHitObjectBlueprint.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs index 41fb3ed8b9..1376ba23fb 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineTickDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs index 19f4678c15..b493845ad4 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs index 7ff059ff77..7252fbc474 100644 --- a/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs +++ b/osu.Game.Tests/Visual/Gameplay/OsuPlayerTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index 6cb1101173..b251253b7c 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index e779c6c1cb..6297b062dd 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using osu.Game.Rulesets; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 22f7111f68..f978653f2a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs index 626406e4d2..71ed0a14a2 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneMedalOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Overlays; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs index 84334ba0a9..0e03f253a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneNightcoreBeatContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Beatmaps.Timing; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs index 2ae5e6f998..515bc09bbb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditorComponentsList.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs index 6f079778c5..59a1f938e6 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableAccuracyCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs index 93fa953ef4..0c351a93bb 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableComboCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs index 7f6c9d7804..b4ebb7c410 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableHealthDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs index 2cb3303dd6..7079b93d3e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableScoreCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs index 1c09c29748..f1ee5cc414 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Screens; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs index 699c8ea20a..b002e90bb0 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneStarCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs index cb5631e599..1d85643adf 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneUnknownMod.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index 45e5a7c270..fb82b0df80 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs index 0c024248ea..c0ced9057a 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.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. -#nullable disable - using NUnit.Framework; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs index 23373892d1..e8859400d5 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs index 2ccf184525..cb4a52a3b9 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneIntroWelcome.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs index e5e092b382..4f01dcffd9 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSideOverlays.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs index c54c66df7e..e4add64da2 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneSongTicker.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs index 49256c7a01..f4732234a7 100644 --- a/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs +++ b/osu.Game.Tests/Visual/Mods/TestSceneModFailCondition.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs index 63a0ada3dc..24d1b51ff8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Online.API; using osu.Game.Online.Rooms; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index defb3006cc..ea8fe8873d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Online.API; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs index 3d85a47ca9..46d409e6f1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiHeader.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index a612167d57..bafe373d57 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 48f74cf308..37662ffce8 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Game.Online.Multiplayer; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs index d636373fbd..c2d3b17ccb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchFooter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index aaf1a850af..d5f53bc354 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using Moq; diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs index e46ae978d7..b53a61f881 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs index 64ea6003bc..c6d67f2bc6 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneButtonSystemNavigation.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Testing; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs index bd75825da2..1633a778ab 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneEditDefaultSkin.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs index f885c2f44c..0bfe02cb16 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupBeatmapSetDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs index 621dabe869..d70eaf16f6 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneStartupRuleset.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Development; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs index c32aa7f5f9..820df02b66 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Utils; using osu.Game.Configuration; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs index 36f8d2d9bd..ccd3d7f4d6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index d9763ef6c8..60fb6b8c86 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -39,7 +37,7 @@ namespace osu.Game.Tests.Visual.Online } [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; [SetUp] public void SetUp() => Schedule(() => SelectedMods.Value = Array.Empty()); diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs index 96996db940..fbd3b3a728 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogSupporterPromo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs index 43d80ee0ac..89b8a8c079 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsHeader.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs index 504be45b44..9407941da6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDashboardOverlay.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. -#nullable disable - using NUnit.Framework; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs index 90ec3160d8..84f245afb6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneExternalLinkButton.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneGraph.cs index 357ed7548c..4f19003638 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneGraph.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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs index a58845ca7e..5c726bd69e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHomeNewsPanel.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs index 0231775189..4c67f778a2 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneLeaderboardScopeSelector.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. -#nullable disable - using osu.Game.Overlays.BeatmapSet; using osu.Framework.Graphics; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs index 001e6d925e..2d91df8a6d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNewsCard.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNewsCard.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Overlays.News; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs index ecfa76f395..f332575fb4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapListingOverlay.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. -#nullable disable - using osu.Game.Overlays; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs index 01b0b39661..3a4d0b97db 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineBeatmapSetOverlay.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. -#nullable disable - using NUnit.Framework; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs index 6c8430e955..df29b33f17 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneOnlineViewContainer.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs index dfefcd735e..3b38cf47d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsCountryFilter.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Rankings; diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 5aef91bef1..eb2a451c9b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs index 4cbcaaac85..5ce82a8766 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSpotlightsLayout.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs index 8af87dd597..cbd8ffa91c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneTotalCommentsCounter.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Bindables; using osu.Game.Overlays.Comments; diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs index 8876f0fd3b..9967be73e8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMainPage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs index c4a1200cb1..3b60c28dc0 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsParticipantsList.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs index 71e284ecfe..891dd3bb1a 100644 --- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.cs +++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsScreen.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. -#nullable disable - using NUnit.Framework; namespace osu.Game.Tests.Visual.Playlists diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs index bf18bd3e51..03b168c72c 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using NUnit.Framework; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs index e92e74598d..3004cb8a0c 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs index be7be6d4f1..27d66ea2a2 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs index ce6973aacf..3ef0ffc13a 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneDirectorySelector.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Tests.Visual.UserInterface; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs index f61e3ca557..e8f74a2f1b 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneFileSelector.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,7 +14,7 @@ namespace osu.Game.Tests.Visual.Settings public partial class TestSceneFileSelector : ThemeComparisonTestScene { [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Test] public void TestJpgFilesOnly() diff --git a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs index 91320fdb1c..22f185cbd3 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneMigrationScreens.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.IO; using System.Threading; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs index 30811bab32..309438e51c 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsSource.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs index 46a26d2e98..fa4981c137 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapOptionsOverlay.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 0476198e41..30f1803795 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs index 837de60053..494268b158 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs index dd7bf48791..343378ccfb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapListingSortTabControl.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs index 7f7ba6966b..5e22450ba8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapSearchFilter.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs index eeb2d1e70f..92bf2448b1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneBreadcrumbControl.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs index d2acf89dc8..bc3f1d0070 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneColourPicker.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs index 1bfa389a25..eaaf40fb36 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.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. -#nullable disable - using osu.Game.Overlays.Comments.Buttons; using osu.Framework.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs index 3491b7dbc1..7b80549854 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneContextMenu.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs index 01d4eb83f3..a8eaabe758 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCursors.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs index 6092f35050..77658dc482 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDashboardBeatmapListing.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Overlays.Dashboard.Home; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs index 108ad8b7c1..b590abf4e5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDrawableDate.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs index 72dacb7558..7d1b3a4bb7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneEditorSidebar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index 9d850c0fc5..ed0fd340e7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs index ec8ef0ad50..4b589ffe4c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBehaviour.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs index e9460e45d3..30a36652c2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenBundledBeatmaps.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs index e6fc889a70..680b54f637 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenImportFromStable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Threading; using System.Threading.Tasks; using Moq; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs index 8ba94cf9ae..2dee57f4cb 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFirstRunScreenUIScale.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs index 24b4060a42..4e1bf1390a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneFooterButtonMods.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs index 801bef62c8..91c1f58155 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs index 454fa7cd05..a1910570dd 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneIconButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs index a2cfae3c7f..300b451cf5 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs index 6181891e13..726f13861b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSliderBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs index c4af47bd0f..bec517af2c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledSwitchButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs index 8046554819..a9f6b812df 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLabelledTextBox.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs index 40e786592a..bd36be846b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLoadingSpinner.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs index f9d92aabc6..863e59f6a7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneLogoAnimation.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs index bd5a0d8645..1bb83eeddf 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs index 07312379b3..83dc96d0d7 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchSmall.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs index 34dd139428..2d953fe9ad 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs index f2123061e5..4bd3a883f1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOnScreenDisplay.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs index 770b9dece1..b0548d7e9f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs index 24a27f71e8..62a493815b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuLogo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Menu; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs index 4ff7befe71..98ae50c915 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuPopover.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs index 929537e675..69fe8ad105 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOsuTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index e90041774e..a927b0931b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs index 7a445427f5..5a43c5ae69 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeaderBackground.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Game.Overlays; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs index 432e448038..d83e922edf 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayRulesetSelector.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs index b9e3592389..3f3b6d8267 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePageSelector.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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs index 92d4981d4a..38f65b3a17 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneParallaxContainer.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs index f364a48616..59600e639f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRankingsSortTabControl.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs index cbf67c49a6..8c2651f71d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneRoundedButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Bindables; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs index 3d35f2c9cc..968cf9f9db 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneScreenBreadcrumbControl.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs index a0fe5fce32..1101f27139 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneSettingsCheckbox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs index aeea0681eb..27b128e709 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedOverlayHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs index 0072864335..f3a7f1481a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneShearedSearchTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs index 24c4ed79b1..94117ff7e3 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTabControl.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs index 41a6f35624..f564f561ec 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneToggleMenuItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs index 20b0ab5801..524119f34d 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneTwoLayerButton.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. -#nullable disable - using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs index 8737f7312e..a373fbbc51 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUserListToolbar.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs index 7cedef96e3..311bae0d50 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneVolumePieces.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Overlays.Volume; using osuTK; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs index 7851571b36..e1f8357a36 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneWaveContainer.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. -#nullable disable - using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs index 05ffd1fbef..2c894eacab 100644 --- a/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs +++ b/osu.Game.Tests/Visual/UserInterface/ThemeComparisonTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs index cb923a1f9a..3dac550bd6 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentMatch.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs index dd7c613c6c..a809d0747a 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneDrawableTournamentTeam.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Tests.Visual; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs index 2347c84ba8..ae4c5ec685 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs index 9b1fc17591..3007232077 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneMatchScoreDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Utils; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs index cb22e7e7c7..431b6eff63 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneRoundDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Tournament.Components; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs index 057566d426..4fa90437c8 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentBeatmapPanel.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.API; @@ -21,7 +19,7 @@ namespace osu.Game.Tournament.Tests.Components /// It cannot be trivially replaced because setting to causes to no longer be usable. /// [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index d9ae8df651..ddae626305 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs index 45dffdc94a..3ae1400a99 100644 --- a/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/CustomTourneyDirectoryTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.IO; using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs index f1e0966293..962a6fbd6c 100644 --- a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; using NUnit.Framework; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs index 10ed850002..cd15550931 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneDrawingsScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.IO; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs index 5c4e1b2a5a..839730f3ca 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs index 20f729bb8d..ecc741ddc1 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Cursor; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs index ebeb69012d..2e7bf364f7 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneRoundEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs index cfb533149d..0d06b0352f 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Tournament.Models; using osu.Game.Tournament.Screens.Editors; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs index c9620bc0b9..f656934239 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs index 84c8b9a141..6af2af7732 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Tournament.Screens.Setup; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs index 6287679c27..e50a2a0c07 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Tournament.Screens.Showcase; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs index dbd9cb2817..db49bc960a 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs index 63c08800ad..7b371ed78b 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tournament.Screens.Editors; namespace osu.Game.Tournament.Tests.Screens diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs index 5c26bc203c..02762ab5c7 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamIntroScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 43e16873c6..8096988864 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs index 859d0591c3..f580b2e455 100644 --- a/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs +++ b/osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; namespace osu.Game.Tournament.Tests diff --git a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs index f29272fbb8..037afd8690 100644 --- a/osu.Game.Tournament.Tests/TournamentTestBrowser.cs +++ b/osu.Game.Tournament.Tests/TournamentTestBrowser.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; diff --git a/osu.Game.Tournament.Tests/TournamentTestRunner.cs b/osu.Game.Tournament.Tests/TournamentTestRunner.cs index f95fcbf487..f6aef53514 100644 --- a/osu.Game.Tournament.Tests/TournamentTestRunner.cs +++ b/osu.Game.Tournament.Tests/TournamentTestRunner.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs index c3e66e80eb..b5912349a0 100644 --- a/osu.Game.Tournament/Components/ControlPanel.cs +++ b/osu.Game.Tournament/Components/ControlPanel.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 192d8c9fd1..4fa94b6c63 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tournament/Components/DrawableTeamHeader.cs b/osu.Game.Tournament/Components/DrawableTeamHeader.cs index 1648e7373b..e9ce9f3759 100644 --- a/osu.Game.Tournament/Components/DrawableTeamHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Tournament.Models; using osuTK; diff --git a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs index 27113b0d21..59e261a7dd 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs index 9606670ad8..5ebed34e6a 100644 --- a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs +++ b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs index c83fceb01d..671d2ffb65 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderLogo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs index 7a1f448cb4..ef576f5b02 100644 --- a/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs +++ b/osu.Game.Tournament/Components/DrawableTournamentHeaderText.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Components/IPCErrorDialog.cs b/osu.Game.Tournament/Components/IPCErrorDialog.cs index 995bbffffc..07aeb65ee6 100644 --- a/osu.Game.Tournament/Components/IPCErrorDialog.cs +++ b/osu.Game.Tournament/Components/IPCErrorDialog.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game.Tournament/Components/RoundDisplay.cs b/osu.Game.Tournament/Components/RoundDisplay.cs index 6018cc6ffb..4c72209d12 100644 --- a/osu.Game.Tournament/Components/RoundDisplay.cs +++ b/osu.Game.Tournament/Components/RoundDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament/Components/TournamentModIcon.cs b/osu.Game.Tournament/Components/TournamentModIcon.cs index 76b6151519..28114e64fe 100644 --- a/osu.Game.Tournament/Components/TournamentModIcon.cs +++ b/osu.Game.Tournament/Components/TournamentModIcon.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,7 +21,7 @@ namespace osu.Game.Tournament.Components private readonly string modAcronym; [Resolved] - private IRulesetStore rulesets { get; set; } + private IRulesetStore rulesets { get; set; } = null!; public TournamentModIcon(string modAcronym) { diff --git a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs index 3a16662463..97cb610021 100644 --- a/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs +++ b/osu.Game.Tournament/Components/TournamentSpriteTextWithBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Tournament/Configuration/TournamentConfigManager.cs b/osu.Game.Tournament/Configuration/TournamentConfigManager.cs index 8f256ba9c3..b76b18cb5f 100644 --- a/osu.Game.Tournament/Configuration/TournamentConfigManager.cs +++ b/osu.Game.Tournament/Configuration/TournamentConfigManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs index ba584f1d3e..ba0e593eae 100644 --- a/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs +++ b/osu.Game.Tournament/IO/TournamentVideoResourceStore.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.IO.Stores; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/IPC/MatchIPCInfo.cs b/osu.Game.Tournament/IPC/MatchIPCInfo.cs index 3bf790d58e..ff557717d5 100644 --- a/osu.Game.Tournament/IPC/MatchIPCInfo.cs +++ b/osu.Game.Tournament/IPC/MatchIPCInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game.Tournament/Models/BeatmapChoice.cs b/osu.Game.Tournament/Models/BeatmapChoice.cs index ddd4597722..c8ba989fa7 100644 --- a/osu.Game.Tournament/Models/BeatmapChoice.cs +++ b/osu.Game.Tournament/Models/BeatmapChoice.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using Newtonsoft.Json; using Newtonsoft.Json.Converters; diff --git a/osu.Game.Tournament/Models/LadderEditorInfo.cs b/osu.Game.Tournament/Models/LadderEditorInfo.cs index 84ebeff3db..7b36096e3f 100644 --- a/osu.Game.Tournament/Models/LadderEditorInfo.cs +++ b/osu.Game.Tournament/Models/LadderEditorInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; namespace osu.Game.Tournament.Models diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index cb4e8bc16a..b5bc5fd307 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Models/SeedingResult.cs b/osu.Game.Tournament/Models/SeedingResult.cs index 2a404153e6..865f65294e 100644 --- a/osu.Game.Tournament/Models/SeedingResult.cs +++ b/osu.Game.Tournament/Models/SeedingResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game.Tournament/Models/TournamentProgression.cs b/osu.Game.Tournament/Models/TournamentProgression.cs index 6c3ba1922a..f119605026 100644 --- a/osu.Game.Tournament/Models/TournamentProgression.cs +++ b/osu.Game.Tournament/Models/TournamentProgression.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Tournament.Models diff --git a/osu.Game.Tournament/Models/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs index 480d6c37c3..a92bab690e 100644 --- a/osu.Game.Tournament/Models/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game.Tournament/Properties/AssemblyInfo.cs b/osu.Game.Tournament/Properties/AssemblyInfo.cs index 2eb8c3e1d6..70e42bcafb 100644 --- a/osu.Game.Tournament/Properties/AssemblyInfo.cs +++ b/osu.Game.Tournament/Properties/AssemblyInfo.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. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs index 6f7234b8c3..e977012803 100644 --- a/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs +++ b/osu.Game.Tournament/Screens/BeatmapInfoScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs index ac1d599851..1a2f5a1ff4 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/DrawingsConfigManager.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. -#nullable disable - using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs index b397f807f0..a79e2253a4 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs index 37e15b7e45..0a2fa3f207 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupContainer.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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs index 167a576424..137003a126 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/GroupTeam.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs index 7e0ac89c83..09208818a9 100644 --- a/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.cs +++ b/osu.Game.Tournament/Screens/Drawings/Components/ITeamList.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Tournament.Models; diff --git a/osu.Game.Tournament/Screens/Editors/IModelBacked.cs b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs index ca59afa2cb..867055f9ea 100644 --- a/osu.Game.Tournament/Screens/Editors/IModelBacked.cs +++ b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Tournament.Screens.Editors { /// diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index 75131c282d..4a3b5c0846 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -29,7 +27,7 @@ namespace osu.Game.Tournament.Screens.Editors public TournamentRound Model { get; } [Resolved] - private LadderInfo ladderInfo { get; set; } + private LadderInfo ladderInfo { get; set; } = null!; public RoundRow(TournamentRound round) { @@ -146,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Editors public RoundBeatmap Model { get; } [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; private readonly Bindable beatmapId = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs index a4358b4396..9927dd56a0 100644 --- a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -140,7 +138,7 @@ namespace osu.Game.Tournament.Screens.Editors public SeedingBeatmap Model { get; } [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; private readonly Bindable beatmapId = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index c9d897ca11..93fbfba0e3 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -63,11 +61,11 @@ namespace osu.Game.Tournament.Screens.Editors private readonly Container drawableContainer; - [Resolved(canBeNull: true)] - private TournamentSceneManager sceneManager { get; set; } + [Resolved] + private TournamentSceneManager? sceneManager { get; set; } [Resolved] - private LadderInfo ladderInfo { get; set; } + private LadderInfo ladderInfo { get; set; } = null!; public TeamRow(TournamentTeam team, TournamentScreen parent) { @@ -211,10 +209,10 @@ namespace osu.Game.Tournament.Screens.Editors private readonly TournamentUser user; [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; [Resolved] - private TournamentGameBase game { get; set; } + private TournamentGameBase game { get; set; } = null!; private readonly Bindable playerId = new Bindable(); diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs index d2b61220f0..79de4e465e 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Tournament.Components; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs index 60d1678326..c23327a43f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs index 8b3786fa1f..c154e4fcef 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/TeamScore.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs index c79dbc26be..3d59bd8349 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/ProgressionPath.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Lines; diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs index f7a42e4f50..00e5353edd 100644 --- a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs +++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; diff --git a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs index 10d58612f4..80b46007e7 100644 --- a/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs +++ b/osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs index 35d63f4fcf..db4d6198e6 100644 --- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs +++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs index d04059118f..5d9ab5fa8f 100644 --- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs +++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tournament/Screens/TournamentScreen.cs b/osu.Game.Tournament/Screens/TournamentScreen.cs index 02903a637c..1e119e0336 100644 --- a/osu.Game.Tournament/Screens/TournamentScreen.cs +++ b/osu.Game.Tournament/Screens/TournamentScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -15,7 +13,7 @@ namespace osu.Game.Tournament.Screens public const double FADE_DELAY = 200; [Resolved] - protected LadderInfo LadderInfo { get; private set; } + protected LadderInfo LadderInfo { get; private set; } = null!; protected TournamentScreen() { diff --git a/osu.Game.Tournament/TournamentSpriteText.cs b/osu.Game.Tournament/TournamentSpriteText.cs index 7ecb31ff15..227231a310 100644 --- a/osu.Game.Tournament/TournamentSpriteText.cs +++ b/osu.Game.Tournament/TournamentSpriteText.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game.Tournament/TourneyButton.cs b/osu.Game.Tournament/TourneyButton.cs index 558bd476c3..67426c1d58 100644 --- a/osu.Game.Tournament/TourneyButton.cs +++ b/osu.Game.Tournament/TourneyButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tournament/WarningBox.cs b/osu.Game.Tournament/WarningBox.cs index 4a196446f6..a79e97914b 100644 --- a/osu.Game.Tournament/WarningBox.cs +++ b/osu.Game.Tournament/WarningBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Beatmaps/APIFailTimes.cs b/osu.Game/Beatmaps/APIFailTimes.cs index 441d30d06b..7218906b38 100644 --- a/osu.Game/Beatmaps/APIFailTimes.cs +++ b/osu.Game/Beatmaps/APIFailTimes.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. -#nullable disable - using System; using Newtonsoft.Json; diff --git a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs index fe4e815e62..be96a66614 100644 --- a/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Localisation; diff --git a/osu.Game/Beatmaps/BeatmapOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapOnlineStatus.cs index cdd99d4432..41393a8a39 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineStatus.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineStatus.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs b/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs index b2d4cac210..4dd08203fc 100644 --- a/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetHypeStatus.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs b/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs index cea0063814..8cf43ab320 100644 --- a/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetNominationStatus.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs b/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs index 12424b797c..8d519158b6 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineAvailability.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs index ad2e994d3e..e727e2c37f 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineGenre.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineGenre.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. -#nullable disable - namespace osu.Game.Beatmaps { public struct BeatmapSetOnlineGenre diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs index c71c279086..5656fab721 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineLanguage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Beatmaps { public struct BeatmapSetOnlineLanguage diff --git a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs index ca07e5f365..b2d59646ae 100644 --- a/osu.Game/Beatmaps/BeatmapStatisticIcon.cs +++ b/osu.Game/Beatmaps/BeatmapStatisticIcon.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Beatmaps/CountdownType.cs b/osu.Game/Beatmaps/CountdownType.cs index 7fb3de74fb..bbe9b648f7 100644 --- a/osu.Game/Beatmaps/CountdownType.cs +++ b/osu.Game/Beatmaps/CountdownType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index 5b9cf6846c..052fae160f 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs index 84445dc14c..5d0e3891c9 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDifficultyList.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs index 3737715a7d..5ea42fe4b1 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -30,10 +28,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly Box foregroundFill; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; public BeatmapCardDownloadProgressBar() { diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs index c99d1f0c76..ad91615031 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs index 8f8a47c199..4645ca822c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapSetFavouriteState.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps.Drawables.Cards.Buttons; using osu.Game.Beatmaps.Drawables.Cards.Statistics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs index ee45d56b6e..e78fd651fe 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs index 9a2a37a09a..b4298e493a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/ExpandedContentScrollContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs index 3cabbba98d..16be57ac95 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/IconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/IconPill.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs index 439e6acd22..6a329011f3 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/FavouritesStatistic.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Humanizer; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs index 45ab6ddb40..4ce37b8659 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/PlayCountStatistic.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Humanizer; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs index 6de16da2b1..6cb19696f8 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/StoryboardIconPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs index 63b5e95b12..b96ed23826 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/VideoIconPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs index efce0f80f1..2fb3a8eee4 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs index 9877b628db..55af57a45f 100644 --- a/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/DownloadProgressBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs index 36fff1dc3c..df8953d57c 100644 --- a/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs +++ b/osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -47,10 +45,10 @@ namespace osu.Game.Beatmaps.Drawables public IBindable DisplayedStars => displayedStars; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; - [Resolved(canBeNull: true)] - private OverlayColourProvider colourProvider { get; set; } + [Resolved] + private OverlayColourProvider? colourProvider { get; set; } /// /// Creates a new using an already computed . diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 2cd9785048..72f37143d0 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -21,7 +19,7 @@ namespace osu.Game.Beatmaps.Drawables protected override double LoadDelay => 500; [Resolved] - private BeatmapManager beatmaps { get; set; } + private BeatmapManager beatmaps { get; set; } = null!; private readonly BeatmapSetCoverType beatmapSetCoverType; diff --git a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs index 0b53278ab3..d20baf1edb 100644 --- a/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/FlatFileWorkingBeatmap.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.IO; using osu.Framework.Audio.Track; diff --git a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs index b651ef9515..9f2eeff253 100644 --- a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs index 4f292a9a1f..a758e10f7c 100644 --- a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.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. -#nullable disable - using osu.Game.IO; using osu.Game.IO.Serialization; diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index bf69100361..b3815569ec 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; namespace osu.Game.Beatmaps.Formats diff --git a/osu.Game/Beatmaps/Formats/Parsing.cs b/osu.Game/Beatmaps/Formats/Parsing.cs index 9b0d200077..a1683ced0d 100644 --- a/osu.Game/Beatmaps/Formats/Parsing.cs +++ b/osu.Game/Beatmaps/Formats/Parsing.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Globalization; diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 9dc3084cb5..fbe1a9b462 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index f84188c5e2..2833af8ca2 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.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. -#nullable disable - using System; using System.Collections.Generic; using System.Threading; diff --git a/osu.Game/Beatmaps/IBeatmapProcessor.cs b/osu.Game/Beatmaps/IBeatmapProcessor.cs index 0a4a98c606..014dccf5e3 100644 --- a/osu.Game/Beatmaps/IBeatmapProcessor.cs +++ b/osu.Game/Beatmaps/IBeatmapProcessor.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. -#nullable disable - using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs index 9e79e03785..fe9dada9d5 100644 --- a/osu.Game/Beatmaps/IBeatmapResourceProvider.cs +++ b/osu.Game/Beatmaps/IBeatmapResourceProvider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.IO; diff --git a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs index 5c3c72c9e4..fc80f0db6f 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs index b3717c81dc..78368daf09 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEffectFlags.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs index 42d21d14f6..c4a9566110 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyEventType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyEventType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Beatmaps.Legacy { internal enum LegacyEventType diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs index ec947c6dc2..07f170f996 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitObjectType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs index d1782ec862..808a85b621 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyHitSoundType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacyMods.cs b/osu.Game/Beatmaps/Legacy/LegacyMods.cs index 27b2e313ec..0e517ea3df 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyMods.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyMods.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. -#nullable disable - using System; namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs index f8a57c3ac9..70eb941a73 100644 --- a/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs +++ b/osu.Game/Beatmaps/Legacy/LegacySampleBank.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Beatmaps.Legacy { internal enum LegacySampleBank diff --git a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs index 69d0c96b57..5352fb65ed 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyStoryLayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Beatmaps.Legacy { internal enum LegacyStoryLayer diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 274b56a862..4c90b16745 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.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. -#nullable disable - using osu.Game.Screens.Play; namespace osu.Game.Beatmaps.Timing diff --git a/osu.Game/Configuration/BackgroundSource.cs b/osu.Game/Configuration/BackgroundSource.cs index f08b29cffe..2d9ed6df2c 100644 --- a/osu.Game/Configuration/BackgroundSource.cs +++ b/osu.Game/Configuration/BackgroundSource.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs index 33329002a9..c979ebf453 100644 --- a/osu.Game/Configuration/DevelopmentOsuConfigManager.cs +++ b/osu.Game/Configuration/DevelopmentOsuConfigManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Platform; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/DiscordRichPresenceMode.cs b/osu.Game/Configuration/DiscordRichPresenceMode.cs index 150d23447e..6bec4fcc74 100644 --- a/osu.Game/Configuration/DiscordRichPresenceMode.cs +++ b/osu.Game/Configuration/DiscordRichPresenceMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/HUDVisibilityMode.cs b/osu.Game/Configuration/HUDVisibilityMode.cs index 9c69f33220..5ba7cbbe99 100644 --- a/osu.Game/Configuration/HUDVisibilityMode.cs +++ b/osu.Game/Configuration/HUDVisibilityMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/InMemoryConfigManager.cs b/osu.Game/Configuration/InMemoryConfigManager.cs index d8879daa3f..ccf697f680 100644 --- a/osu.Game/Configuration/InMemoryConfigManager.cs +++ b/osu.Game/Configuration/InMemoryConfigManager.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. -#nullable disable - using System; using osu.Framework.Configuration; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 193068193a..309a5818ae 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Diagnostics; using osu.Framework.Bindables; diff --git a/osu.Game/Configuration/RandomSelectAlgorithm.cs b/osu.Game/Configuration/RandomSelectAlgorithm.cs index 052c6b4c55..985b4a8c55 100644 --- a/osu.Game/Configuration/RandomSelectAlgorithm.cs +++ b/osu.Game/Configuration/RandomSelectAlgorithm.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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index e0ad59746b..3ad46d771c 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/ScreenshotFormat.cs b/osu.Game/Configuration/ScreenshotFormat.cs index 13d0b64fd2..f043781c45 100644 --- a/osu.Game/Configuration/ScreenshotFormat.cs +++ b/osu.Game/Configuration/ScreenshotFormat.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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/ScrollVisualisationMethod.cs b/osu.Game/Configuration/ScrollVisualisationMethod.cs index 111bb95e67..5f48fe8bfd 100644 --- a/osu.Game/Configuration/ScrollVisualisationMethod.cs +++ b/osu.Game/Configuration/ScrollVisualisationMethod.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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/SeasonalBackgroundMode.cs b/osu.Game/Configuration/SeasonalBackgroundMode.cs index 3e6d9e42aa..4ef71ef09c 100644 --- a/osu.Game/Configuration/SeasonalBackgroundMode.cs +++ b/osu.Game/Configuration/SeasonalBackgroundMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index fda7193fea..e5d2d572c8 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.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. -#nullable disable - using osu.Game.Database; namespace osu.Game.Configuration diff --git a/osu.Game/Configuration/StorageConfigManager.cs b/osu.Game/Configuration/StorageConfigManager.cs index c8781918e1..40c0e70488 100644 --- a/osu.Game/Configuration/StorageConfigManager.cs +++ b/osu.Game/Configuration/StorageConfigManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index da970a29d4..bdbcebeaf5 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.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. -#nullable disable - using System.Collections.Generic; using System.Threading.Tasks; diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index 9f8ce05218..3f6531832f 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.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. -#nullable disable - using System.Collections.Generic; using JetBrains.Annotations; diff --git a/osu.Game/Database/IHasGuidPrimaryKey.cs b/osu.Game/Database/IHasGuidPrimaryKey.cs index 9cf7cf0683..8520707bd2 100644 --- a/osu.Game/Database/IHasGuidPrimaryKey.cs +++ b/osu.Game/Database/IHasGuidPrimaryKey.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using Newtonsoft.Json; using Realms; diff --git a/osu.Game/Database/IHasNamedFiles.cs b/osu.Game/Database/IHasNamedFiles.cs index 3524eb4c99..34f6560f75 100644 --- a/osu.Game/Database/IHasNamedFiles.cs +++ b/osu.Game/Database/IHasNamedFiles.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; namespace osu.Game.Database diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index 84709ccd26..51a49948fe 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.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. -#nullable disable - using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; diff --git a/osu.Game/Database/IModelFileManager.cs b/osu.Game/Database/IModelFileManager.cs index c40b57f663..390be4a69d 100644 --- a/osu.Game/Database/IModelFileManager.cs +++ b/osu.Game/Database/IModelFileManager.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. -#nullable disable - using System.IO; namespace osu.Game.Database diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 988178818d..ce79aac966 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; namespace osu.Game.Database diff --git a/osu.Game/Database/INamedFileInfo.cs b/osu.Game/Database/INamedFileInfo.cs index 9df4a0869c..d95f228440 100644 --- a/osu.Game/Database/INamedFileInfo.cs +++ b/osu.Game/Database/INamedFileInfo.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. -#nullable disable - using osu.Game.IO; namespace osu.Game.Database diff --git a/osu.Game/Database/IPostNotifications.cs b/osu.Game/Database/IPostNotifications.cs index 8bb2c54945..205350b80c 100644 --- a/osu.Game/Database/IPostNotifications.cs +++ b/osu.Game/Database/IPostNotifications.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Overlays.Notifications; diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index 3ace67f410..beb7c5a4df 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; diff --git a/osu.Game/Graphics/Backgrounds/SkinBackground.cs b/osu.Game/Graphics/Backgrounds/SkinBackground.cs index e30bb961a0..17af5e6991 100644 --- a/osu.Game/Graphics/Backgrounds/SkinBackground.cs +++ b/osu.Game/Graphics/Backgrounds/SkinBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Skinning; diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index 55160e14af..7722374c69 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs index a06af61125..5abb4096ac 100644 --- a/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs +++ b/osu.Game/Graphics/Containers/ExpandingButtonContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Graphics.Containers { /// diff --git a/osu.Game/Graphics/Containers/IExpandable.cs b/osu.Game/Graphics/Containers/IExpandable.cs index 05d569775c..8549d3bf2c 100644 --- a/osu.Game/Graphics/Containers/IExpandable.cs +++ b/osu.Game/Graphics/Containers/IExpandable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/IExpandingContainer.cs b/osu.Game/Graphics/Containers/IExpandingContainer.cs index dbd9274ae7..6a36372e88 100644 --- a/osu.Game/Graphics/Containers/IExpandingContainer.cs +++ b/osu.Game/Graphics/Containers/IExpandingContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 5b1780a068..4a61ee2043 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig; using Markdig.Extensions.Footnotes; using Markdig.Extensions.Tables; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs index b5bbe3e2cc..7d84d368ad 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownFencedCodeBlock.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs index 800a0e1fc3..da4273c9b9 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownHeading.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs index 8ccac158eb..10207dd389 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownImage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax.Inlines; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs index 6eac9378ae..1812a9529c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownOrderedListItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs index 447085a48c..d2e6f4d370 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownQuoteBlock.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs index 343a1d1015..b785b748a7 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownSeparator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs index c9c1098e05..652d3d9e3e 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Extensions.Tables; using osu.Framework.Graphics.Containers.Markdown; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs index dbf15a2546..4ffdeb179c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownTableCell.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Extensions.Tables; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs index 64e98511c2..cdd6bc6ed5 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownUnorderedListItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index b4b80f7574..3b5e48d23e 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs index e37d23fe97..892edf8551 100644 --- a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 9a1ddac40d..bb9be2b939 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Game.Extensions; diff --git a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs index 715677aec1..6934c95385 100644 --- a/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs +++ b/osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; namespace osu.Game.Graphics.Containers diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 05a666721a..9fd3d103c9 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.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. -#nullable disable - using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index 27700e71d9..c5bcfcd2df 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index dc75d626b9..aab5b3ee36 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.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. -#nullable disable - using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/DateTooltip.cs b/osu.Game/Graphics/DateTooltip.cs index c62f53f1d4..c084f498fe 100644 --- a/osu.Game/Graphics/DateTooltip.cs +++ b/osu.Game/Graphics/DateTooltip.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 553b27acb1..0e5bcc8019 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/ErrorTextFlowContainer.cs b/osu.Game/Graphics/ErrorTextFlowContainer.cs index 65a90534e5..7386baf83f 100644 --- a/osu.Game/Graphics/ErrorTextFlowContainer.cs +++ b/osu.Game/Graphics/ErrorTextFlowContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index fc722375ce..af497da70f 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.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. -#nullable disable - using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs index 78c8cbb79e..2428eebbe5 100644 --- a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs +++ b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.InteropServices; using osu.Framework.Graphics.Rendering.Vertices; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index e06f6b3fd0..1b21f79c0a 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.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. -#nullable disable - using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Graphics/OsuIcon.cs b/osu.Game/Graphics/OsuIcon.cs index 0a099f1fcc..1f4d6a62da 100644 --- a/osu.Game/Graphics/OsuIcon.cs +++ b/osu.Game/Graphics/OsuIcon.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Sprites; namespace osu.Game.Graphics diff --git a/osu.Game/Graphics/ParticleExplosion.cs b/osu.Game/Graphics/ParticleExplosion.cs index 56e1568441..e16913c6c9 100644 --- a/osu.Game/Graphics/ParticleExplosion.cs +++ b/osu.Game/Graphics/ParticleExplosion.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs index ae594ddfe2..1355bfc272 100644 --- a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs +++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index afbec0eab4..6ce64a9052 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.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. -#nullable disable - using System; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index 53217e2120..9b63cabeda 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.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. -#nullable disable - using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index c394e58d87..27a41eb7e3 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osuTK; using osu.Framework.Graphics; using System.Collections.Generic; diff --git a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs index c4e03133dc..2e76951e7b 100644 --- a/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/BasicSearchTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osuTK; diff --git a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs index ba76a17fc6..e0a5409683 100644 --- a/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/CommaSeparatedScoreCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs b/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs index 5855a66ae1..b237dd9b71 100644 --- a/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs +++ b/osu.Game/Graphics/UserInterface/DangerousRoundedButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics.UserInterfaceV2; diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 670778b07b..06ebe48850 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.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. -#nullable disable - using System; using osu.Framework; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs index ec3a5744f8..5af275c9e7 100644 --- a/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/DrawableStatefulMenuItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs index 5bc17303d8..121a1eef49 100644 --- a/osu.Game/Graphics/UserInterface/ExpandableSlider.cs +++ b/osu.Game/Graphics/UserInterface/ExpandableSlider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -106,8 +104,8 @@ namespace osu.Game.Graphics.UserInterface }; } - [Resolved(canBeNull: true)] - private IExpandingContainer expandingContainer { get; set; } + [Resolved] + private IExpandingContainer? expandingContainer { get; set; } protected override void LoadComplete() { diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs index 6d7c41ee7c..bec4e6e49c 100644 --- a/osu.Game/Graphics/UserInterface/ExpandingBar.cs +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osuTK; diff --git a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs index f0ff76b35d..72d50eb042 100644 --- a/osu.Game/Graphics/UserInterface/HoverSampleSet.cs +++ b/osu.Game/Graphics/UserInterface/HoverSampleSet.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index 47f06715b5..0268fa59c2 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.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. -#nullable disable - using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/LoadingButton.cs b/osu.Game/Graphics/UserInterface/LoadingButton.cs index 8a841ffc94..4a37811114 100644 --- a/osu.Game/Graphics/UserInterface/LoadingButton.cs +++ b/osu.Game/Graphics/UserInterface/LoadingButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs index 0ea44dfe49..df921c5c81 100644 --- a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs +++ b/osu.Game/Graphics/UserInterface/LoadingSpinner.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 69e8df0286..de4df96942 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -41,7 +39,7 @@ namespace osu.Game.Graphics.UserInterface } [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; protected override Container Content => content; diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index 1b5f7cc4b5..96797e5d01 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.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. -#nullable disable - using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -17,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface private const int fade_duration = 250; [Resolved] - private OsuContextMenuSamples samples { get; set; } + private OsuContextMenuSamples samples { get; set; } = null!; // todo: this shouldn't be required after https://github.com/ppy/osu-framework/issues/4519 is fixed. private bool wasOpened; diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index dc089e3410..14f8f6f3c5 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.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. -#nullable disable - using System; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs index f6a3abdaae..df92863797 100644 --- a/osu.Game/Graphics/UserInterface/OsuNumberBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuNumberBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 9de9eceb07..123854a2dd 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.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. -#nullable disable - using osuTK; using osuTK.Graphics; using osuTK.Input; @@ -39,7 +37,7 @@ namespace osu.Game.Graphics.UserInterface private readonly CapsWarning warning; [Resolved] - private GameHost host { get; set; } + private GameHost host { get; set; } = null!; public OsuPasswordTextBox() { diff --git a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs b/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs index 01d072b6d7..6272f95510 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabDropdown.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. -#nullable disable - using osuTK; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs index 068e477d79..0f3b09f2dc 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageEllipsis.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs index 63f35d5f89..416cd4b8ff 100644 --- a/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.cs +++ b/osu.Game/Graphics/UserInterface/PageSelector/PageSelector.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. -#nullable disable - using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index de93d9b2b4..ed06211e8f 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 2d09a239bb..a2e0ab6482 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.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. -#nullable disable - using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs index a85cd36808..11cf88c20e 100644 --- a/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SeekLimitedSearchTextBox.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. -#nullable disable - namespace osu.Game.Graphics.UserInterface { /// diff --git a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs index fb0a66cb8d..3940bf8bca 100644 --- a/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/ShearedSearchTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs index e3f5bc65e6..33382305cf 100644 --- a/osu.Game/Graphics/UserInterface/SlimEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/SlimEnumDropdown.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index d7d088d798..82f6f8e0a4 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.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. -#nullable disable - using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/TimeSlider.cs b/osu.Game/Graphics/UserInterface/TimeSlider.cs index e6e7ae9305..7652eda7be 100644 --- a/osu.Game/Graphics/UserInterface/TimeSlider.cs +++ b/osu.Game/Graphics/UserInterface/TimeSlider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; namespace osu.Game.Graphics.UserInterface diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index aa542b8f49..5532e5c6a7 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs index 721d8990ba..163d1fb2b9 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledColourPalette.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs index 8fd9a62ad7..59a1812e5d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledComponent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs index 0e2ea362da..dbbae390a7 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs index 3ca460be90..9c2c8397ed 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledEnumDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs index 2643db0547..4926afd7a3 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledNumberBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs index 00f4ef1a30..4585d3a4c9 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSliderBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Game.Overlays.Settings; diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs index 3c27829de3..d25bcbfbe9 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledSwitchButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Graphics.UserInterfaceV2 { public partial class LabelledSwitchButton : LabelledComponent diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs index fed17eaf20..cf86206f5c 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuColourPicker.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterfaceV2 diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs index beaeb86243..c0ac9f21ca 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuDirectorySelectorParentDirectory.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.IO; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index ff51f3aa92..75ff1e5665 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs index 9aa650d88d..6633ba0eb2 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs index d89322cecd..9153d5253d 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions; diff --git a/osu.Game/IO/Archives/LegacyByteArrayReader.cs b/osu.Game/IO/Archives/LegacyByteArrayReader.cs index e58dbb48ce..06db02b335 100644 --- a/osu.Game/IO/Archives/LegacyByteArrayReader.cs +++ b/osu.Game/IO/Archives/LegacyByteArrayReader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs index e26f6af081..dfae58aed7 100644 --- a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.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. -#nullable disable - using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs index aee1add2f6..c317cae5fc 100644 --- a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs index d47f936eb3..8d14385707 100644 --- a/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs +++ b/osu.Game/IO/FileAbstraction/StreamFileAbstraction.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.IO; diff --git a/osu.Game/IO/Legacy/ILegacySerializable.cs b/osu.Game/IO/Legacy/ILegacySerializable.cs index f21e67a34b..e5518a0a30 100644 --- a/osu.Game/IO/Legacy/ILegacySerializable.cs +++ b/osu.Game/IO/Legacy/ILegacySerializable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.IO.Legacy { public interface ILegacySerializable diff --git a/osu.Game/IO/OsuStorage.cs b/osu.Game/IO/OsuStorage.cs index f4c55e4b0e..a2b89b6d97 100644 --- a/osu.Game/IO/OsuStorage.cs +++ b/osu.Game/IO/OsuStorage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Diagnostics; using System.Linq; using JetBrains.Annotations; diff --git a/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs b/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs index 65283d0d82..450eebd736 100644 --- a/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs +++ b/osu.Game/IO/Serialization/Converters/SnakeCaseStringEnumConverter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; diff --git a/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs b/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs index b51a8473ca..d01e8de26d 100644 --- a/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.cs +++ b/osu.Game/IO/Serialization/SnakeCaseKeyContractResolver.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. -#nullable disable - using Newtonsoft.Json.Serialization; using osu.Game.Extensions; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index 54157c9e3d..40f270c234 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -68,7 +66,7 @@ namespace osu.Game.Input public void OnReleased(KeyBindingReleaseEvent e) => updateLastInteractionTime(); [Resolved] - private GameHost host { get; set; } + private GameHost host { get; set; } = null!; protected override bool Handle(UIEvent e) { diff --git a/osu.Game/Input/OsuConfineMouseMode.cs b/osu.Game/Input/OsuConfineMouseMode.cs index 2d914ac6e0..e875ceebd9 100644 --- a/osu.Game/Input/OsuConfineMouseMode.cs +++ b/osu.Game/Input/OsuConfineMouseMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Input; using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Input/OsuUserInputManager.cs b/osu.Game/Input/OsuUserInputManager.cs index c205636ab9..b8fd0bb11c 100644 --- a/osu.Game/Input/OsuUserInputManager.cs +++ b/osu.Game/Input/OsuUserInputManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Input; using osuTK.Input; diff --git a/osu.Game/Online/API/APIException.cs b/osu.Game/Online/API/APIException.cs index 21a9c761c7..7491e375df 100644 --- a/osu.Game/Online/API/APIException.cs +++ b/osu.Game/Online/API/APIException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/APIMessagesRequest.cs b/osu.Game/Online/API/APIMessagesRequest.cs index 5bb3e29621..3ad6b1d7c8 100644 --- a/osu.Game/Online/API/APIMessagesRequest.cs +++ b/osu.Game/Online/API/APIMessagesRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs b/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs index df64984c7a..8df2d3fc2d 100644 --- a/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs +++ b/osu.Game/Online/API/ModSettingsDictionaryFormatter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Buffers; using System.Collections.Generic; using System.Text; diff --git a/osu.Game/Online/API/OsuJsonWebRequest.cs b/osu.Game/Online/API/OsuJsonWebRequest.cs index 2d402edd3f..eb0be57d9f 100644 --- a/osu.Game/Online/API/OsuJsonWebRequest.cs +++ b/osu.Game/Online/API/OsuJsonWebRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/OsuWebRequest.cs b/osu.Game/Online/API/OsuWebRequest.cs index 9a7cf45a2f..ee7115fa96 100644 --- a/osu.Game/Online/API/OsuWebRequest.cs +++ b/osu.Game/Online/API/OsuWebRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/Requests/CommentVoteRequest.cs b/osu.Game/Online/API/Requests/CommentVoteRequest.cs index a835b0365c..06a3b1126e 100644 --- a/osu.Game/Online/API/Requests/CommentVoteRequest.cs +++ b/osu.Game/Online/API/Requests/CommentVoteRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; using System.Net.Http; diff --git a/osu.Game/Online/API/Requests/CreateChannelRequest.cs b/osu.Game/Online/API/Requests/CreateChannelRequest.cs index 130210b1c3..e660c4a883 100644 --- a/osu.Game/Online/API/Requests/CreateChannelRequest.cs +++ b/osu.Game/Online/API/Requests/CreateChannelRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs index 6b7192dbf4..0429a30b0b 100644 --- a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs +++ b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/Cursor.cs b/osu.Game/Online/API/Requests/Cursor.cs index c7bb119bd8..8ddbce39ca 100644 --- a/osu.Game/Online/API/Requests/Cursor.cs +++ b/osu.Game/Online/API/Requests/Cursor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index f190b6e821..5254dc3cf8 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/DownloadReplayRequest.cs b/osu.Game/Online/API/Requests/DownloadReplayRequest.cs index 5635c4728e..77174f0bb5 100644 --- a/osu.Game/Online/API/Requests/DownloadReplayRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadReplayRequest.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. -#nullable disable - using osu.Game.Scoring; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs index f3690c934d..158ae03b8d 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.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. -#nullable disable - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs index e118d1bddc..6cb9e6dd44 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs index 2d2d241b86..baa15c70c4 100644 --- a/osu.Game/Online/API/Requests/GetChangelogBuildRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogBuildRequest.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. -#nullable disable - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetChangelogRequest.cs b/osu.Game/Online/API/Requests/GetChangelogRequest.cs index 82ed42615f..97799ff66a 100644 --- a/osu.Game/Online/API/Requests/GetChangelogRequest.cs +++ b/osu.Game/Online/API/Requests/GetChangelogRequest.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. -#nullable disable - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetCommentsRequest.cs b/osu.Game/Online/API/Requests/GetCommentsRequest.cs index 1aa08f2ed8..1e033a58a7 100644 --- a/osu.Game/Online/API/Requests/GetCommentsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCommentsRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs index 9d037ab116..d8a1198627 100644 --- a/osu.Game/Online/API/Requests/GetCountryRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetCountryRankingsRequest.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. -#nullable disable - using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs index 640ddcbb9e..63a221d91a 100644 --- a/osu.Game/Online/API/Requests/GetFriendsRequest.cs +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetMessagesRequest.cs b/osu.Game/Online/API/Requests/GetMessagesRequest.cs index 2f9879c63f..651f8a06c5 100644 --- a/osu.Game/Online/API/Requests/GetMessagesRequest.cs +++ b/osu.Game/Online/API/Requests/GetMessagesRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/GetRankingsRequest.cs b/osu.Game/Online/API/Requests/GetRankingsRequest.cs index f42da69dcc..ddc3298ca7 100644 --- a/osu.Game/Online/API/Requests/GetRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetRankingsRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Rulesets; diff --git a/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs b/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs index 0ecce90749..941b47244a 100644 --- a/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSeasonalBackgroundsRequest.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. -#nullable disable - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs index 2d8a8b3b61..59b2928a2a 100644 --- a/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetSpotlightRankingsRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Overlays.Rankings; using osu.Game.Rulesets; diff --git a/osu.Game/Online/API/Requests/GetTopUsersRequest.cs b/osu.Game/Online/API/Requests/GetTopUsersRequest.cs index 7f05cd5eab..dbbd2119db 100644 --- a/osu.Game/Online/API/Requests/GetTopUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetTopUsersRequest.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. -#nullable disable - namespace osu.Game.Online.API.Requests { public class GetTopUsersRequest : APIRequest diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index e4134980b1..226bc6bf1e 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index 3d0ee23080..67d3ad26b0 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index e5e65415f7..bef3df42fb 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs b/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs index c27a83b695..628fc1be96 100644 --- a/osu.Game/Online/API/Requests/GetUserRankingsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRankingsRequest.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. -#nullable disable - using osu.Framework.IO.Network; using osu.Game.Rulesets; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 82cf0a508a..79f0549d4a 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetWikiRequest.cs b/osu.Game/Online/API/Requests/GetWikiRequest.cs index 7c84e1f790..f6bd80e210 100644 --- a/osu.Game/Online/API/Requests/GetWikiRequest.cs +++ b/osu.Game/Online/API/Requests/GetWikiRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Extensions; using osu.Game.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/JoinChannelRequest.cs b/osu.Game/Online/API/Requests/JoinChannelRequest.cs index 30b8fafd57..33eab7e355 100644 --- a/osu.Game/Online/API/Requests/JoinChannelRequest.cs +++ b/osu.Game/Online/API/Requests/JoinChannelRequest.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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs b/osu.Game/Online/API/Requests/LeaveChannelRequest.cs index 4e77055e67..7dfc9a0aed 100644 --- a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs +++ b/osu.Game/Online/API/Requests/LeaveChannelRequest.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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/ListChannelsRequest.cs b/osu.Game/Online/API/Requests/ListChannelsRequest.cs index 6f8fb427dc..9660695c14 100644 --- a/osu.Game/Online/API/Requests/ListChannelsRequest.cs +++ b/osu.Game/Online/API/Requests/ListChannelsRequest.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. -#nullable disable - using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs index afdc8a47f4..b24669e6d5 100644 --- a/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.cs +++ b/osu.Game/Online/API/Requests/MarkChannelAsReadRequest.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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs index 4af1f58180..44b2b17d66 100644 --- a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Globalization; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/PaginationParameters.cs b/osu.Game/Online/API/Requests/PaginationParameters.cs index 6dacb009bd..cab56bcf2e 100644 --- a/osu.Game/Online/API/Requests/PaginationParameters.cs +++ b/osu.Game/Online/API/Requests/PaginationParameters.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Online.API.Requests { /// diff --git a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs index 1438c9c436..9fdc3382aa 100644 --- a/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.cs +++ b/osu.Game/Online/API/Requests/PostBeatmapFavouriteRequest.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. -#nullable disable - using osu.Framework.IO.Network; using System.Net.Http; diff --git a/osu.Game/Online/API/Requests/PostMessageRequest.cs b/osu.Game/Online/API/Requests/PostMessageRequest.cs index e3709d8f13..64b88f0340 100644 --- a/osu.Game/Online/API/Requests/PostMessageRequest.cs +++ b/osu.Game/Online/API/Requests/PostMessageRequest.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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs index 4a877f392a..be43fc8ae7 100644 --- a/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs +++ b/osu.Game/Online/API/Requests/Responses/APIPlayStyle.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs b/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs index 65001dd6cf..836a5bc485 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserAchievement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs b/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs index 6eb3c8b8a4..9a34699a1b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserHistoryCount.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using Newtonsoft.Json; diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index ee53c00668..883a2496f7 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -27,8 +25,8 @@ namespace osu.Game.Online.Chat /// public readonly List Parts; - [Resolved(CanBeNull = true)] - private OverlayColourProvider overlayColourProvider { get; set; } + [Resolved] + private OverlayColourProvider? overlayColourProvider { get; set; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Parts.Any(d => d.ReceivePositionalInputAt(screenSpacePos)); diff --git a/osu.Game/Online/Chat/ErrorMessage.cs b/osu.Game/Online/Chat/ErrorMessage.cs index 9cd91a0927..ccfc0e29b4 100644 --- a/osu.Game/Online/Chat/ErrorMessage.cs +++ b/osu.Game/Online/Chat/ErrorMessage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Online.Chat { public class ErrorMessage : InfoMessage diff --git a/osu.Game/Online/DevelopmentEndpointConfiguration.cs b/osu.Game/Online/DevelopmentEndpointConfiguration.cs index 3171d15fc2..69276f452a 100644 --- a/osu.Game/Online/DevelopmentEndpointConfiguration.cs +++ b/osu.Game/Online/DevelopmentEndpointConfiguration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Online { public class DevelopmentEndpointConfiguration : EndpointConfiguration diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 5a65c15444..5177f35478 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.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. -#nullable disable - using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs index 68bf3cfaec..f266c38b8b 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerLoungeServer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Threading.Tasks; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs index a2608f1564..b7a5faf7c9 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Threading.Tasks; using osu.Game.Online.API; diff --git a/osu.Game/Online/Multiplayer/InvalidPasswordException.cs b/osu.Game/Online/Multiplayer/InvalidPasswordException.cs index 305c41e69b..d3da8f491b 100644 --- a/osu.Game/Online/Multiplayer/InvalidPasswordException.cs +++ b/osu.Game/Online/Multiplayer/InvalidPasswordException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs b/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs index ab513e71ee..4c793dba68 100644 --- a/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs +++ b/osu.Game/Online/Multiplayer/InvalidStateChangeException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/InvalidStateException.cs b/osu.Game/Online/Multiplayer/InvalidStateException.cs index ba3b84ffe4..27b111a781 100644 --- a/osu.Game/Online/Multiplayer/InvalidStateException.cs +++ b/osu.Game/Online/Multiplayer/InvalidStateException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/MatchUserRequest.cs b/osu.Game/Online/Multiplayer/MatchUserRequest.cs index 7fc1790434..8515256581 100644 --- a/osu.Game/Online/Multiplayer/MatchUserRequest.cs +++ b/osu.Game/Online/Multiplayer/MatchUserRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using MessagePack; using osu.Game.Online.Multiplayer.Countdown; diff --git a/osu.Game/Online/Multiplayer/NotHostException.cs b/osu.Game/Online/Multiplayer/NotHostException.cs index 9f789f1e81..cd43b13e52 100644 --- a/osu.Game/Online/Multiplayer/NotHostException.cs +++ b/osu.Game/Online/Multiplayer/NotHostException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs b/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs index c749e4615a..0a96406c16 100644 --- a/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs +++ b/osu.Game/Online/Multiplayer/NotJoinedRoomException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Runtime.Serialization; using Microsoft.AspNetCore.SignalR; diff --git a/osu.Game/Online/Multiplayer/QueueMode.cs b/osu.Game/Online/Multiplayer/QueueMode.cs index a7bc4ae00a..adc975539f 100644 --- a/osu.Game/Online/Multiplayer/QueueMode.cs +++ b/osu.Game/Online/Multiplayer/QueueMode.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index de7ac6e936..60c9ecbcdc 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; @@ -12,8 +10,8 @@ namespace osu.Game.Online.Placeholders { public sealed partial class LoginPlaceholder : ClickablePlaceholder { - [Resolved(CanBeNull = true)] - private LoginOverlay login { get; set; } + [Resolved] + private LoginOverlay? login { get; set; } public LoginPlaceholder(LocalisableString actionMessage) : base(actionMessage, FontAwesome.Solid.UserLock) diff --git a/osu.Game/Online/Placeholders/MessagePlaceholder.cs b/osu.Game/Online/Placeholders/MessagePlaceholder.cs index 07a111a10f..bef889a576 100644 --- a/osu.Game/Online/Placeholders/MessagePlaceholder.cs +++ b/osu.Game/Online/Placeholders/MessagePlaceholder.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Online/Rooms/APIScoreToken.cs b/osu.Game/Online/Rooms/APIScoreToken.cs index 58a633f3cf..542f972d3f 100644 --- a/osu.Game/Online/Rooms/APIScoreToken.cs +++ b/osu.Game/Online/Rooms/APIScoreToken.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/CreateRoomRequest.cs b/osu.Game/Online/Rooms/CreateRoomRequest.cs index b22780490b..63a3b7bfa8 100644 --- a/osu.Game/Online/Rooms/CreateRoomRequest.cs +++ b/osu.Game/Online/Rooms/CreateRoomRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs index 65731b2b68..c31c6a929a 100644 --- a/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/CreateRoomScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs b/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs index 6b5ed2d024..e016074f5d 100644 --- a/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomLeaderboardRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/GetRoomRequest.cs b/osu.Game/Online/Rooms/GetRoomRequest.cs index 237d427509..b968f4e864 100644 --- a/osu.Game/Online/Rooms/GetRoomRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/GetRoomsRequest.cs b/osu.Game/Online/Rooms/GetRoomsRequest.cs index afab83b5be..7feb709acb 100644 --- a/osu.Game/Online/Rooms/GetRoomsRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomsRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.IO.Network; using osu.Game.Extensions; diff --git a/osu.Game/Online/Rooms/IndexScoresParams.cs b/osu.Game/Online/Rooms/IndexScoresParams.cs index 253caa13a1..b69af27e8b 100644 --- a/osu.Game/Online/Rooms/IndexScoresParams.cs +++ b/osu.Game/Online/Rooms/IndexScoresParams.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using JetBrains.Annotations; using Newtonsoft.Json; diff --git a/osu.Game/Online/Rooms/ItemAttemptsCount.cs b/osu.Game/Online/Rooms/ItemAttemptsCount.cs index 71f50b9898..dc86897660 100644 --- a/osu.Game/Online/Rooms/ItemAttemptsCount.cs +++ b/osu.Game/Online/Rooms/ItemAttemptsCount.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/JoinRoomRequest.cs b/osu.Game/Online/Rooms/JoinRoomRequest.cs index 0a687312e7..a1d6ed1e82 100644 --- a/osu.Game/Online/Rooms/JoinRoomRequest.cs +++ b/osu.Game/Online/Rooms/JoinRoomRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/MatchType.cs b/osu.Game/Online/Rooms/MatchType.cs index fd2f583f83..28f2da897a 100644 --- a/osu.Game/Online/Rooms/MatchType.cs +++ b/osu.Game/Online/Rooms/MatchType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Online/Rooms/MultiplayerScores.cs b/osu.Game/Online/Rooms/MultiplayerScores.cs index 4c13579b3e..3331a2155c 100644 --- a/osu.Game/Online/Rooms/MultiplayerScores.cs +++ b/osu.Game/Online/Rooms/MultiplayerScores.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Online/Rooms/PartRoomRequest.cs b/osu.Game/Online/Rooms/PartRoomRequest.cs index da4e9a44c5..09ba6f65c3 100644 --- a/osu.Game/Online/Rooms/PartRoomRequest.cs +++ b/osu.Game/Online/Rooms/PartRoomRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Net.Http; using osu.Framework.IO.Network; using osu.Game.Online.API; diff --git a/osu.Game/Online/Rooms/RoomAvailability.cs b/osu.Game/Online/Rooms/RoomAvailability.cs index fada111826..3aea0e5948 100644 --- a/osu.Game/Online/Rooms/RoomAvailability.cs +++ b/osu.Game/Online/Rooms/RoomAvailability.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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/RoomCategory.cs b/osu.Game/Online/Rooms/RoomCategory.cs index ba17fb2121..17afb0dc7f 100644 --- a/osu.Game/Online/Rooms/RoomCategory.cs +++ b/osu.Game/Online/Rooms/RoomCategory.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs index 9aa6424592..0fc27d26b8 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusEnded.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs index c37b93ea1b..5cc664cf36 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusOpen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs index 9eb61a82ec..4d0c93b8ab 100644 --- a/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs +++ b/osu.Game/Online/Rooms/RoomStatuses/RoomStatusPlaying.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs b/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs index affb2846a2..8e6a1ac7c7 100644 --- a/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs +++ b/osu.Game/Online/Rooms/ShowPlaylistUserScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.API; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs index f4cadc3fde..3f404386c3 100644 --- a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Scoring; namespace osu.Game.Online.Rooms diff --git a/osu.Game/Online/Rooms/SubmitScoreRequest.cs b/osu.Game/Online/Rooms/SubmitScoreRequest.cs index 48a7780a03..b4a91a5892 100644 --- a/osu.Game/Online/Rooms/SubmitScoreRequest.cs +++ b/osu.Game/Online/Rooms/SubmitScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/SignalRWorkaroundTypes.cs b/osu.Game/Online/SignalRWorkaroundTypes.cs index 0b545821ee..0e3eb0aab0 100644 --- a/osu.Game/Online/SignalRWorkaroundTypes.cs +++ b/osu.Game/Online/SignalRWorkaroundTypes.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Online/Solo/CreateSoloScoreRequest.cs b/osu.Game/Online/Solo/CreateSoloScoreRequest.cs index 8c92b32915..2f462b2610 100644 --- a/osu.Game/Online/Solo/CreateSoloScoreRequest.cs +++ b/osu.Game/Online/Solo/CreateSoloScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Globalization; using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs index f387e61901..3260ba8e7c 100644 --- a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs +++ b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.Rooms; using osu.Game.Scoring; diff --git a/osu.Game/Online/Spectator/ISpectatorClient.cs b/osu.Game/Online/Spectator/ISpectatorClient.cs index 605ebc4ef0..9605604966 100644 --- a/osu.Game/Online/Spectator/ISpectatorClient.cs +++ b/osu.Game/Online/Spectator/ISpectatorClient.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Threading.Tasks; namespace osu.Game.Online.Spectator diff --git a/osu.Game/Online/Spectator/ISpectatorServer.cs b/osu.Game/Online/Spectator/ISpectatorServer.cs index fa9d04792a..848983009b 100644 --- a/osu.Game/Online/Spectator/ISpectatorServer.cs +++ b/osu.Game/Online/Spectator/ISpectatorServer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Threading.Tasks; namespace osu.Game.Online.Spectator diff --git a/osu.Game/OsuGameBase_Importing.cs b/osu.Game/OsuGameBase_Importing.cs index cf65460bab..601d17bea9 100644 --- a/osu.Game/OsuGameBase_Importing.cs +++ b/osu.Game/OsuGameBase_Importing.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs index 0042b9f8f6..8d015709aa 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs index a7dd53f511..32e5ca471c 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index 2f290d05e9..e3e2bcaf9a 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index 3ab0e47a6c..608ecbb6f3 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs index 96626d0ac6..2efa4b455e 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchRulesetFilterRow.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs index 031833a107..195ac09c3e 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchScoreFilterRow.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions; diff --git a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs index b3e12d00a6..2c77177541 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchCategory.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchCategory.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs index 10fea6d5b2..4df5cd4b0a 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExplicit.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs b/osu.Game/Overlays/BeatmapListing/SearchExtra.cs index d307cd09eb..e54632acd8 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchExtra.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchExtra.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs index ebcbef1ad9..28d8473a6e 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGeneral.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs index 7746eb50d7..f928f8a7bb 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchGenre.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchGenre.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs index d52f923158..af8a298919 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchLanguage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Framework.Utils; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs b/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs index 0c379b3825..3b04ac01ca 100644 --- a/osu.Game/Overlays/BeatmapListing/SearchPlayed.cs +++ b/osu.Game/Overlays/BeatmapListing/SearchPlayed.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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs index 6c010c7504..5e3cbbfeea 100644 --- a/osu.Game/Overlays/BeatmapListing/SortCriteria.cs +++ b/osu.Game/Overlays/BeatmapListing/SortCriteria.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 9291988367..7d8160bef7 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs index 305a3661a7..4dd257c6ea 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetLayoutSection.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. -#nullable disable - using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index b3b8b80a0d..62a8bf80d3 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 8758b9c5cf..c182ef2e15 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 476a252c7b..5cfe4a35b3 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.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. -#nullable disable - using osu.Game.Screens.Select.Leaderboards; using osu.Game.Graphics.UserInterface; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/MetadataType.cs b/osu.Game/Overlays/BeatmapSet/MetadataType.cs index dc96ce99e9..c92cecc17e 100644 --- a/osu.Game/Overlays/BeatmapSet/MetadataType.cs +++ b/osu.Game/Overlays/BeatmapSet/MetadataType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs index f7703af27d..29a696593d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NoScoresPlaceholder.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Screens.Select.Leaderboards; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index 04ab3ec72f..7cb119bf32 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index 130dfd45e7..8a6545a97b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs index 04cbf171f6..59ba9cd449 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreboardTime.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Extensions; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index afaed85250..9dc2ce204f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs index e730496b5c..67b11af0c1 100644 --- a/osu.Game/Overlays/BreadcrumbControlOverlayHeader.cs +++ b/osu.Game/Overlays/BreadcrumbControlOverlayHeader.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Changelog/ChangelogEntry.cs b/osu.Game/Overlays/Changelog/ChangelogEntry.cs index ab671d9c86..06ec2043f9 100644 --- a/osu.Game/Overlays/Changelog/ChangelogEntry.cs +++ b/osu.Game/Overlays/Changelog/ChangelogEntry.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Diagnostics; using System.Net; @@ -26,10 +24,10 @@ namespace osu.Game.Overlays.Changelog private readonly APIChangelogEntry entry; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; private FontUsage fontLarge; private FontUsage fontMedium; diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 4b784c7a28..3a648f66cf 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 4aded1dd59..012ccf8f64 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs index 155cbc7d65..e3dd989e2d 100644 --- a/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.cs +++ b/osu.Game/Overlays/Changelog/ChangelogUpdateStreamControl.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. -#nullable disable - using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Changelog diff --git a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs index 090f7835ae..6d8b21a7c5 100644 --- a/osu.Game/Overlays/Chat/ChannelScrollContainer.cs +++ b/osu.Game/Overlays/Chat/ChannelScrollContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs b/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs index 88e7d00476..45024f25db 100644 --- a/osu.Game/Overlays/Comments/Buttons/ChevronButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/ChevronButton.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics.Containers; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs index d9576f5b72..400820ddd9 100644 --- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs +++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -26,7 +24,7 @@ namespace osu.Game.Overlays.Comments.Buttons } [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; private readonly ChevronIcon icon; private readonly Box background; diff --git a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs index 9cc20caa05..278cef9112 100644 --- a/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs +++ b/osu.Game/Overlays/Comments/CommentMarkdownContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax; using osu.Framework.Graphics.Containers.Markdown; using osu.Game.Graphics.Containers.Markdown; diff --git a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs b/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs index 1770fcb269..50bd08b66b 100644 --- a/osu.Game/Overlays/Comments/CommentsShowMoreButton.cs +++ b/osu.Game/Overlays/Comments/CommentsShowMoreButton.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs b/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs index 6adb388185..fa366f38c3 100644 --- a/osu.Game/Overlays/Comments/DeletedCommentsCounter.cs +++ b/osu.Game/Overlays/Comments/DeletedCommentsCounter.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Comments/HeaderButton.cs b/osu.Game/Overlays/Comments/HeaderButton.cs index de99cd6cc8..1a26148e49 100644 --- a/osu.Game/Overlays/Comments/HeaderButton.cs +++ b/osu.Game/Overlays/Comments/HeaderButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs index 5cbeb8f306..0f4697e33c 100644 --- a/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.cs +++ b/osu.Game/Overlays/Dashboard/DashboardOverlayHeader.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs b/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs index 3bb42ec953..4abece9a8d 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendStream.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendStream.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. -#nullable disable - namespace osu.Game.Overlays.Dashboard.Friends { public class FriendStream diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs index 785eef38ad..2aea631b7c 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendsOnlineStatusItem.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. -#nullable disable - using System; using osu.Framework.Extensions; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs index 21bc5b8203..dc291f1a44 100644 --- a/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs +++ b/osu.Game/Overlays/Dashboard/Friends/OnlineStatus.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs index db8510325c..3f31ceee1a 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserListToolbar.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; diff --git a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs index 886ed08af2..db01e1f266 100644 --- a/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.cs +++ b/osu.Game/Overlays/Dashboard/Friends/UserSortTabControl.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs index 0282ba8785..4eac1a1d29 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardBeatmapListing.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs index fef33bdf5a..9e9c22fea2 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardNewBeatmapPanel.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs index 54d95c994b..a08a1fef6f 100644 --- a/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/DashboardPopularBeatmapPanel.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs index af36f71dd2..a0e22a0faf 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableBeatmapList.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs index 8a60d8568c..a22ce8acb0 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawableNewBeatmapList.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs index aab99d0ed3..b321057ef2 100644 --- a/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.cs +++ b/osu.Game/Overlays/Dashboard/Home/DrawablePopularBeatmapList.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Localisation; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs b/osu.Game/Overlays/Dashboard/Home/HomePanel.cs index 8023c093aa..93db9978a7 100644 --- a/osu.Game/Overlays/Dashboard/Home/HomePanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/HomePanel.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs index dabe65964a..86babf82b5 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/FeaturedNewsItemPanel.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs index 9b27d1a193..9319d0dabd 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsGroupItem.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs index fa59f38690..f0d51be52a 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsItemGroupPanel.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs index 1960e0372e..d6f8499c85 100644 --- a/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.cs +++ b/osu.Game/Overlays/Dashboard/Home/News/NewsTitleLink.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/DashboardOverlay.cs b/osu.Game/Overlays/DashboardOverlay.cs index 527ac1689b..2f96421531 100644 --- a/osu.Game/Overlays/DashboardOverlay.cs +++ b/osu.Game/Overlays/DashboardOverlay.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. -#nullable disable - using System; using osu.Game.Overlays.Dashboard; using osu.Game.Overlays.Dashboard.Friends; diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index f5a7e9e43d..9969677826 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs index 91a19add21..499dab3a1d 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.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. -#nullable disable - using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs index f4289c66f1..c55226b147 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs index eb4a0f0709..968657755f 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogOkButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index 032821f215..b58a3b929b 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -29,7 +27,7 @@ namespace osu.Game.Overlays protected virtual Color4 BackgroundColour => ColourProvider.Background5; [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; [Cached] protected readonly OverlayColourProvider ColourProvider; diff --git a/osu.Game/Overlays/INamedOverlayComponent.cs b/osu.Game/Overlays/INamedOverlayComponent.cs index e9d01a55e3..65664b12e7 100644 --- a/osu.Game/Overlays/INamedOverlayComponent.cs +++ b/osu.Game/Overlays/INamedOverlayComponent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; namespace osu.Game.Overlays diff --git a/osu.Game/Overlays/INotificationOverlay.cs b/osu.Game/Overlays/INotificationOverlay.cs index b9ac466229..93346cb0ee 100644 --- a/osu.Game/Overlays/INotificationOverlay.cs +++ b/osu.Game/Overlays/INotificationOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Overlays.Notifications; diff --git a/osu.Game/Overlays/IOverlayManager.cs b/osu.Game/Overlays/IOverlayManager.cs index 0318b2b3a0..d771308e34 100644 --- a/osu.Game/Overlays/IOverlayManager.cs +++ b/osu.Game/Overlays/IOverlayManager.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index 0bdfa82517..78b5271ca0 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs index 817b6beac3..0e60fc3414 100644 --- a/osu.Game/Overlays/Mods/DeselectAllModsButton.cs +++ b/osu.Game/Overlays/Mods/DeselectAllModsButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs index ee4f932326..9e16aa926f 100644 --- a/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs +++ b/osu.Game/Overlays/Mods/DifficultyMultiplierDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs index 93279b6e1c..26c5b2ac49 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingModPanel.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -19,7 +17,7 @@ namespace osu.Game.Overlays.Mods private readonly BindableBool incompatible = new BindableBool(); [Resolved] - private Bindable> selectedMods { get; set; } + private Bindable> selectedMods { get; set; } = null!; public IncompatibilityDisplayingModPanel(ModState modState) : base(modState) diff --git a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs index 1723634774..2f82711162 100644 --- a/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs +++ b/osu.Game/Overlays/Mods/IncompatibilityDisplayingTooltip.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -24,7 +22,7 @@ namespace osu.Game.Overlays.Mods private readonly Bindable> incompatibleMods = new Bindable>(); [Resolved] - private Bindable ruleset { get; set; } + private Bindable ruleset { get; set; } = null!; public IncompatibilityDisplayingTooltip() { diff --git a/osu.Game/Overlays/Mods/ModSettingsArea.cs b/osu.Game/Overlays/Mods/ModSettingsArea.cs index f11fef1299..fe1d683d59 100644 --- a/osu.Game/Overlays/Mods/ModSettingsArea.cs +++ b/osu.Game/Overlays/Mods/ModSettingsArea.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -32,7 +30,7 @@ namespace osu.Game.Overlays.Mods private readonly FillFlowContainer modSettingsFlow; [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; public ModSettingsArea() { diff --git a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs index 827caf0467..b7d265c448 100644 --- a/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs +++ b/osu.Game/Overlays/Music/MusicKeyBindingHandler.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; @@ -24,16 +22,16 @@ namespace osu.Game.Overlays.Music public partial class MusicKeyBindingHandler : Component, IKeyBindingHandler { [Resolved] - private IBindable beatmap { get; set; } + private IBindable beatmap { get; set; } = null!; [Resolved] - private MusicController musicController { get; set; } - - [Resolved(canBeNull: true)] - private OnScreenDisplay onScreenDisplay { get; set; } + private MusicController musicController { get; set; } = null!; [Resolved] - private OsuGame game { get; set; } + private OnScreenDisplay? onScreenDisplay { get; set; } + + [Resolved] + private OsuGame game { get; set; } = null!; public bool OnPressed(KeyBindingPressEvent e) { diff --git a/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs b/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs index ae59fbb35e..fa9a2e3972 100644 --- a/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.cs +++ b/osu.Game/Overlays/Music/NowPlayingCollectionDropdown.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. -#nullable disable - using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/News/NewsPostBackground.cs b/osu.Game/Overlays/News/NewsPostBackground.cs index 05f8a639fa..663747255a 100644 --- a/osu.Game/Overlays/News/NewsPostBackground.cs +++ b/osu.Game/Overlays/News/NewsPostBackground.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs index 7d0d07fc1b..758eea93d4 100644 --- a/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleErrorNotification.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Sprites; namespace osu.Game.Overlays.Notifications diff --git a/osu.Game/Overlays/OSD/Toast.cs b/osu.Game/Overlays/OSD/Toast.cs index ff8696c04f..7df534d90d 100644 --- a/osu.Game/Overlays/OSD/Toast.cs +++ b/osu.Game/Overlays/OSD/Toast.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. -#nullable disable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OnlineOverlay.cs b/osu.Game/Overlays/OnlineOverlay.cs index 8b7a82f899..051873b394 100644 --- a/osu.Game/Overlays/OnlineOverlay.cs +++ b/osu.Game/Overlays/OnlineOverlay.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/OverlayColourProvider.cs b/osu.Game/Overlays/OverlayColourProvider.cs index d7581960f4..a4f6527024 100644 --- a/osu.Game/Overlays/OverlayColourProvider.cs +++ b/osu.Game/Overlays/OverlayColourProvider.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. -#nullable disable - using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 93de463204..827a7749af 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/OverlayHeaderBackground.cs b/osu.Game/Overlays/OverlayHeaderBackground.cs index a089001385..7e264ee196 100644 --- a/osu.Game/Overlays/OverlayHeaderBackground.cs +++ b/osu.Game/Overlays/OverlayHeaderBackground.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/OverlayRulesetSelector.cs b/osu.Game/Overlays/OverlayRulesetSelector.cs index 9205a14d9f..e10bcda734 100644 --- a/osu.Game/Overlays/OverlayRulesetSelector.cs +++ b/osu.Game/Overlays/OverlayRulesetSelector.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/OverlayRulesetTabItem.cs b/osu.Game/Overlays/OverlayRulesetTabItem.cs index d5c70a46d0..6d318820b3 100644 --- a/osu.Game/Overlays/OverlayRulesetTabItem.cs +++ b/osu.Game/Overlays/OverlayRulesetTabItem.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -35,7 +33,7 @@ namespace osu.Game.Overlays protected override Container Content { get; } [Resolved] - private OverlayColourProvider colourProvider { get; set; } + private OverlayColourProvider colourProvider { get; set; } = null!; private readonly Drawable icon; diff --git a/osu.Game/Overlays/OverlaySidebar.cs b/osu.Game/Overlays/OverlaySidebar.cs index 93e5e83ffc..b08a9d08a4 100644 --- a/osu.Game/Overlays/OverlaySidebar.cs +++ b/osu.Game/Overlays/OverlaySidebar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/CountryFilter.cs b/osu.Game/Overlays/Rankings/CountryFilter.cs index 525816f8fd..c4e281402b 100644 --- a/osu.Game/Overlays/Rankings/CountryFilter.cs +++ b/osu.Game/Overlays/Rankings/CountryFilter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/CountryPill.cs b/osu.Game/Overlays/Rankings/CountryPill.cs index 5efa9d12f0..294b6df34d 100644 --- a/osu.Game/Overlays/Rankings/CountryPill.cs +++ b/osu.Game/Overlays/Rankings/CountryPill.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Rankings/RankingsScope.cs b/osu.Game/Overlays/Rankings/RankingsScope.cs index 2644fee58b..3392db9360 100644 --- a/osu.Game/Overlays/Rankings/RankingsScope.cs +++ b/osu.Game/Overlays/Rankings/RankingsScope.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs b/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs index 9e73c3adb0..b13ecc190e 100644 --- a/osu.Game/Overlays/Rankings/RankingsSortTabControl.cs +++ b/osu.Game/Overlays/Rankings/RankingsSortTabControl.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. -#nullable disable - using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 3be5cc994c..fb3e58d2ac 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; @@ -68,8 +66,8 @@ namespace osu.Game.Overlays.Rankings.Tables private partial class CountryName : LinkFlowContainer { - [Resolved(canBeNull: true)] - private RankingsOverlay rankings { get; set; } + [Resolved] + private RankingsOverlay? rankings { get; set; } public CountryName(CountryCode countryCode) : base(t => t.Font = OsuFont.GetFont(size: 12)) diff --git a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs index 19ed3afdca..f13fbd66ec 100644 --- a/osu.Game/Overlays/Rankings/Tables/PerformanceTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/PerformanceTable.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs b/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs index 0da3fba8cc..9005334dda 100644 --- a/osu.Game/Overlays/Rankings/Tables/ScoresTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/ScoresTable.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs index 54ec45f4ff..8c50e72207 100644 --- a/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs +++ b/osu.Game/Overlays/Rankings/Tables/TableRowBackground.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs index 248b4d339a..42b042ae75 100644 --- a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs +++ b/osu.Game/Overlays/Settings/DangerousSettingsButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/ISettingsItem.cs b/osu.Game/Overlays/Settings/ISettingsItem.cs index 509fc1ab0d..b77a8d9268 100644 --- a/osu.Game/Overlays/Settings/ISettingsItem.cs +++ b/osu.Game/Overlays/Settings/ISettingsItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/OutlinedTextBox.cs b/osu.Game/Overlays/Settings/OutlinedTextBox.cs index 56b662ecf0..ef2039f8bf 100644 --- a/osu.Game/Overlays/Settings/OutlinedTextBox.cs +++ b/osu.Game/Overlays/Settings/OutlinedTextBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index fc354027c1..6b5c769853 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index 7066be4f92..2bb5fa983f 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 542d5bc8fd..fb3d486776 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 509410fbb1..33a6f4c673 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.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. -#nullable disable - using osu.Framework.Development; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 6c2bfedba0..1044810bdc 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index bf0a48d2c2..0d2d163859 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.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. -#nullable disable - using System; using System.Threading; using System.Threading.Tasks; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs index 00eb6fa62c..467c988020 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/AudioSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs index 09e5f3e163..048351b4cb 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BackgroundSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs index da5fc519e6..9efdfa9955 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/BeatmapSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 96d458a942..c7f5aa5665 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs index c67c14bb43..e7c83159cd 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/HUDSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs index 9291dfe923..c245a1a9ea 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/InputSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index f6b3c12487..79a971510f 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index ae6145752b..b60689b611 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs index 8054b27de5..c7180ec51b 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/ScreenshotSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 323cdaf14d..98f6908512 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs index 2b478f6af3..a93e6c37af 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/BindingSettings.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs index 30429c84f0..7296003c7f 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingPanel.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 19f0d0f7d1..0ed7de9d3f 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 0647068da7..a8f19cc91d 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs index 633bf8c5a5..fcbc603c83 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectoryLocationDialog.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. -#nullable disable - using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; @@ -15,7 +13,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance public partial class StableDirectoryLocationDialog : PopupDialog { [Resolved] - private IPerformFromScreenRunner performer { get; set; } + private IPerformFromScreenRunner performer { get; set; } = null!; public StableDirectoryLocationDialog(TaskCompletionSource taskCompletionSource) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs index 048f3ee683..1f62077f20 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.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. -#nullable disable - using System.IO; using System.Linq; using System.Threading.Tasks; diff --git a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs index dc6743c042..e7b6aa56a8 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/AlertsAndPrivacySettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs index 33748d0f5e..3d0fac32cf 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/IntegrationSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index d0707a434a..d34b01ebf3 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 775c6f9839..c8faa3b697 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs index 20d77bef0d..c73831d8d1 100644 --- a/osu.Game/Overlays/Settings/Sections/SizeSlider.cs +++ b/osu.Game/Overlays/Settings/Sections/SizeSlider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Globalization; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs index 2e8d005401..844b8aeac6 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/GeneralSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs index d3303e409c..addf5ce163 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterface/SongSelectSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs index 0926574a54..2ec9e32ea9 100644 --- a/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/UserInterfaceSection.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index a413bcf220..f8edcaf53d 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 62dd4f2905..cf6bc30f85 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 9ab0fa7ad8..ffb955f3bd 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Development; using osu.Framework.Graphics; @@ -83,7 +81,7 @@ namespace osu.Game.Overlays.Settings private readonly string version; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; public BuildDisplay(string version) { diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index f2b84c4ba9..8d155fd01e 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/SettingsNumberBox.cs b/osu.Game/Overlays/Settings/SettingsNumberBox.cs index 97b8f6de60..7912890528 100644 --- a/osu.Game/Overlays/Settings/SettingsNumberBox.cs +++ b/osu.Game/Overlays/Settings/SettingsNumberBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsSidebar.cs b/osu.Game/Overlays/Settings/SettingsSidebar.cs index 36411e01cc..06bc2fd788 100644 --- a/osu.Game/Overlays/Settings/SettingsSidebar.cs +++ b/osu.Game/Overlays/Settings/SettingsSidebar.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index e1483d4202..6c81fece13 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index eda18abaef..87772eb18c 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.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. -#nullable disable - using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index 3f9fa06384..7fc7e1a97b 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.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. -#nullable disable - using System; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index aec0509394..5fe0e1afc0 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; @@ -14,7 +12,7 @@ namespace osu.Game.Overlays.Settings protected const double FADE_DURATION = 500; [Resolved] - protected OverlayColourProvider ColourProvider { get; private set; } + protected OverlayColourProvider ColourProvider { get; private set; } = null!; protected SidebarButton() : base(HoverSampleSet.ButtonSidebar) diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index 2b87535708..edfe38b2da 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/Toolbar/ClockDisplay.cs b/osu.Game/Overlays/Toolbar/ClockDisplay.cs index 088631f8d6..c72c92b61b 100644 --- a/osu.Game/Overlays/Toolbar/ClockDisplay.cs +++ b/osu.Game/Overlays/Toolbar/ClockDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs index efcb011293..247be553e1 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarBeatmapListingButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 4193e52584..e181322dda 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -39,10 +37,10 @@ namespace osu.Game.Overlays.Toolbar } [Resolved] - private TextureStore textures { get; set; } + private TextureStore textures { get; set; } = null!; [Resolved] - private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } + private ReadableKeyCombinationProvider keyCombinationProvider { get; set; } = null!; public void SetIcon(string texture) => SetIcon(new Sprite @@ -81,7 +79,7 @@ namespace osu.Game.Overlays.Toolbar protected FillFlowContainer Flow; [Resolved] - private RealmAccess realm { get; set; } + private RealmAccess realm { get; set; } = null!; protected ToolbarButton() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs index 30e32d831c..06f171b1f2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChangelogButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 7bb94067ab..126f8383ce 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index dba4e8feb6..ba2c8282c5 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Input.Bindings; using osu.Game.Localisation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs index bdcf6c3fec..13900dffa9 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNewsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNewsButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 3dfec2cba0..1871371750 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs index ddbf4889b6..3e94ff90c5 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRankingsButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs index 07f7d52545..7d75acb9d1 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetTabButton.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index 6ebf2a4c02..78df060252 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index a8a88813d2..8e6a5fdb78 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; diff --git a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs index 49e6be7978..e60aea53c3 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/VersionManager.cs b/osu.Game/Overlays/VersionManager.cs index 0e74cada29..71f8fc05aa 100644 --- a/osu.Game/Overlays/VersionManager.cs +++ b/osu.Game/Overlays/VersionManager.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Development; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index c83ad4ac0d..1dc8d754b7 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 34fbec93b7..153f7f5412 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs index 7c36caa62f..9107ad342b 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using Markdig.Extensions.CustomContainers; using Markdig.Extensions.Yaml; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs index 71c2df538d..cfeb4de19c 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImage.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax.Inlines; using osu.Game.Graphics.Containers.Markdown; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs index 641c6242b6..bb7c232a13 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownImageBlock.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Syntax.Inlines; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,7 +14,7 @@ namespace osu.Game.Overlays.Wiki.Markdown public partial class WikiMarkdownImageBlock : FillFlowContainer { [Resolved] - private IMarkdownTextFlowComponent parentFlowComponent { get; set; } + private IMarkdownTextFlowComponent parentFlowComponent { get; set; } = null!; private readonly LinkInline linkInline; diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs index a40bd14878..1ab35b1972 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiNoticeContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using Markdig.Extensions.Yaml; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -80,7 +78,7 @@ namespace osu.Game.Overlays.Wiki.Markdown private partial class NoticeBox : Container { [Resolved] - private IMarkdownTextFlowComponent parentFlowComponent { get; set; } + private IMarkdownTextFlowComponent parentFlowComponent { get; set; } = null!; public LocalisableString Text { get; set; } diff --git a/osu.Game/Performance/HighPerformanceSession.cs b/osu.Game/Performance/HighPerformanceSession.cs index c113e7a342..07b5e7da98 100644 --- a/osu.Game/Performance/HighPerformanceSession.cs +++ b/osu.Game/Performance/HighPerformanceSession.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs index dde1af6461..1b77e45891 100644 --- a/osu.Game/Properties/AssemblyInfo.cs +++ b/osu.Game/Properties/AssemblyInfo.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. -#nullable disable - using System.Runtime.CompilerServices; // We publish our internal attributes to other sub-projects of the framework. diff --git a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs index 15b90e5147..e8c4c71913 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.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. -#nullable disable - using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 38a35ddb3b..f5e826f8c7 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Scoring; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs b/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs index 76dfca3db7..a654652ef8 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceDisplayAttribute.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Rulesets.Difficulty { /// diff --git a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs index 44abbaaf41..8b8892113b 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/Skill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs index 6abde64eb7..8fab61ed62 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs index 4beba22e05..b43a272324 100644 --- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index 5f5aba26bb..dc73e35923 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Edit.Checks; diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs index 20ee409937..324f2068e9 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -25,7 +23,7 @@ namespace osu.Game.Rulesets.Edit private readonly DrawableRuleset drawableRuleset; [Resolved] - private EditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } = null!; public DrawableEditorRulesetWrapper(DrawableRuleset drawableRuleset) { @@ -43,8 +41,8 @@ namespace osu.Game.Rulesets.Edit Playfield.DisplayJudgements.Value = false; } - [Resolved(canBeNull: true)] - private IEditorChangeHandler changeHandler { get; set; } + [Resolved] + private IEditorChangeHandler? changeHandler { get; set; } protected override void LoadComplete() { diff --git a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs index 312ba62b61..f30f5148fe 100644 --- a/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs +++ b/osu.Game/Rulesets/Edit/EditorToolboxGroup.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Overlays; diff --git a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs index 7bf10f6beb..36cbf49885 100644 --- a/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs +++ b/osu.Game/Rulesets/Edit/ExpandingToolboxContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Graphics.Containers; diff --git a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs index 826bffef5f..7fc9772598 100644 --- a/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/IBeatmapVerifier.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Edit.Checks.Components; diff --git a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs index 6fbd994e23..da44b42831 100644 --- a/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IDistanceSnapProvider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs b/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs index ad129e068d..002a0aafe6 100644 --- a/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs +++ b/osu.Game/Rulesets/Edit/IPositionSnapProvider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osuTK; diff --git a/osu.Game/Rulesets/Edit/SnapType.cs b/osu.Game/Rulesets/Edit/SnapType.cs index f5f9ab0437..cf743f6ace 100644 --- a/osu.Game/Rulesets/Edit/SnapType.cs +++ b/osu.Game/Rulesets/Edit/SnapType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Rulesets.Edit diff --git a/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs index f08b43e72a..2c78561d31 100644 --- a/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 770f656e8f..99dce82ec2 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.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. -#nullable disable - using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index 34d1f1f6e9..f001a4cd92 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using JetBrains.Annotations; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs index 9728a4393b..d3c29d90ce 100644 --- a/osu.Game/Rulesets/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.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. -#nullable disable - namespace osu.Game.Rulesets.Objects { public abstract class HitObjectParser diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index 9facfec96f..12b4812824 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs index 62726019bb..fb1afed3b4 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index cccb66d92b..014494ec54 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Catch diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs index d95f97624d..54dbd28c76 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 6f1968b41d..386eb8d3ee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.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. -#nullable disable - using osuTK; using osu.Game.Audio; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index b6594d0206..2fa4766c1d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index dcbaf22c51..c05aaceb9c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Mania diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index 33b390e3ba..069366bad3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index 2f8e9dd352..e947690668 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index d49e9fe9db..e9e5ca8c94 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index ec8d7971ec..1d5ecb1ef3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.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. -#nullable disable - using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects.Legacy.Taiko diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs index d32a7cb16d..7013d32cbc 100644 --- a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index 13cc6361cf..028f8b6839 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Collections.Specialized; diff --git a/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs b/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs index ee860e82e2..7a9f6948b0 100644 --- a/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs +++ b/osu.Game/Rulesets/Objects/SyntheticHitObjectEntry.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Objects diff --git a/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs b/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs index 89ee5022bf..691418ec48 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDisplayColour.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osuTK.Graphics; diff --git a/osu.Game/Rulesets/Objects/Types/IHasPath.cs b/osu.Game/Rulesets/Objects/Types/IHasPath.cs index 46834a55dd..5a3f270f54 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPath.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPath.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Rulesets.Objects.Types { public interface IHasPath : IHasDistance diff --git a/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs index 536707e95f..279946b44e 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPathWithRepeats.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. -#nullable disable - using osuTK; namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs index 281f619ba5..8948fe59a9 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPosition.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. -#nullable disable - using osuTK; namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 821a6de520..2a4215b960 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.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. -#nullable disable - using osu.Game.Audio; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/RulesetLoadException.cs b/osu.Game/Rulesets/RulesetLoadException.cs index 6fee8f446b..803c756b41 100644 --- a/osu.Game/Rulesets/RulesetLoadException.cs +++ b/osu.Game/Rulesets/RulesetLoadException.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Rulesets diff --git a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs index af6e825b06..422bf8ea79 100644 --- a/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/AccumulatingHealthProcessor.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Rulesets.Scoring { /// diff --git a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs index 2fde73d5a2..b4bdd8a1ea 100644 --- a/osu.Game/Rulesets/Scoring/HitEventExtensions.cs +++ b/osu.Game/Rulesets/Scoring/HitEventExtensions.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Scoring/HitWindows.cs b/osu.Game/Rulesets/Scoring/HitWindows.cs index 99129fcf96..2d008b58ba 100644 --- a/osu.Game/Rulesets/Scoring/HitWindows.cs +++ b/osu.Game/Rulesets/Scoring/HitWindows.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. -#nullable disable - using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs index cbce397d1e..0ce3f76384 100644 --- a/osu.Game/Rulesets/UI/GameplayCursorContainer.cs +++ b/osu.Game/Rulesets/UI/GameplayCursorContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Rulesets/UI/IHitObjectContainer.cs b/osu.Game/Rulesets/UI/IHitObjectContainer.cs index 74fd7dee81..6dcb0944be 100644 --- a/osu.Game/Rulesets/UI/IHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/IHitObjectContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs index b842e708b0..f5739ee525 100644 --- a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs +++ b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/JudgementContainer.cs b/osu.Game/Rulesets/UI/JudgementContainer.cs index 7181e80206..886dd34fc7 100644 --- a/osu.Game/Rulesets/UI/JudgementContainer.cs +++ b/osu.Game/Rulesets/UI/JudgementContainer.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. -#nullable disable - using System; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs index 0f440adef8..9339602ac6 100644 --- a/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game/Rulesets/UI/PlayfieldAdjustmentContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/UI/PlayfieldBorder.cs b/osu.Game/Rulesets/UI/PlayfieldBorder.cs index 18bd5b9b93..e87421fc88 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorder.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorder.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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs b/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs index 79f3a2ca84..503bc8fd99 100644 --- a/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs +++ b/osu.Game/Rulesets/UI/PlayfieldBorderStyle.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Localisation; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs index c957a84eb1..b0bde50cae 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.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. -#nullable disable - namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public class ConstantScrollAlgorithm : IScrollAlgorithm diff --git a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs index e00f0ffe5d..cd85932599 100644 --- a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs +++ b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling.Algorithms; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 7d141113df..1a17349d12 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; @@ -20,7 +18,7 @@ namespace osu.Game.Rulesets.UI.Scrolling public new ScrollingHitObjectContainer HitObjectContainer => (ScrollingHitObjectContainer)base.HitObjectContainer; [Resolved] - public IScrollingInfo ScrollingInfo { get; private set; } + public IScrollingInfo ScrollingInfo { get; private set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Scoring/HitResultDisplayStatistic.cs b/osu.Game/Scoring/HitResultDisplayStatistic.cs index 20deff4875..59e074fb5f 100644 --- a/osu.Game/Scoring/HitResultDisplayStatistic.cs +++ b/osu.Game/Scoring/HitResultDisplayStatistic.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Scoring/IScoreInfo.cs b/osu.Game/Scoring/IScoreInfo.cs index ffc30384d2..3644d099d9 100644 --- a/osu.Game/Scoring/IScoreInfo.cs +++ b/osu.Game/Scoring/IScoreInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Game.Beatmaps; using osu.Game.Database; diff --git a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs index 52dec20b32..e298d51ccb 100644 --- a/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs +++ b/osu.Game/Scoring/Legacy/ScoreInfoExtensions.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 06bc3edd37..3323706ac1 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Replays; using osu.Game.Utils; diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index a1916953c4..327e4191d7 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index ca0dad83c8..6ebc97ebbb 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs index 09778c5cdf..742d149580 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 3c8ed6fe76..14331c1978 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.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. -#nullable disable - using osu.Game.Graphics.Backgrounds; namespace osu.Game.Screens.Backgrounds diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs index 67b346fb64..56df0552cc 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorPresetCollection.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs index 602ed6f627..e33ef66007 100644 --- a/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/CircularDistanceSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -19,7 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public abstract partial class CircularDistanceSnapGrid : DistanceSnapGrid { [Resolved] - private EditorClock editorClock { get; set; } + private EditorClock editorClock { get; set; } = null!; protected CircularDistanceSnapGrid(HitObject referenceObject, Vector2 startPosition, double startTime, double? endTime = null) : base(referenceObject, startPosition, startTime, endTime) @@ -127,10 +125,10 @@ namespace osu.Game.Screens.Edit.Compose.Components private partial class Ring : CircularProgress { [Resolved] - private IDistanceSnapProvider snapProvider { get; set; } + private IDistanceSnapProvider snapProvider { get; set; } = null!; - [Resolved(canBeNull: true)] - private EditorClock editorClock { get; set; } + [Resolved] + private EditorClock? editorClock { get; set; } private readonly HitObject referenceObject; diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs index d618541685..a73278a61e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -28,7 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public const string HIT_BANK_AUTO = "auto"; [Resolved] - protected EditorBeatmap EditorBeatmap { get; private set; } + protected EditorBeatmap EditorBeatmap { get; private set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs index 849a526556..0edaaf9825 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,7 +16,7 @@ namespace osu.Game.Screens.Edit.Compose.Components public sealed partial class HitObjectOrderedSelectionContainer : Container> { [Resolved] - private EditorBeatmap editorBeatmap { get; set; } + private EditorBeatmap editorBeatmap { get; set; } = null!; protected override void LoadComplete() { diff --git a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs index 46d948f8b6..4515e4d7be 100644 --- a/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs +++ b/osu.Game/Screens/Edit/Compose/Components/MoveSelectionEvent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Rulesets.Edit; using osuTK; diff --git a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs index 06b73c8af4..063ea23281 100644 --- a/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs +++ b/osu.Game/Screens/Edit/Compose/Components/RectangularPositionSnapGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs index 44daf70577..aee3cffbfd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index c94de0fe67..767854252e 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs index 29983c9cbf..cd97b293ba 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Specialized; using System.Diagnostics; using System.Linq; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs index 257cc9e635..fc3ef92bf5 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineControlPointGroup.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs index a1dfd0718b..c16a948822 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineDragBox.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -20,7 +18,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private double? startTime; [Resolved] - private Timeline timeline { get; set; } + private Timeline timeline { get; set; } = null!; protected override Drawable CreateBox() => new Box { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs index 6a0688e19c..7e7bef8cf2 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineTickDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Diagnostics; using osu.Framework.Allocation; @@ -21,19 +19,19 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public partial class TimelineTickDisplay : TimelinePart { [Resolved] - private EditorBeatmap beatmap { get; set; } + private EditorBeatmap beatmap { get; set; } = null!; [Resolved] - private Bindable working { get; set; } + private Bindable working { get; set; } = null!; [Resolved] - private BindableBeatDivisor beatDivisor { get; set; } - - [Resolved(CanBeNull = true)] - private IEditorChangeHandler changeHandler { get; set; } + private BindableBeatDivisor beatDivisor { get; set; } = null!; [Resolved] - private OsuColour colours { get; set; } + private IEditorChangeHandler? changeHandler { get; set; } + + [Resolved] + private OsuColour colours { get; set; } = null!; public TimelineTickDisplay() { @@ -72,8 +70,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline /// private float? nextMaxTick; - [Resolved(canBeNull: true)] - private Timeline timeline { get; set; } + [Resolved] + private Timeline? timeline { get; set; } protected override void Update() { diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs index 4191864e5c..2a4ad66918 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimingPointPiece.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 951f4129d4..848c8f9a0f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -41,8 +39,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private bool isZoomSetUp; - [Resolved(canBeNull: true)] - private IFrameBasedClock editorClock { get; set; } + [Resolved] + private IFrameBasedClock? editorClock { get; set; } private readonly LayoutValue zoomedContentWidthCache = new LayoutValue(Invalidation.DrawSize); diff --git a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs index 46d9555e0c..57960a76a1 100644 --- a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs +++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Screens/Edit/EditorClipboard.cs b/osu.Game/Screens/Edit/EditorClipboard.cs index f749f4bad6..af303618fb 100644 --- a/osu.Game/Screens/Edit/EditorClipboard.cs +++ b/osu.Game/Screens/Edit/EditorClipboard.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; namespace osu.Game.Screens.Edit diff --git a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs index 1c083b4fab..510c27e8c6 100644 --- a/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs +++ b/osu.Game/Screens/Edit/EditorRoundedScreenSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 069a5490bb..b39c0cf5f3 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -17,7 +15,7 @@ namespace osu.Game.Screens.Edit public abstract partial class EditorScreen : VisibilityContainer { [Resolved] - protected EditorBeatmap EditorBeatmap { get; private set; } + protected EditorBeatmap EditorBeatmap { get; private set; } = null!; protected override Container Content => content; private readonly Container content; diff --git a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs index a74d97cdc7..bb151e4a45 100644 --- a/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs +++ b/osu.Game/Screens/Edit/GameplayTest/EditorPlayerLoader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; @@ -14,7 +12,7 @@ namespace osu.Game.Screens.Edit.GameplayTest public partial class EditorPlayerLoader : PlayerLoader { [Resolved] - private OsuLogo osuLogo { get; set; } + private OsuLogo osuLogo { get; set; } = null!; public EditorPlayerLoader(Editor editor) : base(() => new EditorPlayer(editor)) diff --git a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs index 5a5572b508..eb1df43ddd 100644 --- a/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs +++ b/osu.Game/Screens/Edit/GameplayTest/SaveBeforeGameplayTestDialog.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics.Sprites; using osu.Game.Overlays.Dialog; diff --git a/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs index 3e1e0c4cfe..ee64a53301 100644 --- a/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs +++ b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using JetBrains.Annotations; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs index 5b6eea098c..b16e3750bf 100644 --- a/osu.Game/Screens/Edit/Verify/InterpretationSection.cs +++ b/osu.Game/Screens/Edit/Verify/InterpretationSection.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Edit/Verify/IssueSettings.cs b/osu.Game/Screens/Edit/Verify/IssueSettings.cs index e8275c3684..6d3c0520a2 100644 --- a/osu.Game/Screens/Edit/Verify/IssueSettings.cs +++ b/osu.Game/Screens/Edit/Verify/IssueSettings.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs index 5b1d7142e4..9dc0ea0d07 100644 --- a/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs +++ b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/IHandlePresentBeatmap.cs b/osu.Game/Screens/IHandlePresentBeatmap.cs index 62cd2c3d3e..323e3b1c0c 100644 --- a/osu.Game/Screens/IHandlePresentBeatmap.cs +++ b/osu.Game/Screens/IHandlePresentBeatmap.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/IHasSubScreenStack.cs b/osu.Game/Screens/IHasSubScreenStack.cs index 325702313b..0fcf21ef2b 100644 --- a/osu.Game/Screens/IHasSubScreenStack.cs +++ b/osu.Game/Screens/IHasSubScreenStack.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Screens; namespace osu.Game.Screens diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index a5739a41b1..cceede5424 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index bc2f6ea00f..64b9bd52e8 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Menu/SongTicker.cs b/osu.Game/Screens/Menu/SongTicker.cs index bac7e15461..3bdc0efe19 100644 --- a/osu.Game/Screens/Menu/SongTicker.cs +++ b/osu.Game/Screens/Menu/SongTicker.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,7 +18,7 @@ namespace osu.Game.Screens.Menu private const int fade_duration = 800; [Resolved] - private Bindable beatmap { get; set; } + private Bindable beatmap { get; set; } = null!; private readonly OsuSpriteText title, artist; diff --git a/osu.Game/Screens/Menu/StorageErrorDialog.cs b/osu.Game/Screens/Menu/StorageErrorDialog.cs index ba05ad8b76..dd43289873 100644 --- a/osu.Game/Screens/Menu/StorageErrorDialog.cs +++ b/osu.Game/Screens/Menu/StorageErrorDialog.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; @@ -15,7 +13,7 @@ namespace osu.Game.Screens.Menu public partial class StorageErrorDialog : PopupDialog { [Resolved] - private IDialogOverlay dialogOverlay { get; set; } + private IDialogOverlay dialogOverlay { get; set; } = null!; public StorageErrorDialog(OsuStorage storage, OsuStorageError error) { diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs index 7c48fc0871..41b994ea32 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapDetailAreaPlaylistTabItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Screens.Select; namespace osu.Game.Screens.OnlinePlay.Components diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs index ebcc08360e..7c57f5b4f5 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -49,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Components } [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; private void updateText() { diff --git a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs index 3f7f38f3bc..97716759c3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DisableableTabControl.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs index 77e461ce41..d24ad74a68 100644 --- a/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs +++ b/osu.Game/Screens/OnlinePlay/Components/DrawableGameType.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; @@ -41,7 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Components } [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs index 0e2ce6703f..09a3602cdd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs index f8dcd7b75d..fc86cbbbdd 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OverlinedPlaylistHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Components diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs index 4fdf41d0f7..e6999771d3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs index 772c8c4278..813e243449 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ReadyButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs index 395a77b9e6..0ba7f20f1c 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomPollingComponent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Online; using osu.Game.Online.API; @@ -12,9 +10,9 @@ namespace osu.Game.Screens.OnlinePlay.Components public abstract partial class RoomPollingComponent : PollingComponent { [Resolved] - protected IAPIProvider API { get; private set; } + protected IAPIProvider API { get; private set; } = null!; [Resolved] - protected IRoomManager RoomManager { get; private set; } + protected IRoomManager RoomManager { get; private set; } = null!; } } diff --git a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs index 98f3df525d..920aff13a8 100644 --- a/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs +++ b/osu.Game/Screens/OnlinePlay/FooterButtonFreeMods.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs b/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs index f32ead5a11..c528e3952e 100644 --- a/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/IOnlinePlaySubScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Screens.OnlinePlay { public interface IOnlinePlaySubScreen : IOsuScreen diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs index c25dd6f158..844991095e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/EndDateInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs index 35e0482f2b..e30d673b26 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/MatchTypePill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Game.Online.Rooms; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs index 263261143d..b473ea82c6 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PillContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index d1365c02f3..fe5ccb4f09 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using Humanizer; using osu.Framework.Extensions.LocalisationExtensions; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs index 208c11c155..23f4ecf8db 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/QueueModePill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs index 10f6e59260..9b8954bb33 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomSpecialCategoryPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics.Sprites; @@ -14,7 +12,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public partial class RoomSpecialCategoryPill : OnlinePlayPill { [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; protected override FontUsage Font => base.Font.With(weight: FontWeight.SemiBold); diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs index 463b883f11..53fbf670e1 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusFilter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Screens.OnlinePlay.Lounge.Components diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index ca9917ad00..aae82b6721 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -19,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components public partial class RoomStatusPill : OnlinePlayPill { [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; protected override FontUsage Font => base.Font.With(weight: FontWeight.SemiBold); diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs index 0251dba6ce..3788f4c0b2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/CreateRoomButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Input; using osu.Framework.Input.Bindings; diff --git a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs index 55d39407b0..8dc1704fcd 100644 --- a/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Match/Components/MatchChatDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.Chat; @@ -14,8 +12,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components { private readonly IBindable channelId = new Bindable(); - [Resolved(CanBeNull = true)] - private ChannelManager channelManager { get; set; } + [Resolved] + private ChannelManager? channelManager { get; set; } private readonly Room room; private readonly bool leaveChannelOnDispose; diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs index c9e51d376c..982275f96a 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Online.Rooms; using osu.Game.Screens.OnlinePlay.Components; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs index 8c08390c73..b4373d728f 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/GameplayMatchScoreDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Play.HUD; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs index a19f61787b..d18bb011f0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs index a5589c48b9..e5d94c5358 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylistTabControl.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 164d1c9a4b..66ae814444 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Logging; @@ -16,7 +14,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer public partial class Multiplayer : OnlinePlayScreen { [Resolved] - private MultiplayerClient client { get; set; } + private MultiplayerClient client { get; set; } = null!; protected override void LoadComplete() { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs index de19d3a0e9..9708a94cd7 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerResultsScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.Rooms; using osu.Game.Scoring; using osu.Game.Screens.OnlinePlay.Playlists; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs index 7f4e3360e4..79c6fb33cd 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsListHeader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Online.Multiplayer; using osu.Game.Resources.Localisation.Web; @@ -13,7 +11,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants public partial class ParticipantsListHeader : OverlinedHeader { [Resolved] - private MultiplayerClient client { get; set; } + private MultiplayerClient client { get; set; } = null!; public ParticipantsListHeader() : base(RankingsStrings.SpotlightParticipants) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index eb55b0d18a..9a43e96a50 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs index 82d4cf5caf..771a8c0de4 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs index 2f4ed35392..934c22c918 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerGrid_Facade.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index 7ecb7d954e..2e3e2e1dc0 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Screens; namespace osu.Game.Screens.OnlinePlay diff --git a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs index 9507169e0f..d56ef9ef0c 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/CreatePlaylistsRoomButton.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Screens.OnlinePlay.Match.Components; diff --git a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs index f9324840dc..f1d2384c2f 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/Playlists.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Screens.OnlinePlay.Lounge; namespace osu.Game.Screens.OnlinePlay.Playlists diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs index 736f09584b..2ca1f4cd1f 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsPlaylist.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index dffbbdbc55..ef579fac85 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; diff --git a/osu.Game/Screens/Play/Break/BlurredIcon.cs b/osu.Game/Screens/Play/Break/BlurredIcon.cs index 6ce1c2e686..2bf59ea63b 100644 --- a/osu.Game/Screens/Play/Break/BlurredIcon.cs +++ b/osu.Game/Screens/Play/Break/BlurredIcon.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index f0f1e8cc3d..41277c7557 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index f99c1d1817..ef453405b5 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Play/Break/GlowIcon.cs b/osu.Game/Screens/Play/Break/GlowIcon.cs index 595c4dd494..8e2b9da0ad 100644 --- a/osu.Game/Screens/Play/Break/GlowIcon.cs +++ b/osu.Game/Screens/Play/Break/GlowIcon.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs index da83f8c29f..3ac0a493da 100644 --- a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/Break/RemainingTimeCounter.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. -#nullable disable - using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs index eb3c71afbb..4a0e8b4f39 100644 --- a/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultAccuracyCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Skinning; diff --git a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs index 2c43905a46..c4d04c5580 100644 --- a/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/DefaultHealthDisplay.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs index 7cc2dc1751..2a17559503 100644 --- a/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs +++ b/osu.Game/Screens/Play/HUD/DefaultScoreCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 7a73eb1657..19ede5533f 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -22,7 +20,7 @@ namespace osu.Game.Screens.Play.HUD private readonly Bindable showHealthBar = new Bindable(true); [Resolved] - protected HealthProcessor HealthProcessor { get; private set; } + protected HealthProcessor HealthProcessor { get; private set; } = null!; public Bindable Current { get; } = new BindableDouble(1) { @@ -34,8 +32,8 @@ namespace osu.Game.Screens.Play.HUD { } - [Resolved(canBeNull: true)] - private HUDOverlay hudOverlay { get; set; } + [Resolved] + private HUDOverlay? hudOverlay { get; set; } protected override void LoadComplete() { diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 8b2b8f9464..579a0d163a 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs index 38027c64ac..0b2ce10ac3 100644 --- a/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModFlowDisplay.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index 064d2071ce..b6b385e262 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs index 4ceca817e2..e3034b2442 100644 --- a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs +++ b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -30,7 +28,7 @@ namespace osu.Game.Screens.Play.HUD private readonly Bindable valid = new Bindable(); [Resolved] - private ScoreProcessor scoreProcessor { get; set; } + private ScoreProcessor scoreProcessor { get; set; } = null!; public UnstableRateCounter() { diff --git a/osu.Game/Screens/Play/HotkeyExitOverlay.cs b/osu.Game/Screens/Play/HotkeyExitOverlay.cs index 4c1265c699..bcd9bd7cd6 100644 --- a/osu.Game/Screens/Play/HotkeyExitOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyExitOverlay.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. -#nullable disable - using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 582b5a1691..11d0b4f84f 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.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. -#nullable disable - using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs index e4328b2c78..2d181a09d4 100644 --- a/osu.Game/Screens/Play/ILocalUserPlayInfo.cs +++ b/osu.Game/Screens/Play/ILocalUserPlayInfo.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Screens/Play/PlayerConfiguration.cs b/osu.Game/Screens/Play/PlayerConfiguration.cs index b82925ccb8..122e25f406 100644 --- a/osu.Game/Screens/Play/PlayerConfiguration.cs +++ b/osu.Game/Screens/Play/PlayerConfiguration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Screens.Play { public class PlayerConfiguration diff --git a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index 7c76936621..f64861cfa5 100644 --- a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index 13e5b66a70..cf261ba49b 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index cb6fcb2413..4753effdb0 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.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. -#nullable disable - using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index 45009684a6..88b778fafb 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/ReplayPlayerLoader.cs b/osu.Game/Screens/Play/ReplayPlayerLoader.cs index 1c9d694325..7da06fe506 100644 --- a/osu.Game/Screens/Play/ReplayPlayerLoader.cs +++ b/osu.Game/Screens/Play/ReplayPlayerLoader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Screens; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs index 3830443ce8..8f2bcfe046 100644 --- a/osu.Game/Screens/Play/SpectatorPlayerLoader.cs +++ b/osu.Game/Screens/Play/SpectatorPlayerLoader.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Screens; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index b54dbb387a..67ec1373df 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Game.Online.Spectator; @@ -19,7 +17,7 @@ namespace osu.Game.Screens.Play } [Resolved] - private SpectatorClient spectatorClient { get; set; } + private SpectatorClient spectatorClient { get; set; } = null!; [BackgroundDependencyLoader] private void load() diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs index 9ec2a15044..a26bb8fe43 100644 --- a/osu.Game/Screens/Ranking/AspectContainer.cs +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs index 402322c611..195cd03e9b 100644 --- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs +++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelMiddleContent.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -36,7 +34,7 @@ namespace osu.Game.Screens.Ranking.Contracted private readonly ScoreInfo score; [Resolved] - private ScoreManager scoreManager { get; set; } + private ScoreManager scoreManager { get; set; } = null!; /// /// Creates a new . diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs index 32f2eb2fa5..244acbe8b1 100644 --- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs +++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs index 863c450617..384e5661b4 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/HitResultStatistic.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs index ecadc9eed6..b279c8107c 100644 --- a/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.cs +++ b/osu.Game/Screens/Ranking/Expanded/Statistics/StatisticCounter.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Ranking/RetryButton.cs b/osu.Game/Screens/Ranking/RetryButton.cs index c7d2416e29..d977f25323 100644 --- a/osu.Game/Screens/Ranking/RetryButton.cs +++ b/osu.Game/Screens/Ranking/RetryButton.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -18,8 +16,8 @@ namespace osu.Game.Screens.Ranking { private readonly Box background; - [Resolved(canBeNull: true)] - private Player player { get; set; } + [Resolved] + private Player? player { get; set; } public RetryButton() { diff --git a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs index ec153cbd63..f5a26ef754 100644 --- a/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs +++ b/osu.Game/Screens/Ranking/ScorePanelTrackingContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs index bb9905d29c..fb7107cc88 100644 --- a/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs +++ b/osu.Game/Screens/Ranking/Statistics/AverageHitError.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs index d3327224dc..4202b2158e 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Diagnostics.CodeAnalysis; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs index c5bdc6f6f5..6a595bf05c 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using JetBrains.Annotations; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs index de01668029..cc3535a426 100644 --- a/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs +++ b/osu.Game/Screens/Ranking/Statistics/UnstableRate.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs index d6b076f30b..4ff2600a72 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaDetailTabItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Screens.Select { public class BeatmapDetailAreaDetailTabItem : BeatmapDetailAreaTabItem diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs index 6efadc77b3..8dbe5b8bea 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaLeaderboardTabItem.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs index d5d258704b..50ec446c4f 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedgeBackground.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. -#nullable disable - using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Select/Filter/GroupMode.cs b/osu.Game/Screens/Select/Filter/GroupMode.cs index 8e2b9271b0..d794c215a3 100644 --- a/osu.Game/Screens/Select/Filter/GroupMode.cs +++ b/osu.Game/Screens/Select/Filter/GroupMode.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. -#nullable disable - using System.ComponentModel; namespace osu.Game.Screens.Select.Filter diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index c77bdbfbc6..7f2b33adbe 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Screens/Select/FooterButtonOptions.cs b/osu.Game/Screens/Select/FooterButtonOptions.cs index e56efcb458..532051369b 100644 --- a/osu.Game/Screens/Select/FooterButtonOptions.cs +++ b/osu.Game/Screens/Select/FooterButtonOptions.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index b8840b124a..5bcb4c27a7 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.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. -#nullable disable - using System.ComponentModel; using osu.Framework.Localisation; using osu.Game.Resources.Localisation.Web; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 0d3e1238f3..045a518525 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.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. -#nullable disable - using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Spectate/SpectatorGameplayState.cs b/osu.Game/Screens/Spectate/SpectatorGameplayState.cs index 498363adef..1ee328a307 100644 --- a/osu.Game/Screens/Spectate/SpectatorGameplayState.cs +++ b/osu.Game/Screens/Spectate/SpectatorGameplayState.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Scoring; diff --git a/osu.Game/Screens/StartupScreen.cs b/osu.Game/Screens/StartupScreen.cs index 84ef3eac78..9e04a238eb 100644 --- a/osu.Game/Screens/StartupScreen.cs +++ b/osu.Game/Screens/StartupScreen.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Overlays; namespace osu.Game.Screens diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index f460a3d31a..f1c99a315d 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 29e034d86c..480d69c12f 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.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. -#nullable disable - using System; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index d198ed68bd..0b96db6861 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.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. -#nullable disable - using System; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs index 50f3f0ef49..011f345df2 100644 --- a/osu.Game/Storyboards/CommandTrigger.cs +++ b/osu.Game/Storyboards/CommandTrigger.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. -#nullable disable - namespace osu.Game.Storyboards { public class CommandTrigger : CommandTimelineGroup diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 6fc8d124c7..38e7ff1c70 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.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. -#nullable disable - using System.Threading; using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index c281d23804..830b6a5caa 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -30,8 +28,8 @@ namespace osu.Game.Storyboards.Drawables LifetimeStart = sampleInfo.StartTime; } - [Resolved(CanBeNull = true)] - private IReadOnlyList mods { get; set; } + [Resolved] + private IReadOnlyList? mods { get; set; } protected override void SkinChanged(ISkinSource skin) { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 400d33481c..63f644886a 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -86,7 +84,7 @@ namespace osu.Game.Storyboards.Drawables } [Resolved] - private ISkinSource skin { get; set; } + private ISkinSource skin { get; set; } = null!; [BackgroundDependencyLoader] private void load(TextureStore textureStore, Storyboard storyboard) diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index 779c8384c5..bbc55a336d 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index aceb5c041c..165b3d97cc 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Storyboards/Drawables/IVectorScalable.cs b/osu.Game/Storyboards/Drawables/IVectorScalable.cs index 3b43a35a90..60a297e126 100644 --- a/osu.Game/Storyboards/Drawables/IVectorScalable.cs +++ b/osu.Game/Storyboards/Drawables/IVectorScalable.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osuTK; diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 7e83f8b692..9a059991e6 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.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. -#nullable disable - using osu.Framework.Graphics; namespace osu.Game.Storyboards diff --git a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs index 9eed139ad4..3e0f7fb576 100644 --- a/osu.Game/Storyboards/IStoryboardElementWithDuration.cs +++ b/osu.Game/Storyboards/IStoryboardElementWithDuration.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - namespace osu.Game.Storyboards { /// diff --git a/osu.Game/Storyboards/StoryboardExtensions.cs b/osu.Game/Storyboards/StoryboardExtensions.cs index e5cafc152b..04c7196315 100644 --- a/osu.Game/Storyboards/StoryboardExtensions.cs +++ b/osu.Game/Storyboards/StoryboardExtensions.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osuTK; diff --git a/osu.Game/Storyboards/StoryboardLayer.cs b/osu.Game/Storyboards/StoryboardLayer.cs index 2ab8d9fc2a..fa9d4ebfea 100644 --- a/osu.Game/Storyboards/StoryboardLayer.cs +++ b/osu.Game/Storyboards/StoryboardLayer.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. -#nullable disable - using osu.Game.Storyboards.Drawables; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index 752d086993..5d6ce215f5 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.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. -#nullable disable - using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Audio; diff --git a/osu.Game/Storyboards/StoryboardVideo.cs b/osu.Game/Storyboards/StoryboardVideo.cs index 04ff941397..4652e45852 100644 --- a/osu.Game/Storyboards/StoryboardVideo.cs +++ b/osu.Game/Storyboards/StoryboardVideo.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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardVideoLayer.cs b/osu.Game/Storyboards/StoryboardVideoLayer.cs index f08c02cfd2..f780604029 100644 --- a/osu.Game/Storyboards/StoryboardVideoLayer.cs +++ b/osu.Game/Storyboards/StoryboardVideoLayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; using osuTK; diff --git a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs index 921a039065..b7803f3420 100644 --- a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.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. -#nullable disable - using System; using System.Linq; using NUnit.Framework; diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 1aa99ceed9..ff670e1232 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.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. -#nullable disable - using System; using System.Diagnostics; using System.IO; diff --git a/osu.Game/Tests/CleanRunHeadlessGameHost.cs b/osu.Game/Tests/CleanRunHeadlessGameHost.cs index 02d67de5a5..f3c69201e2 100644 --- a/osu.Game/Tests/CleanRunHeadlessGameHost.cs +++ b/osu.Game/Tests/CleanRunHeadlessGameHost.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. -#nullable disable - using System; using System.Runtime.CompilerServices; using osu.Framework; diff --git a/osu.Game/Tests/OsuTestBrowser.cs b/osu.Game/Tests/OsuTestBrowser.cs index 689eae336e..0bc51a0c1e 100644 --- a/osu.Game/Tests/OsuTestBrowser.cs +++ b/osu.Game/Tests/OsuTestBrowser.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Framework.Screens; diff --git a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs index acfff4cefe..000509598d 100644 --- a/osu.Game/Tests/Visual/DependencyProvidingContainer.cs +++ b/osu.Game/Tests/Visual/DependencyProvidingContainer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/ModPerfectTestScene.cs b/osu.Game/Tests/Visual/ModPerfectTestScene.cs index 167d5450e9..164faa16aa 100644 --- a/osu.Game/Tests/Visual/ModPerfectTestScene.cs +++ b/osu.Game/Tests/Visual/ModPerfectTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs index 0570c4e2f2..efd0b80ebf 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index 0f286475bd..88202d4327 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Game.Online.Multiplayer; using osu.Game.Online.Spectator; using osu.Game.Screens.OnlinePlay; diff --git a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs index 12d1846ece..3509519113 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/IOnlinePlayTestSceneDependencies.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Bindables; using osu.Game.Database; using osu.Game.Online.Rooms; diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs index a9acbdcd7e..975423d19b 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestSceneDependencies.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Tests/Visual/OsuGridTestScene.cs b/osu.Game/Tests/Visual/OsuGridTestScene.cs index 9ef3b2a59d..6ee5593a69 100644 --- a/osu.Game/Tests/Visual/OsuGridTestScene.cs +++ b/osu.Game/Tests/Visual/OsuGridTestScene.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs index a5e0bddc6b..16496ff320 100644 --- a/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.cs +++ b/osu.Game/Tests/Visual/OsuManualInputManagerTestScene.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. -#nullable disable - using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs index 7d382ca1bc..3cca1e59cc 100644 --- a/osu.Game/Tests/Visual/ScreenTestScene.cs +++ b/osu.Game/Tests/Visual/ScreenTestScene.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; diff --git a/osu.Game/Tests/Visual/TestReplayPlayer.cs b/osu.Game/Tests/Visual/TestReplayPlayer.cs index bc6dc9bb27..0c9b466152 100644 --- a/osu.Game/Tests/Visual/TestReplayPlayer.cs +++ b/osu.Game/Tests/Visual/TestReplayPlayer.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; diff --git a/osu.Game/Tests/VisualTestRunner.cs b/osu.Game/Tests/VisualTestRunner.cs index c8279b9e3c..e04c71d193 100644 --- a/osu.Game/Tests/VisualTestRunner.cs +++ b/osu.Game/Tests/VisualTestRunner.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. -#nullable disable - using System; using osu.Framework; using osu.Framework.Platform; diff --git a/osu.Game/Users/CountryStatistics.cs b/osu.Game/Users/CountryStatistics.cs index 03d455bc04..921d60bb44 100644 --- a/osu.Game/Users/CountryStatistics.cs +++ b/osu.Game/Users/CountryStatistics.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. -#nullable disable - using Newtonsoft.Json; namespace osu.Game.Users diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 929a29251d..289f68ee7f 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Extensions; diff --git a/osu.Game/Users/UserActivity.cs b/osu.Game/Users/UserActivity.cs index 0b11d12c46..1761282e2e 100644 --- a/osu.Game/Users/UserActivity.cs +++ b/osu.Game/Users/UserActivity.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. -#nullable disable - using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Online.Rooms; diff --git a/osu.Game/Users/UserBrickPanel.cs b/osu.Game/Users/UserBrickPanel.cs index 69b390b36e..b92c9a9afd 100644 --- a/osu.Game/Users/UserBrickPanel.cs +++ b/osu.Game/Users/UserBrickPanel.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index 90b6c11f0e..f4ec1475b1 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index 3047e70a1a..4942cc7512 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.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. -#nullable disable - using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 075463c1e0..ffd86b78c7 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using osu.Framework.Localisation; using osuTK.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Utils/LimitedCapacityQueue.cs b/osu.Game/Utils/LimitedCapacityQueue.cs index 86a106a678..d36aa8af2c 100644 --- a/osu.Game/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Utils/LimitedCapacityQueue.cs @@ -1,8 +1,6 @@ -// 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. -#nullable disable - using System; using System.Collections; using System.Collections.Generic; diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs index c49e6907ff..502f302157 100644 --- a/osu.iOS/OsuGameIOS.cs +++ b/osu.iOS/OsuGameIOS.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. -#nullable disable - using System; using Foundation; using Microsoft.Maui.Devices; From df5b389629e7992ae4f799ed6dbd79a666473ec0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 24 Jun 2023 00:59:36 +0900 Subject: [PATCH 1352/1400] Manual fixes to reduce warnings to zero --- .../ManiaSelectionBlueprintTestScene.cs | 2 +- .../ManiaInputTestScene.cs | 3 ++- .../Edit/ManiaBlueprintContainer.cs | 2 +- .../Preprocessing/OsuDifficultyHitObject.cs | 6 +++--- .../Edit/OsuBlueprintContainer.cs | 2 +- .../Drawables/DrawableStrongNestedHit.cs | 5 ++--- .../TestSceneHitObjectSampleAdjustments.cs | 2 +- .../Screens/TestSceneTeamWinScreen.cs | 2 +- .../Components/DrawableTeamTitleWithHeader.cs | 2 +- .../Components/DrawableTeamWithPlayers.cs | 2 +- osu.Game.Tournament/Models/LadderInfo.cs | 2 +- .../Gameplay/Components/MatchRoundDisplay.cs | 4 ++-- osu.Game/Beatmaps/APIFailTimes.cs | 4 ++-- .../UpdateableBeatmapBackgroundSprite.cs | 2 +- .../Beatmaps/Legacy/LegacyControlPointInfo.cs | 3 --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- osu.Game/Database/IHasFiles.cs | 2 -- .../Graphics/Backgrounds/BeatmapBackground.cs | 2 +- osu.Game/Graphics/ErrorTextFlowContainer.cs | 2 +- .../Graphics/UserInterface/DialogButton.cs | 2 +- .../UserInterfaceV2/OsuHSVColourPicker.cs | 3 +-- .../UserInterfaceV2/OsuHexColourPicker.cs | 3 +-- .../Graphics/UserInterfaceV2/OsuPopover.cs | 3 +-- osu.Game/IO/OsuStorage.cs | 5 +---- .../BeatmapListing/BeatmapSearchFilterRow.cs | 2 -- .../Overlays/BeatmapSet/Buttons/PlayButton.cs | 2 ++ .../BeatmapSet/Buttons/PreviewButton.cs | 2 +- .../Overlays/Changelog/ChangelogListing.cs | 2 +- osu.Game/Overlays/FullscreenOverlay.cs | 2 -- osu.Game/Overlays/OverlayHeader.cs | 3 --- osu.Game/Overlays/OverlaySidebar.cs | 2 -- .../Sections/DebugSettings/GeneralSettings.cs | 2 +- .../Sections/DebugSettings/MemorySettings.cs | 7 ++++--- .../Sections/Input/RulesetBindingsSection.cs | 7 +------ .../StableDirectorySelectScreen.cs | 2 +- osu.Game/Overlays/Settings/SettingsFooter.cs | 4 ++-- osu.Game/Overlays/TabControlOverlayHeader.cs | 3 --- .../Toolbar/ToolbarNotificationButton.cs | 3 +-- .../Edit/Checks/CheckAudioPresence.cs | 2 +- .../Rulesets/Edit/Checks/CheckAudioQuality.cs | 2 +- .../Edit/Checks/CheckBackgroundPresence.cs | 2 +- .../Edit/Checks/CheckBackgroundQuality.cs | 4 ++-- .../Edit/DrawableEditorRulesetWrapper.cs | 3 ++- .../Rulesets/Judgements/JudgementResult.cs | 5 +---- osu.Game/Rulesets/Objects/HitObjectParser.cs | 2 +- .../Objects/Legacy/ConvertHitObjectParser.cs | 1 - .../Rulesets/UI/IPooledHitObjectProvider.cs | 4 +--- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 19 ++++++++----------- osu.Game/Screens/BackgroundScreenStack.cs | 2 +- .../HitObjectOrderedSelectionContainer.cs | 3 ++- .../OnlinePlay/Multiplayer/Multiplayer.cs | 3 ++- .../Spectate/MultiSpectatorPlayerLoader.cs | 3 +-- .../OnlinePlay/OnlinePlaySubScreenStack.cs | 7 +++++-- osu.Game/Screens/OsuScreenStack.cs | 6 +++--- osu.Game/Screens/Play/HUD/HealthDisplay.cs | 3 ++- osu.Game/Screens/Play/HUD/ModDisplay.cs | 4 +--- .../Screens/Play/HUD/UnstableRateCounter.cs | 10 ++++++---- .../Screens/Play/SpectatorResultsScreen.cs | 3 ++- .../Ranking/Statistics/StatisticContainer.cs | 3 +-- .../Ranking/Statistics/StatisticItem.cs | 3 +-- .../Drawables/DrawableStoryboardSprite.cs | 3 ++- 61 files changed, 89 insertions(+), 118 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs index 281dec3c79..80e1b753ea 100644 --- a/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/Editor/ManiaSelectionBlueprintTestScene.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor { protected override Container Content => blueprints ?? base.Content; - private readonly Container blueprints; + private readonly Container? blueprints; [Cached(typeof(Playfield))] public Playfield Playfield { get; } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs index ec249f6ae9..62591ce4ca 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestScene.cs @@ -12,7 +12,8 @@ namespace osu.Game.Rulesets.Mania.Tests { public abstract partial class ManiaInputTestScene : OsuTestScene { - private readonly Container content; + private readonly Container? content; + protected override Container Content => content ?? base.Content; protected ManiaInputTestScene(int keys) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs index fb3e2d494e..d0eb8c1e6e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBlueprintContainer.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit { } - public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) + public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject) { switch (hitObject) { diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 5215920ea0..e627c9ad67 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -82,13 +82,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing /// public double HitWindowGreat { get; private set; } - private readonly OsuHitObject lastLastObject; + private readonly OsuHitObject? lastLastObject; private readonly OsuHitObject lastObject; - public OsuDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject lastLastObject, double clockRate, List objects, int index) + public OsuDifficultyHitObject(HitObject hitObject, HitObject lastObject, HitObject? lastLastObject, double clockRate, List objects, int index) : base(hitObject, lastObject, clockRate, objects, index) { - this.lastLastObject = (OsuHitObject)lastLastObject; + this.lastLastObject = lastLastObject as OsuHitObject; this.lastObject = (OsuHitObject)lastObject; // Capped to 25ms to prevent difficulty calculation breaking from simultaneous objects. diff --git a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs index ed149d004c..54c54fca17 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuBlueprintContainer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit protected override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); - public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) + public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject) { switch (hitObject) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index 6ee29fa014..9b410d1871 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -11,9 +10,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public abstract partial class DrawableStrongNestedHit : DrawableTaikoHitObject { - public new DrawableTaikoHitObject ParentHitObject => (DrawableTaikoHitObject)base.ParentHitObject; + public new DrawableTaikoHitObject? ParentHitObject => base.ParentHitObject as DrawableTaikoHitObject; - protected DrawableStrongNestedHit([CanBeNull] StrongNestedHitObject nestedHit) + protected DrawableStrongNestedHit(StrongNestedHitObject? nestedHit) : base(nestedHit) { } diff --git a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs index 29de0bff79..1415ff4b0f 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneHitObjectSampleAdjustments.cs @@ -358,7 +358,7 @@ namespace osu.Game.Tests.Visual.Editing var popover = this.ChildrenOfType().SingleOrDefault(); var textBox = popover?.ChildrenOfType().First(); - return textBox?.Current.Value == bank && string.IsNullOrEmpty(textBox?.PlaceholderText.ToString()); + return textBox?.Current.Value == bank && string.IsNullOrEmpty(textBox.PlaceholderText.ToString()); }); private void samplePopoverHasIndeterminateBank() => AddUntilStep("sample popover has indeterminate bank", () => diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs index 8096988864..2ed87cdcd5 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tournament.Tests.Screens { AddStep("set up match", () => { - var match = Ladder.CurrentMatch.Value; + var match = Ladder.CurrentMatch.Value!; match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals"); match.Completed.Value = true; diff --git a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs index 59e261a7dd..89f45fc1d3 100644 --- a/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs +++ b/osu.Game.Tournament/Components/DrawableTeamTitleWithHeader.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Components { public partial class DrawableTeamTitleWithHeader : CompositeDrawable { - public DrawableTeamTitleWithHeader(TournamentTeam team, TeamColour colour) + public DrawableTeamTitleWithHeader(TournamentTeam? team, TeamColour colour) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs index 5ebed34e6a..4f0c7d6b72 100644 --- a/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs +++ b/osu.Game.Tournament/Components/DrawableTeamWithPlayers.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tournament.Components { public partial class DrawableTeamWithPlayers : CompositeDrawable { - public DrawableTeamWithPlayers(TournamentTeam team, TeamColour colour) + public DrawableTeamWithPlayers(TournamentTeam? team, TeamColour colour) { AutoSizeAxes = Axes.Both; diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index b5bc5fd307..3defd517cd 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] // updated manually in TournamentGameBase - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); public Bindable ChromaKeyWidth = new BindableInt(1024) { diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs index 79de4e465e..bd23317e1f 100644 --- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs +++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchRoundDisplay.cs @@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components { public partial class MatchRoundDisplay : TournamentSpriteTextWithBackground { - private readonly Bindable currentMatch = new Bindable(); + private readonly Bindable currentMatch = new Bindable(); [BackgroundDependencyLoader] private void load(LadderInfo ladder) @@ -19,7 +19,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components currentMatch.BindTo(ladder.CurrentMatch); } - private void matchChanged(ValueChangedEvent match) => + private void matchChanged(ValueChangedEvent match) => Text.Text = match.NewValue?.Round.Value?.Name.Value ?? "Unknown Round"; } } diff --git a/osu.Game/Beatmaps/APIFailTimes.cs b/osu.Game/Beatmaps/APIFailTimes.cs index 7218906b38..09ab16598d 100644 --- a/osu.Game/Beatmaps/APIFailTimes.cs +++ b/osu.Game/Beatmaps/APIFailTimes.cs @@ -15,12 +15,12 @@ namespace osu.Game.Beatmaps /// Points of failure on a relative time scale (usually 0..100). /// [JsonProperty(@"fail")] - public int[] Fails { get; set; } = Array.Empty(); + public int[]? Fails { get; set; } = Array.Empty(); /// /// Points of retry on a relative time scale (usually 0..100). /// [JsonProperty(@"exit")] - public int[] Retries { get; set; } = Array.Empty(); + public int[]? Retries { get; set; } = Array.Empty(); } } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 72f37143d0..67eedf655e 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -50,7 +50,7 @@ namespace osu.Game.Beatmaps.Drawables return drawable; } - private Drawable getDrawableForModel(IBeatmapInfo model) + private Drawable getDrawableForModel(IBeatmapInfo? model) { // prefer online cover where available. if (model?.BeatmapSet is IBeatmapSetOnlineInfo online) diff --git a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs index fc80f0db6f..6dda18bc4d 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyControlPointInfo.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Lists; using osu.Game.Beatmaps.ControlPoints; @@ -24,7 +23,6 @@ namespace osu.Game.Beatmaps.Legacy /// /// The time to find the sound control point at. /// The sound control point. - [NotNull] public SampleControlPoint SamplePointAt(double time) => BinarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : SampleControlPoint.DEFAULT); /// @@ -40,7 +38,6 @@ namespace osu.Game.Beatmaps.Legacy /// /// The time to find the difficulty control point at. /// The difficulty control point. - [NotNull] public DifficultyControlPoint DifficultyPointAt(double time) => BinarySearchWithFallback(DifficultyPoints, time, DifficultyControlPoint.DEFAULT); public override void Clear() diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 309a5818ae..ba555a7926 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -257,7 +257,7 @@ namespace osu.Game.Configuration string skinName = string.Empty; if (Guid.TryParse(skin, out var id)) - skinName = LookupSkinName(id) ?? string.Empty; + skinName = LookupSkinName(id); return new SettingDescription( rawValue: skinName, diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index 3f6531832f..d64ac9b662 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using JetBrains.Annotations; namespace osu.Game.Database { @@ -13,7 +12,6 @@ namespace osu.Game.Database public interface IHasFiles where TFile : INamedFileInfo { - [NotNull] List Files { get; } string Hash { get; set; } diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index beb7c5a4df..b8de0f7f1e 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Backgrounds [BackgroundDependencyLoader] private void load(LargeTextureStore textures) { - Sprite.Texture = Beatmap?.GetBackground() ?? textures.Get(fallbackTextureName); + Sprite.Texture = Beatmap.GetBackground() ?? textures.Get(fallbackTextureName); } public override bool Equals(Background other) diff --git a/osu.Game/Graphics/ErrorTextFlowContainer.cs b/osu.Game/Graphics/ErrorTextFlowContainer.cs index 7386baf83f..40c7580647 100644 --- a/osu.Game/Graphics/ErrorTextFlowContainer.cs +++ b/osu.Game/Graphics/ErrorTextFlowContainer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Graphics RemovePart(textPart); } - public void AddErrors(string[] errors) + public void AddErrors(string[]? errors) { ClearErrors(); diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 06ebe48850..db81bc991d 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface private const float hover_duration = 500; private const float click_duration = 200; - public event Action StateChanged; + public event Action? StateChanged; private SelectionState state; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs index 75ff1e5665..63bad283a8 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHSVColourPicker.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -24,7 +23,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 protected override SaturationValueSelector CreateSaturationValueSelector() => new OsuSaturationValueSelector(); [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour osuColour) + private void load(OverlayColourProvider? colourProvider, OsuColour osuColour) { Background.Colour = colourProvider?.Dark5 ?? osuColour.GreySeaFoamDark; diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs index 6633ba0eb2..3621ca165f 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuHexColourPicker.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,7 +20,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider overlayColourProvider, OsuColour osuColour) + private void load(OverlayColourProvider? overlayColourProvider, OsuColour osuColour) { Background.Colour = overlayColourProvider?.Dark6 ?? osuColour.GreySeaFoamDarker; } diff --git a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs index 9153d5253d..00e5b8838c 100644 --- a/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs +++ b/osu.Game/Graphics/UserInterfaceV2/OsuPopover.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Graphics; @@ -39,7 +38,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 } [BackgroundDependencyLoader(true)] - private void load([CanBeNull] OverlayColourProvider colourProvider, OsuColour colours) + private void load(OverlayColourProvider? colourProvider, OsuColour colours) { Background.Colour = Arrow.Colour = colourProvider?.Background4 ?? colours.GreySeaFoamDarker; } diff --git a/osu.Game/IO/OsuStorage.cs b/osu.Game/IO/OsuStorage.cs index a2b89b6d97..a936fa74da 100644 --- a/osu.Game/IO/OsuStorage.cs +++ b/osu.Game/IO/OsuStorage.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Linq; -using JetBrains.Annotations; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Configuration; @@ -20,13 +19,11 @@ namespace osu.Game.IO /// /// The custom storage path as selected by the user. /// - [CanBeNull] - public string CustomStoragePath => storageConfig.Get(StorageConfig.FullPath); + public string? CustomStoragePath => storageConfig.Get(StorageConfig.FullPath); /// /// The default storage path to be used if a custom storage path hasn't been selected or is not accessible. /// - [NotNull] public string DefaultStoragePath => defaultStorage.GetFullPath("."); private readonly GameHost host; diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs index 608ecbb6f3..6d75521cb0 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapSearchFilterRow.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -64,7 +63,6 @@ namespace osu.Game.Overlays.BeatmapListing Current = filterWithValue.Current; } - [NotNull] protected virtual Drawable CreateFilter() => new BeatmapSearchFilter(); protected partial class BeatmapSearchFilter : TabControl diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs index c43be33290..5f9cdf5065 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PlayButton.cs @@ -3,6 +3,7 @@ #nullable disable +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -24,6 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly BindableBool playing = new BindableBool(); + [CanBeNull] public PreviewTrack Preview { get; private set; } private APIBeatmapSet beatmapSet; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 62a8bf80d3..2254514a44 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons private readonly Box background, progress; private readonly PlayButton playButton; - private PreviewTrack preview => playButton.Preview; + private PreviewTrack? preview => playButton.Preview; public IBindable Playing => playButton.Playing; diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index 3a648f66cf..c4320dcbd0 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Changelog { public partial class ChangelogListing : ChangelogContent { - private readonly List entries; + private readonly List? entries; public ChangelogListing(List entries) { diff --git a/osu.Game/Overlays/FullscreenOverlay.cs b/osu.Game/Overlays/FullscreenOverlay.cs index b58a3b929b..7ae5167081 100644 --- a/osu.Game/Overlays/FullscreenOverlay.cs +++ b/osu.Game/Overlays/FullscreenOverlay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -81,7 +80,6 @@ namespace osu.Game.Overlays Waves.FourthWaveColour = ColourProvider.Dark3; } - [NotNull] protected abstract T CreateHeader(); public override void Show() diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index 827a7749af..3d71b7d5ae 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -96,10 +95,8 @@ namespace osu.Game.Overlays titleBackground.Colour = colourProvider.Dark5; } - [NotNull] protected virtual Drawable CreateContent() => Empty(); - [NotNull] protected virtual Drawable CreateBackground() => Empty(); protected abstract OverlayTitle CreateTitle(); diff --git a/osu.Game/Overlays/OverlaySidebar.cs b/osu.Game/Overlays/OverlaySidebar.cs index b08a9d08a4..f1bdfbddac 100644 --- a/osu.Game/Overlays/OverlaySidebar.cs +++ b/osu.Game/Overlays/OverlaySidebar.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -71,7 +70,6 @@ namespace osu.Game.Overlays scrollbarBackground.Colour = colourProvider.Background3; } - [NotNull] protected virtual Drawable CreateContent() => Empty(); private partial class SidebarScrollContainer : OsuScrollContainer diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 1044810bdc..01408ca087 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader; [BackgroundDependencyLoader(true)] - private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, IPerformFromScreenRunner performer) + private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, IPerformFromScreenRunner? performer) { Children = new Drawable[] { diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs index 0d2d163859..d5de7ae2db 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/MemorySettings.cs @@ -5,6 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Framework.Logging; @@ -56,7 +57,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { try { - var token = realm.BlockAllOperations("maintenance"); + IDisposable? token = realm.BlockAllOperations("maintenance"); blockAction.Enabled.Value = false; @@ -73,10 +74,10 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings void unblock() { - if (token == null) + if (token.IsNull()) return; - token?.Dispose(); + token.Dispose(); token = null; Scheduler.Add(() => diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs index 0ed7de9d3f..3b5002b423 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs @@ -2,19 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Graphics; using osu.Game.Rulesets; namespace osu.Game.Overlays.Settings.Sections.Input { public partial class RulesetBindingsSection : SettingsSection { - public override Drawable CreateIcon() => ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon - { - Icon = OsuIcon.Hot - }; + public override Drawable CreateIcon() => ruleset.CreateInstance().CreateIcon(); public override LocalisableString Header => ruleset.Name; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs index 1f62077f20..1b935b0cec 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; - protected override bool IsValidDirectory(DirectoryInfo info) => info?.GetFiles("osu!.*.cfg").Any() ?? false; + protected override bool IsValidDirectory(DirectoryInfo? info) => info?.GetFiles("osu!.*.cfg").Any() ?? false; public override LocalisableString HeaderText => "Please select your osu!stable install location"; diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index ffb955f3bd..4e9d4c0d28 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -92,8 +92,8 @@ namespace osu.Game.Overlays.Settings Height = 20; } - [BackgroundDependencyLoader(true)] - private void load(ChangelogOverlay changelog) + [BackgroundDependencyLoader] + private void load(ChangelogOverlay? changelog) { Action = () => changelog?.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index edfe38b2da..3875f18152 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -83,13 +82,11 @@ namespace osu.Game.Overlays controlBackground.Colour = colourProvider.Dark4; } - [NotNull] protected virtual OsuTabControl CreateTabControl() => new OverlayHeaderTabControl(); /// /// Creates a on the opposite side of the . Used mostly to create . /// - [NotNull] protected virtual Drawable CreateTabControlContent() => Empty(); public partial class OverlayHeaderTabControl : OverlayTabControl diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 1871371750..9971871229 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -41,8 +41,7 @@ namespace osu.Game.Overlays.Toolbar { StateContainer = notificationOverlay as NotificationOverlay; - if (notificationOverlay != null) - NotificationCount.BindTo(notificationOverlay.UnreadCount); + NotificationCount.BindTo(notificationOverlay.UnreadCount); NotificationCount.ValueChanged += count => { diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs index e922ddf023..416a0d5897 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Audio; protected override string TypeOfFile => "audio"; - protected override string? GetFilename(IBeatmap beatmap) => beatmap.Metadata?.AudioFile; + protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata.AudioFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs index daa33fb0da..440d4e8e62 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckAudioQuality.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - string? audioFile = context.Beatmap.Metadata?.AudioFile; + string audioFile = context.Beatmap.Metadata.AudioFile; if (string.IsNullOrEmpty(audioFile)) yield break; diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs index 4ca93a9807..04cbba1e8c 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundPresence.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Edit.Checks { protected override CheckCategory Category => CheckCategory.Resources; protected override string TypeOfFile => "background"; - protected override string? GetFilename(IBeatmap beatmap) => beatmap.Metadata?.BackgroundFile; + protected override string GetFilename(IBeatmap beatmap) => beatmap.Metadata.BackgroundFile; } } diff --git a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs index 8c3a5c026d..5008c13d9a 100644 --- a/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs +++ b/osu.Game/Rulesets/Edit/Checks/CheckBackgroundQuality.cs @@ -33,8 +33,8 @@ namespace osu.Game.Rulesets.Edit.Checks public IEnumerable Run(BeatmapVerifierContext context) { - string? backgroundFile = context.Beatmap.Metadata?.BackgroundFile; - if (backgroundFile == null) + string backgroundFile = context.Beatmap.Metadata.BackgroundFile; + if (string.IsNullOrEmpty(backgroundFile)) yield break; var texture = context.WorkingBeatmap.GetBackground(); diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs index 324f2068e9..174b278d89 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mods; @@ -92,7 +93,7 @@ namespace osu.Game.Rulesets.Edit { base.Dispose(isDisposing); - if (beatmap != null) + if (beatmap.IsNotNull()) { beatmap.HitObjectAdded -= addHitObject; beatmap.HitObjectRemoved -= removeHitObject; diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index f001a4cd92..c67f8b9fd5 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -22,13 +21,11 @@ namespace osu.Game.Rulesets.Judgements /// /// The which was judged. /// - [NotNull] public readonly HitObject HitObject; /// /// The which this applies for. /// - [NotNull] public readonly Judgement Judgement; /// @@ -97,7 +94,7 @@ namespace osu.Game.Rulesets.Judgements /// /// The which was judged. /// The to refer to for scoring information. - public JudgementResult([NotNull] HitObject hitObject, [NotNull] Judgement judgement) + public JudgementResult(HitObject hitObject, Judgement judgement) { HitObject = hitObject; Judgement = judgement; diff --git a/osu.Game/Rulesets/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs index d3c29d90ce..c6e250bd74 100644 --- a/osu.Game/Rulesets/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.cs @@ -5,6 +5,6 @@ namespace osu.Game.Rulesets.Objects { public abstract class HitObjectParser { - public abstract HitObject Parse(string text); + public abstract HitObject? Parse(string text); } } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 8eda2a8f61..3dbe7b6519 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -44,7 +44,6 @@ namespace osu.Game.Rulesets.Objects.Legacy FormatVersion = formatVersion; } - [CanBeNull] public override HitObject Parse(string text) { string[] split = text.Split(','); diff --git a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs index f5739ee525..01c8e6d1da 100644 --- a/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs +++ b/osu.Game/Rulesets/UI/IPooledHitObjectProvider.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -15,7 +14,6 @@ namespace osu.Game.Rulesets.UI /// The to retrieve the representation of. /// The parenting , if any. /// The representing , or null if no poolable representation exists. - [CanBeNull] - DrawableHitObject GetPooledDrawableRepresentation([NotNull] HitObject hitObject, [CanBeNull] DrawableHitObject parent); + DrawableHitObject? GetPooledDrawableRepresentation(HitObject hitObject, DrawableHitObject? parent); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 87e1e79f87..2a54ef16c6 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -126,19 +126,16 @@ namespace osu.Game.Scoring.Legacy // As this is baked into hitobject timing (see `LegacyBeatmapDecoder`) we also need to apply this to replay frame timing. double offset = beatmap?.BeatmapInfo.BeatmapVersion < 5 ? -LegacyBeatmapDecoder.EARLY_VERSION_TIMING_OFFSET : 0; - if (score.Replay != null) + int lastTime = 0; + + foreach (var f in score.Replay.Frames) { - int lastTime = 0; + var legacyFrame = getLegacyFrame(f); - foreach (var f in score.Replay.Frames) - { - var legacyFrame = getLegacyFrame(f); - - // Rounding because stable could only parse integral values - int time = (int)Math.Round(legacyFrame.Time + offset); - replayData.Append(FormattableString.Invariant($"{time - lastTime}|{legacyFrame.MouseX ?? 0}|{legacyFrame.MouseY ?? 0}|{(int)legacyFrame.ButtonState},")); - lastTime = time; - } + // Rounding because stable could only parse integral values + int time = (int)Math.Round(legacyFrame.Time + offset); + replayData.Append(FormattableString.Invariant($"{time - lastTime}|{legacyFrame.MouseX ?? 0}|{legacyFrame.MouseY ?? 0}|{(int)legacyFrame.ButtonState},")); + lastTime = time; } // Warning: this is purposefully hardcoded as a string rather than interpolating, as in some cultures the minus sign is not encoded as the standard ASCII U+00C2 codepoint, diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs index 6ebc97ebbb..99ca383b9f 100644 --- a/osu.Game/Screens/BackgroundScreenStack.cs +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens /// /// The screen to attempt to push. /// Whether the push succeeded. For example, if the existing screen was already of the correct type this will return false. - public bool Push(BackgroundScreen screen) + public bool Push(BackgroundScreen? screen) { if (screen == null) return false; diff --git a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs index 0edaaf9825..8f54d55d5d 100644 --- a/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/HitObjectOrderedSelectionContainer.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Edit; @@ -67,7 +68,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { base.Dispose(isDisposing); - if (editorBeatmap != null) + if (editorBeatmap.IsNotNull()) editorBeatmap.BeatmapReprocessed -= SortInternal; } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs index 66ae814444..514b80b999 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Multiplayer.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.Multiplayer; @@ -93,7 +94,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.Dispose(isDisposing); - if (client != null) + if (client.IsNotNull()) client.RoomUpdated -= onRoomUpdated; } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs index 9a43e96a50..737f301f4d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorPlayerLoader.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Game.Scoring; using osu.Game.Screens.Menu; @@ -15,7 +14,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate /// public partial class MultiSpectatorPlayerLoader : SpectatorPlayerLoader { - public MultiSpectatorPlayerLoader([NotNull] Score score, [NotNull] Func createPlayer) + public MultiSpectatorPlayerLoader(Score score, Func createPlayer) : base(score, createPlayer) { } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs index 2e3e2e1dc0..6695c97508 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySubScreenStack.cs @@ -1,18 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Diagnostics; using osu.Framework.Screens; namespace osu.Game.Screens.OnlinePlay { public partial class OnlinePlaySubScreenStack : OsuScreenStack { - protected override void ScreenChanged(IScreen prev, IScreen next) + protected override void ScreenChanged(IScreen prev, IScreen? next) { base.ScreenChanged(prev, next); // because this is a screen stack within a screen stack, let's manually handle disabled changes to simplify things. - var osuScreen = ((OsuScreen)next); + var osuScreen = next as OsuScreen; + + Debug.Assert(osuScreen != null); bool disallowChanges = osuScreen.DisallowExternalBeatmapRulesetChanges; diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs index ef579fac85..7d1f6419ad 100644 --- a/osu.Game/Screens/OsuScreenStack.cs +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -52,12 +52,12 @@ namespace osu.Game.Screens ScreenChanged(prev, next); } - protected virtual void ScreenChanged(IScreen prev, IScreen next) + protected virtual void ScreenChanged(IScreen prev, IScreen? next) { setParallax(next); } - private void setParallax(IScreen next) => - parallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * (((IOsuScreen)next)?.BackgroundParallaxAmount ?? 1.0f); + private void setParallax(IScreen? next) => + parallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * ((next as IOsuScreen)?.BackgroundParallaxAmount ?? 1.0f); } } diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index 19ede5533f..9fdd735804 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; @@ -59,7 +60,7 @@ namespace osu.Game.Screens.Play.HUD { base.Dispose(isDisposing); - if (HealthProcessor != null) + if (HealthProcessor.IsNotNull()) HealthProcessor.NewJudgement -= onNewJudgement; } } diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 579a0d163a..c064cdb040 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Play.HUD public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover; - private readonly BindableWithCurrent> current = new BindableWithCurrent>(); + private readonly BindableWithCurrent> current = new BindableWithCurrent>(Array.Empty()); public Bindable> Current { @@ -63,8 +63,6 @@ namespace osu.Game.Screens.Play.HUD { iconsContainer.Clear(); - if (mods.NewValue == null) return; - foreach (Mod mod in mods.NewValue) iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) }); diff --git a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs index e3034b2442..701b8a8732 100644 --- a/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs +++ b/osu.Game/Screens/Play/HUD/UnstableRateCounter.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -75,10 +76,11 @@ namespace osu.Game.Screens.Play.HUD { base.Dispose(isDisposing); - if (scoreProcessor == null) return; - - scoreProcessor.NewJudgement -= updateDisplay; - scoreProcessor.JudgementReverted -= updateDisplay; + if (scoreProcessor.IsNotNull()) + { + scoreProcessor.NewJudgement -= updateDisplay; + scoreProcessor.JudgementReverted -= updateDisplay; + } } private partial class TextComponent : CompositeDrawable, IHasText diff --git a/osu.Game/Screens/Play/SpectatorResultsScreen.cs b/osu.Game/Screens/Play/SpectatorResultsScreen.cs index 67ec1373df..001d3b4bbc 100644 --- a/osu.Game/Screens/Play/SpectatorResultsScreen.cs +++ b/osu.Game/Screens/Play/SpectatorResultsScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Screens; using osu.Game.Online.Spectator; using osu.Game.Scoring; @@ -40,7 +41,7 @@ namespace osu.Game.Screens.Play { base.Dispose(isDisposing); - if (spectatorClient != null) + if (spectatorClient.IsNotNull()) spectatorClient.OnUserBeganPlaying -= userBeganPlaying; } } diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs index 4202b2158e..9191ee6f52 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics.CodeAnalysis; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,7 +21,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// Creates a new . /// /// The to display. - public StatisticContainer([NotNull] StatisticItem item) + public StatisticContainer(StatisticItem item) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs index 6a595bf05c..fd7a0ddb4f 100644 --- a/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs +++ b/osu.Game/Screens/Ranking/Statistics/StatisticItem.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using JetBrains.Annotations; using osu.Framework.Graphics; using osu.Framework.Localisation; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Ranking.Statistics /// The name of the item. Can be to hide the item header. /// A function returning the content to be displayed. /// Whether this item requires hit events. If true, will not be called if no hit events are available. - public StatisticItem(LocalisableString name, [NotNull] Func createContent, bool requiresHitEvents = false) + public StatisticItem(LocalisableString name, Func createContent, bool requiresHitEvents = false) { Name = name; RequiresHitEvents = requiresHitEvents; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 63f644886a..ec0cb7ca19 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -106,7 +107,7 @@ namespace osu.Game.Storyboards.Drawables { base.Dispose(isDisposing); - if (skin != null) + if (skin.IsNotNull()) skin.SourceChanged -= skinSourceChanged; } } From ad6650cbfa229c61910ff59114a740f7cc9fb3d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 24 Jun 2023 01:56:16 +0900 Subject: [PATCH 1353/1400] Add automated commit to blame ignore revs --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index b85862270b..d35d4be412 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -6,3 +6,5 @@ 212d78865a6b5f091173a347bad5686834d1d5fe # Add partial specs in mobile projects too 00c11b2b4e389e48f3995d63484a6bc66a7afbdb +# Mass NRT enabling +0ab0c52ad577b3e7b406d09fa6056a56ff997c3e From 4a2f259f7e254c57d33f1829f9fcf358207f10e5 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Jun 2023 22:04:29 +0300 Subject: [PATCH 1354/1400] Add test coverage for tournament players with profile colours --- .../TestSceneTournamentMatchChatDisplay.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index b552d49d1d..8003011475 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -43,6 +43,12 @@ namespace osu.Game.Tournament.Tests.Components OnlineID = 4, }; + private readonly TournamentUser blueUserWithCustomColour = new TournamentUser + { + Username = "nekodex", + OnlineID = 5, + }; + [Cached] private LadderInfo ladderInfo = new LadderInfo(); @@ -67,7 +73,7 @@ namespace osu.Game.Tournament.Tests.Components }, Team2 = { - Value = new TournamentTeam { Players = new BindableList { blueUser } } + Value = new TournamentTeam { Players = new BindableList { blueUser, blueUserWithCustomColour } } } }; @@ -108,6 +114,21 @@ namespace osu.Game.Tournament.Tests.Components AddUntilStep("message from team blue is blue color", () => this.ChildrenOfType().Last().AccentColour, () => Is.EqualTo(TournamentGame.COLOUR_BLUE)); + var userWithCustomColour = blueUserWithCustomColour.ToAPIUser(); + userWithCustomColour.Colour = "#e45678"; + + AddStep("message from team blue with custom colour", () => testChannel.AddNewMessages(new Message(nextMessageId()) + { + Sender = userWithCustomColour, + Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand." + })); + + AddUntilStep("message from team blue is blue color", () => + this.ChildrenOfType().Last().AccentColour, () => Is.EqualTo(TournamentGame.COLOUR_BLUE)); + + AddUntilStep("message from user with custom colour is inverted", () => + this.ChildrenOfType().Last().Inverted, () => Is.EqualTo(true)); + AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = admin, From 7a771609f90b26d3bce25fe934ccef40d8d7330e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Jun 2023 22:20:25 +0300 Subject: [PATCH 1355/1400] Reword and fix typo --- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index fdf91dce23..bbc3ee5bf4 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -70,7 +70,7 @@ namespace osu.Game.Overlays.Chat private Container? highlight; /// - /// The colour to use to paint the chat mesasge author's username. + /// The colour used to paint the author's username. /// /// /// The colour can be set explicitly by consumers via the property initialiser. From ff17685bc3650928062fecb20fe9b31698c0d839 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Fri, 23 Jun 2023 22:37:44 +0300 Subject: [PATCH 1356/1400] Fix `OpenUserProfile` links having multiple argument types --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 8 +++++++- osu.Game/OsuGame.cs | 10 +++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 2d27ce906b..a2c9b0ac32 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -74,7 +74,13 @@ namespace osu.Game.Graphics.Containers } public void AddUserLink(IUser user, Action creationParameters = null) - => createLink(CreateChunkFor(user.Username, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user), "view profile"); + { + string argument = user.OnlineID > 1 + ? user.OnlineID.ToString() + : user.Username; + + createLink(CreateChunkFor(user.Username, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, argument), "view profile"); + } private void createLink(ITextPart textPart, LinkDetails link, LocalisableString tooltipText, Action action = null) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index a80639d4ff..2db8872524 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -446,15 +446,11 @@ namespace osu.Game break; case LinkAction.OpenUserProfile: - if (!(link.Argument is IUser user)) - { - user = int.TryParse(argString, out int userId) - ? new APIUser { Id = userId } - : new APIUser { Username = argString }; - } + var user = int.TryParse(argString, out int userId) + ? new APIUser { Id = userId } + : new APIUser { Username = argString }; ShowUser(user); - break; case LinkAction.OpenWiki: From 3585c3f1d5b96e66aec5aa9162fd75de2b6eb336 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Jun 2023 15:58:05 +0900 Subject: [PATCH 1357/1400] Apply required nullability changes --- .../Editor/TestSceneSliderSplitting.cs | 2 +- osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs | 2 +- osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs | 2 +- osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 4 ++++ .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 4 ++-- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs index 605771fb20..8ba97892fe 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestSceneSliderSplitting.cs @@ -244,7 +244,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor MenuItem? item = visualiser.ContextMenuItems.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); - item?.Action?.Value(); + item?.Action.Value?.Invoke(); }); } } diff --git a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs index 6d19db999c..60bacf6413 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Default/DefaultInputDrum.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default back = rim; } - if (target != null) + if (target != null && back != null) { const float scale_amount = 0.05f; const float alpha_amount = 0.5f; diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs index f97019e466..c6dad1b25e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHUDOverlay.cs @@ -213,7 +213,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("attempt seek", () => { - InputManager.MoveMouseTo(getSongProgress()); + InputManager.MoveMouseTo(getSongProgress().AsNonNull()); InputManager.Click(MouseButton.Left); }); diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index f094d40caa..af3a6e178c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -825,6 +825,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Click on a filtered difficulty", () => { + Debug.Assert(filteredIcon != null); + InputManager.MoveMouseTo(filteredIcon); InputManager.Click(MouseButton.Left); @@ -918,6 +920,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Click on a difficulty", () => { + Debug.Assert(difficultyIcon != null); + InputManager.MoveMouseTo(difficultyIcon); InputManager.Click(MouseButton.Left); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index d566a04261..dcb1f730a2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("dismiss mod customisation via toggle", () => { - InputManager.MoveMouseTo(modSelectOverlay.CustomisationButton); + InputManager.MoveMouseTo(modSelectOverlay.CustomisationButton.AsNonNull()); InputManager.Click(MouseButton.Left); }); assertCustomisationToggleState(disabled: false, active: false); @@ -558,7 +558,7 @@ namespace osu.Game.Tests.Visual.UserInterface void navigateAndClick() where T : Drawable { - InputManager.MoveMouseTo(modSelectOverlay.ChildrenOfType().FirstOrDefault()); + InputManager.MoveMouseTo(modSelectOverlay.ChildrenOfType().First()); InputManager.Click(MouseButton.Left); } } From 58e6b3782b63e3c16ed1e4ae056f2ec5bb2222f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 24 Jun 2023 09:48:16 +0900 Subject: [PATCH 1358/1400] Fix a couple of remaining issues --- .../Visual/Online/TestSceneCurrentlyPlayingDisplay.cs | 2 +- osu.Game/Rulesets/RulesetStore.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs index 885c00be80..5237238f63 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCurrentlyPlayingDisplay.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Online public void TestBasicDisplay() { AddStep("Add playing user", () => spectatorClient.SendStartPlay(streamingUser.Id, 0)); - AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType()?.FirstOrDefault()?.User.Id == 2); + AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType().FirstOrDefault()?.User.Id == 2); AddStep("Remove playing user", () => spectatorClient.SendEndPlay(streamingUser.Id)); AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType().Any()); } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 881b09bd1b..ac36ee6494 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Reflection; using osu.Framework; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Logging; using osu.Framework.Platform; @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets // This null check prevents Android from attempting to load the rulesets from disk, // as the underlying path "AppContext.BaseDirectory", despite being non-nullable, it returns null on android. // See https://github.com/xamarin/xamarin-android/issues/3489. - if (RuntimeInfo.StartupDirectory != null) + if (RuntimeInfo.StartupDirectory.IsNotNull()) loadFromDisk(); // the event handler contains code for resolving dependency on the game assembly for rulesets located outside the base game directory. From 354e85a2e15c081f8742d29c4880f862b2d85fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 14:35:23 +0200 Subject: [PATCH 1359/1400] Trim redundant BDL nullability spec --- .../Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs index 01408ca087..cf97743fde 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSettings/GeneralSettings.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Settings.Sections.DebugSettings { protected override LocalisableString Header => DebugSettingsStrings.GeneralHeader; - [BackgroundDependencyLoader(true)] + [BackgroundDependencyLoader] private void load(FrameworkDebugConfigManager config, FrameworkConfigManager frameworkConfig, IPerformFromScreenRunner? performer) { Children = new Drawable[] From 1f2f522a1ee3e16a0df4d41a6f27fac7c169597b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 15:07:04 +0200 Subject: [PATCH 1360/1400] Mark override as null-accepting `ModelBackedDrawable.CreateDrawable()` is R#-annotated to accept a potentially null model. Apply nullability there too for better reading experience. --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 67eedf655e..0bb60847e5 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.Drawables protected override double TransformDuration => 400; - protected override Drawable CreateDrawable(IBeatmapInfo model) + protected override Drawable CreateDrawable(IBeatmapInfo? model) { var drawable = getDrawableForModel(model); drawable.RelativeSizeAxes = Axes.Both; From 8fdd599b39cb50005177312b73cadfa62405a810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 15:17:14 +0200 Subject: [PATCH 1361/1400] Match field NRT annotation in ctor argument --- osu.Game/Overlays/Changelog/ChangelogListing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogListing.cs b/osu.Game/Overlays/Changelog/ChangelogListing.cs index c4320dcbd0..5f1ae5b6fa 100644 --- a/osu.Game/Overlays/Changelog/ChangelogListing.cs +++ b/osu.Game/Overlays/Changelog/ChangelogListing.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Changelog { private readonly List? entries; - public ChangelogListing(List entries) + public ChangelogListing(List? entries) { this.entries = entries; } From 66ef199fa47a3b68047e8879284f44aca2de6007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 15:35:07 +0200 Subject: [PATCH 1362/1400] Revert nullability enable in `Score` (and related changes) Causes several knock-on inspections in `OsuGame` et al. Probably best addressed in a separate pass, because treatment is mixed at best (some places nullcheck, some expect non-null). --- osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs | 15 +++++++++------ osu.Game/Scoring/Score.cs | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 2a54ef16c6..f71da6c7e0 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -128,14 +128,17 @@ namespace osu.Game.Scoring.Legacy int lastTime = 0; - foreach (var f in score.Replay.Frames) + if (score.Replay != null) { - var legacyFrame = getLegacyFrame(f); + foreach (var f in score.Replay.Frames) + { + var legacyFrame = getLegacyFrame(f); - // Rounding because stable could only parse integral values - int time = (int)Math.Round(legacyFrame.Time + offset); - replayData.Append(FormattableString.Invariant($"{time - lastTime}|{legacyFrame.MouseX ?? 0}|{legacyFrame.MouseY ?? 0}|{(int)legacyFrame.ButtonState},")); - lastTime = time; + // Rounding because stable could only parse integral values + int time = (int)Math.Round(legacyFrame.Time + offset); + replayData.Append(FormattableString.Invariant($"{time - lastTime}|{legacyFrame.MouseX ?? 0}|{legacyFrame.MouseY ?? 0}|{(int)legacyFrame.ButtonState},")); + lastTime = time; + } } // Warning: this is purposefully hardcoded as a string rather than interpolating, as in some cultures the minus sign is not encoded as the standard ASCII U+00C2 codepoint, diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index 3323706ac1..7152f93f94 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Game.Replays; using osu.Game.Utils; From 2c1a44da895b0be4140704c0fcdca0a614efb3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 15:40:06 +0200 Subject: [PATCH 1363/1400] Revert nullability enable in `BeatmapBackground` Due to varying expectations in handling of `Beatmap`. Some places allow or expect null and some don't. Needs to be looked at closer separately. --- osu.Game/Graphics/Backgrounds/BeatmapBackground.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs index b8de0f7f1e..685f03ae56 100644 --- a/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs +++ b/osu.Game/Graphics/Backgrounds/BeatmapBackground.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using osu.Framework.Allocation; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; @@ -22,7 +24,7 @@ namespace osu.Game.Graphics.Backgrounds [BackgroundDependencyLoader] private void load(LargeTextureStore textures) { - Sprite.Texture = Beatmap.GetBackground() ?? textures.Get(fallbackTextureName); + Sprite.Texture = Beatmap?.GetBackground() ?? textures.Get(fallbackTextureName); } public override bool Equals(Background other) From caf5673b68f3157d09964f487d94aa467cab9ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 16:05:19 +0200 Subject: [PATCH 1364/1400] Revert nullability enables in tournament client Not trivial to fix right now and I'm not fixing in a 1k-line changeset. --- osu.Game.Tournament/Components/DateTextBox.cs | 2 ++ osu.Game.Tournament/Models/LadderInfo.cs | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/DateTextBox.cs b/osu.Game.Tournament/Components/DateTextBox.cs index 4fa94b6c63..f23ad20a67 100644 --- a/osu.Game.Tournament/Components/DateTextBox.cs +++ b/osu.Game.Tournament/Components/DateTextBox.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 3defd517cd..229837c94e 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -25,7 +27,7 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] // updated manually in TournamentGameBase - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); public Bindable ChromaKeyWidth = new BindableInt(1024) { From e3a89a6273b01487b5c74130ab66eeedbd1ffaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 16:07:01 +0200 Subject: [PATCH 1365/1400] Fix remaining obvious CI inspections --- .../Edit/DrawableManiaEditorRuleset.cs | 2 +- .../Difficulty/Evaluators/SpeedEvaluator.cs | 2 +- .../Visual/Online/TestSceneNowPlayingCommand.cs | 5 +++-- osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs | 10 ++++++---- .../Ranking/TestSceneExpandedPanelMiddleContent.cs | 2 +- osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs | 2 +- .../Containers/Markdown/OsuMarkdownContainer.cs | 7 +++++++ osu.Game/Online/API/APIException.cs | 2 +- osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs | 4 ++-- osu.Game/Overlays/BeatmapSet/Info.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 12 files changed, 26 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs index 1e9085bb2f..f480fa516b 100644 --- a/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditorRuleset.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public DrawableManiaEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) + public DrawableManiaEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList? mods) : base(ruleset, beatmap, mods) { } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs index 1ae500ec78..2df383aaa8 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Evaluators/SpeedEvaluator.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators // derive strainTime for calculation var osuCurrObj = (OsuDifficultyHitObject)current; var osuPrevObj = current.Index > 0 ? (OsuDifficultyHitObject)current.Previous(0) : null; - var osuNextObj = (OsuDifficultyHitObject)current.Next(0); + var osuNextObj = (OsuDifficultyHitObject?)current.Next(0); double strainTime = osuCurrObj.StrainTime; double doubletapness = 1; diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs index 10c2b2b9e1..fb36580a42 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs @@ -10,6 +10,7 @@ using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.Chat; +using osu.Game.Online.Rooms; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Users; @@ -32,7 +33,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestGenericActivity() { - AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null)); + AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(new Room())); AddStep("Run command", () => Add(new NowPlayingCommand(new Channel()))); @@ -63,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online [TestCase(false)] public void TestLinkPresence(bool hasOnlineId) { - AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null)); + AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(new Room())); AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null) { diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index a047e2f0c5..c61b572d8c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -9,8 +9,10 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Scoring; using osu.Game.Tests.Beatmaps; using osu.Game.Users; @@ -116,9 +118,9 @@ namespace osu.Game.Tests.Visual.Online AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2)); AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3)); AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap()); - AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(null)); - AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap(null)); - AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(null, null)); + AddStep("editing beatmap", () => activity.Value = new UserActivity.EditingBeatmap(new BeatmapInfo())); + AddStep("modding beatmap", () => activity.Value = new UserActivity.ModdingBeatmap(new BeatmapInfo())); + AddStep("testing beatmap", () => activity.Value = new UserActivity.TestingBeatmap(new BeatmapInfo(), new OsuRuleset().RulesetInfo)); } [Test] @@ -134,7 +136,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert("visit message is not visible", () => !boundPanel2.LastVisitMessage.IsPresent); } - private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(null, rulesetStore.GetRuleset(rulesetId)); + private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(new BeatmapInfo(), rulesetStore.GetRuleset(rulesetId)!); private ScoreInfo createScore(string name) => new ScoreInfo(new TestBeatmap(Ruleset.Value).BeatmapInfo) { diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs index bd7a11b4bb..c05774400f 100644 --- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs +++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual.Ranking private BeatmapInfo createTestBeatmap([NotNull] RealmUser author) { - var beatmap = new TestBeatmap(rulesetStore.GetRuleset(0)).BeatmapInfo; + var beatmap = new TestBeatmap(rulesetStore.GetRuleset(0)!).BeatmapInfo; beatmap.Metadata.Author = author; beatmap.Metadata.Title = "Verrrrrrrrrrrrrrrrrrry looooooooooooooooooooooooong beatmap title"; diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs index 8d5547c749..6b35102014 100644 --- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs +++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs @@ -177,7 +177,7 @@ namespace osu.Game.Tournament.Screens.Schedule Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, - new TournamentSpriteTextWithBackground(match.NewValue.Round.Value?.Name.Value) + new TournamentSpriteTextWithBackground(match.NewValue.Round.Value?.Name.Value ?? string.Empty) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs index a5fc815a5e..041b00c7e1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs @@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Formats writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}")); writer.WriteLine(FormattableString.Invariant($"Countdown: {(int)beatmap.BeatmapInfo.Countdown}")); writer.WriteLine(FormattableString.Invariant( - $"SampleSet: {toLegacySampleBank(((beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePoints?.FirstOrDefault() ?? SampleControlPoint.DEFAULT).SampleBank)}")); + $"SampleSet: {toLegacySampleBank(((beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePoints.FirstOrDefault() ?? SampleControlPoint.DEFAULT).SampleBank)}")); writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}")); writer.WriteLine(FormattableString.Invariant($"Mode: {onlineRulesetID}")); writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}")); diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index 4a61ee2043..b478c4757f 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -35,6 +35,13 @@ namespace osu.Game.Graphics.Containers.Markdown break; case ListItemBlock listItemBlock: + // `ListBlock.Parent` is annotated as null-returning in xmldoc. + // Unfortunately code analysis sees that the type doesn't have NRT enabled and complains. + // This is fixed upstream in 0.24.0 (https://github.com/xoofx/markdig/commit/6684c8257cbbcba2d34457020876be289d3cd8b9), + // but markdig is a transitive dependency from framework, wherein we are locked to 0.23.0 + // (https://github.com/ppy/osu-framework/blob/9746d7d06f48910c05a24687a25f435f30d12f8b/osu.Framework/osu.Framework.csproj#L52C1-L54) + // Therefore... + // ReSharper disable once ConstantConditionalAccessQualifier bool isOrdered = ((ListBlock)listItemBlock.Parent)?.IsOrdered == true; OsuMarkdownListItem childContainer = CreateListItem(listItemBlock, level, isOrdered); diff --git a/osu.Game/Online/API/APIException.cs b/osu.Game/Online/API/APIException.cs index 7491e375df..4327600e13 100644 --- a/osu.Game/Online/API/APIException.cs +++ b/osu.Game/Online/API/APIException.cs @@ -7,7 +7,7 @@ namespace osu.Game.Online.API { public class APIException : InvalidOperationException { - public APIException(string message, Exception innerException) + public APIException(string message, Exception? innerException) : base(message, innerException) { } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs index 7d8160bef7..426fbcdb8d 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapRulesetSelector.cs @@ -11,9 +11,9 @@ namespace osu.Game.Overlays.BeatmapSet { public partial class BeatmapRulesetSelector : OverlayRulesetSelector { - private readonly Bindable beatmapSet = new Bindable(); + private readonly Bindable beatmapSet = new Bindable(); - public APIBeatmapSet BeatmapSet + public APIBeatmapSet? BeatmapSet { get => beatmapSet.Value; set diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index c182ef2e15..d21b2546b9 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet public readonly Bindable BeatmapSet = new Bindable(); - public APIBeatmap BeatmapInfo + public APIBeatmap? BeatmapInfo { get => successRate.Beatmap; set => successRate.Beatmap = value; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 961f8684ce..5dd2486e1c 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -351,7 +351,7 @@ namespace osu.Game.Screens.Select private void addInfoLabels() { - if (working.Beatmap?.HitObjects?.Any() != true) + if (working.Beatmap?.HitObjects.Any() != true) return; infoLabelContainer.Children = new Drawable[] From 34e25403313a0a5926403aac69cd518c5d483c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 17:05:52 +0200 Subject: [PATCH 1366/1400] Fix nullability-related warnings in Android project --- osu.Android/GameplayScreenRotationLocker.cs | 2 +- osu.Android/OsuGameActivity.cs | 15 ++++++++------- osu.Android/OsuGameAndroid.cs | 7 ++++--- osu.Game.Tests.Android/MainActivity.cs | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Android/GameplayScreenRotationLocker.cs b/osu.Android/GameplayScreenRotationLocker.cs index d77b24722a..e5fc354db7 100644 --- a/osu.Android/GameplayScreenRotationLocker.cs +++ b/osu.Android/GameplayScreenRotationLocker.cs @@ -11,7 +11,7 @@ namespace osu.Android { public partial class GameplayScreenRotationLocker : Component { - private Bindable localUserPlaying; + private Bindable localUserPlaying = null!; [Resolved] private OsuGameActivity gameActivity { get; set; } = null!; diff --git a/osu.Android/OsuGameActivity.cs b/osu.Android/OsuGameActivity.cs index 81b218436e..33ffed432e 100644 --- a/osu.Android/OsuGameActivity.cs +++ b/osu.Android/OsuGameActivity.cs @@ -13,6 +13,7 @@ using Android.Graphics; using Android.OS; using Android.Views; using osu.Framework.Android; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Database; using Debug = System.Diagnostics.Debug; using Uri = Android.Net.Uri; @@ -49,11 +50,11 @@ namespace osu.Android /// Adjusted on startup to match expected UX for the current device type (phone/tablet). public ScreenOrientation DefaultOrientation = ScreenOrientation.Unspecified; - private OsuGameAndroid game; + private OsuGameAndroid game = null!; protected override Framework.Game CreateGame() => game = new OsuGameAndroid(this); - protected override void OnCreate(Bundle savedInstanceState) + protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); @@ -90,15 +91,15 @@ namespace osu.Android Assembly.Load("osu.Game.Rulesets.Mania"); } - protected override void OnNewIntent(Intent intent) => handleIntent(intent); + protected override void OnNewIntent(Intent? intent) => handleIntent(intent); - private void handleIntent(Intent intent) + private void handleIntent(Intent? intent) { - switch (intent.Action) + switch (intent?.Action) { case Intent.ActionDefault: if (intent.Scheme == ContentResolver.SchemeContent) - handleImportFromUris(intent.Data); + handleImportFromUris(intent.Data.AsNonNull()); else if (osu_url_schemes.Contains(intent.Scheme)) game.HandleLink(intent.DataString); break; @@ -112,7 +113,7 @@ namespace osu.Android { var content = intent.ClipData?.GetItemAt(i); if (content != null) - uris.Add(content.Uri); + uris.Add(content.Uri.AsNonNull()); } handleImportFromUris(uris.ToArray()); diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs index 96f81c209c..dea70e6b27 100644 --- a/osu.Android/OsuGameAndroid.cs +++ b/osu.Android/OsuGameAndroid.cs @@ -6,6 +6,7 @@ using Android.App; using Microsoft.Maui.Devices; using osu.Framework.Allocation; using osu.Framework.Android.Input; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Input.Handlers; using osu.Framework.Platform; using osu.Game; @@ -30,7 +31,7 @@ namespace osu.Android { get { - var packageInfo = Application.Context.ApplicationContext.PackageManager.GetPackageInfo(Application.Context.ApplicationContext.PackageName, 0); + var packageInfo = Application.Context.ApplicationContext!.PackageManager!.GetPackageInfo(Application.Context.ApplicationContext.PackageName!, 0).AsNonNull(); try { @@ -43,7 +44,7 @@ namespace osu.Android // Basic conversion format (as done in Fastfile): 2020.606.0 -> 202006060 // https://stackoverflow.com/questions/52977079/android-sdk-28-versioncode-in-packageinfo-has-been-deprecated - string versionName = string.Empty; + string versionName; if (OperatingSystem.IsAndroidVersionAtLeast(28)) { @@ -66,7 +67,7 @@ namespace osu.Android { } - return new Version(packageInfo.VersionName); + return new Version(packageInfo.VersionName.AsNonNull()); } } diff --git a/osu.Game.Tests.Android/MainActivity.cs b/osu.Game.Tests.Android/MainActivity.cs index ab43a6766c..d25e46f3c5 100644 --- a/osu.Game.Tests.Android/MainActivity.cs +++ b/osu.Game.Tests.Android/MainActivity.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Android { protected override Framework.Game CreateGame() => new OsuTestBrowser(); - protected override void OnCreate(Bundle savedInstanceState) + protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); From df2dcf85b4b4e7e54755d6d9e56b43ae04e787c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 17:07:42 +0200 Subject: [PATCH 1367/1400] Fix wrong disable --- osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index b478c4757f..5da785603a 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.Containers.Markdown // but markdig is a transitive dependency from framework, wherein we are locked to 0.23.0 // (https://github.com/ppy/osu-framework/blob/9746d7d06f48910c05a24687a25f435f30d12f8b/osu.Framework/osu.Framework.csproj#L52C1-L54) // Therefore... - // ReSharper disable once ConstantConditionalAccessQualifier + // ReSharper disable once ConditionalAccessQualifierIsNonNullableAccordingToAPIContract bool isOrdered = ((ListBlock)listItemBlock.Parent)?.IsOrdered == true; OsuMarkdownListItem childContainer = CreateListItem(listItemBlock, level, isOrdered); From e273c223a8afd7a6c22e3e7de300117fe8832762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 17:11:38 +0200 Subject: [PATCH 1368/1400] Fix some more missed CI inspections --- .../Visual/Online/TestSceneBeatmapRulesetSelector.cs | 2 +- osu.Game/Online/Rooms/JoinRoomRequest.cs | 4 ++-- .../Rulesets/Difficulty/PerformanceBreakdownCalculator.cs | 3 ++- osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs index 36c3576da6..599eee7d0c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online selector.BeatmapSet = new APIBeatmapSet { - Beatmaps = selector.BeatmapSet.Beatmaps + Beatmaps = selector.BeatmapSet!.Beatmaps .Where(b => b.Ruleset.OnlineID != ruleset) .Concat(Enumerable.Range(0, count).Select(_ => new APIBeatmap { RulesetID = ruleset })) .ToArray(), diff --git a/osu.Game/Online/Rooms/JoinRoomRequest.cs b/osu.Game/Online/Rooms/JoinRoomRequest.cs index a1d6ed1e82..8645f2a2c0 100644 --- a/osu.Game/Online/Rooms/JoinRoomRequest.cs +++ b/osu.Game/Online/Rooms/JoinRoomRequest.cs @@ -10,9 +10,9 @@ namespace osu.Game.Online.Rooms public class JoinRoomRequest : APIRequest { public readonly Room Room; - public readonly string Password; + public readonly string? Password; - public JoinRoomRequest(Room room, string password) + public JoinRoomRequest(Room room, string? password) { Room = room; Password = password; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 64a04f896f..8b59500f43 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -88,7 +89,7 @@ namespace osu.Game.Rulesets.Difficulty ).ConfigureAwait(false); // ScorePerformanceCache is not used to avoid caching multiple copies of essentially identical perfect performance attributes - return difficulty == null ? null : ruleset.CreatePerformanceCalculator()?.Calculate(perfectPlay, difficulty.Value.Attributes); + return difficulty == null ? null : ruleset.CreatePerformanceCalculator()?.Calculate(perfectPlay, difficulty.Value.Attributes.AsNonNull()); }, cancellationToken); } diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs index 982275f96a..53a52a8cb8 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomBackgroundScreen.cs @@ -9,9 +9,9 @@ namespace osu.Game.Screens.OnlinePlay.Match { public partial class RoomBackgroundScreen : OnlinePlayBackgroundScreen { - public readonly Bindable SelectedItem = new Bindable(); + public readonly Bindable SelectedItem = new Bindable(); - public RoomBackgroundScreen(PlaylistItem initialPlaylistItem) + public RoomBackgroundScreen(PlaylistItem? initialPlaylistItem) { PlaylistItem = initialPlaylistItem; SelectedItem.BindValueChanged(item => PlaylistItem = item.NewValue); From 9a5f033a0fa6a066d8994322777f2478780463e9 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 24 Jun 2023 18:11:34 +0300 Subject: [PATCH 1369/1400] Change `OpenUserProfile` argument type to always use `IUser` --- osu.Game/Graphics/Containers/LinkFlowContainer.cs | 8 +------- osu.Game/Online/Chat/MessageFormatter.cs | 14 +++++++++++--- osu.Game/OsuGame.cs | 7 +------ .../Sections/Recent/DrawableRecentActivity.cs | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index a2c9b0ac32..2d27ce906b 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -74,13 +74,7 @@ namespace osu.Game.Graphics.Containers } public void AddUserLink(IUser user, Action creationParameters = null) - { - string argument = user.OnlineID > 1 - ? user.OnlineID.ToString() - : user.Username; - - createLink(CreateChunkFor(user.Username, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, argument), "view profile"); - } + => createLink(CreateChunkFor(user.Username, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.OpenUserProfile, user), "view profile"); private void createLink(ITextPart textPart, LinkDetails link, LocalisableString tooltipText, Action action = null) { diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 523185a7cb..f89939d7cf 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.Chat { @@ -172,7 +173,7 @@ namespace osu.Game.Online.Chat case "u": case "users": - return new LinkDetails(LinkAction.OpenUserProfile, mainArg); + return getUserLink(mainArg); case "wiki": return new LinkDetails(LinkAction.OpenWiki, string.Join('/', args.Skip(3))); @@ -230,8 +231,7 @@ namespace osu.Game.Online.Chat break; case "u": - linkType = LinkAction.OpenUserProfile; - break; + return getUserLink(args[2]); default: return new LinkDetails(LinkAction.External, url); @@ -246,6 +246,14 @@ namespace osu.Game.Online.Chat return new LinkDetails(LinkAction.External, url); } + private static LinkDetails getUserLink(string argument) + { + if (int.TryParse(argument, out int userId)) + return new LinkDetails(LinkAction.OpenUserProfile, new APIUser { Id = userId }); + + return new LinkDetails(LinkAction.OpenUserProfile, new APIUser { Username = argument }); + } + private static MessageFormatterResult format(string toFormat, int startIndex = 0, int space = 3) { var result = new MessageFormatterResult(toFormat); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 2db8872524..d8eb63caee 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -45,7 +45,6 @@ using osu.Game.Input.Bindings; using osu.Game.IO; using osu.Game.Localisation; using osu.Game.Online; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Chat; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapListing; @@ -446,11 +445,7 @@ namespace osu.Game break; case LinkAction.OpenUserProfile: - var user = int.TryParse(argString, out int userId) - ? new APIUser { Id = userId } - : new APIUser { Username = argString }; - - ShowUser(user); + ShowUser((IUser)link.Argument); break; case LinkAction.OpenWiki: diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 0479ab7c16..8a0003b4ea 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -223,7 +223,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent private void addBeatmapsetLink() => content.AddLink(activity.Beatmapset.AsNonNull().Title, LinkAction.OpenBeatmapSet, getLinkArgument(activity.Beatmapset.AsNonNull().Url), creationParameters: t => t.Font = getLinkFont()); - private string getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.WebsiteRootUrl}{url}").Argument.ToString().AsNonNull(); + private object getLinkArgument(string url) => MessageFormatter.GetLinkDetails($"{api.WebsiteRootUrl}{url}").Argument.AsNonNull(); private FontUsage getLinkFont(FontWeight fontWeight = FontWeight.Regular) => OsuFont.GetFont(size: font_size, weight: fontWeight, italics: true); From ca402c4d2f4470cba5cd4f21d4a8a4eb15bf5047 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 00:38:19 +0900 Subject: [PATCH 1370/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 66f518f3d5..39c10c2014 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9cb20ee364..d179d354fb 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 256d1e43c4..85cbe3f14b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From f8d2f2f7e1f9f364700b7b10169b667ca0c32837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 24 Jun 2023 19:04:05 +0200 Subject: [PATCH 1371/1400] Fix more issues discovered by CI that can be fixed game-side --- .../Editor/TestScenePathControlPointVisualiser.cs | 2 +- .../Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs index 37561fda85..0d6841017e 100644 --- a/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu.Tests/Editor/TestScenePathControlPointVisualiser.cs @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor { MenuItem item = visualiser.ContextMenuItems.FirstOrDefault(menuItem => menuItem.Text.Value == "Curve type")?.Items.FirstOrDefault(menuItem => menuItem.Text.Value == contextMenuText); - item?.Action?.Value(); + item?.Action.Value?.Invoke(); }); } } diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs index 224e7e411e..5467a64b85 100644 --- a/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs +++ b/osu.Game.Tests/Visual/Navigation/TestSceneChangeAndUseGameplayBindings.cs @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.Navigation private OsuButton configureBindingsButton => Game.Settings .ChildrenOfType().SingleOrDefault()? - .ChildrenOfType()? + .ChildrenOfType() .First(b => b.Text.ToString() == "Configure"); private KeyBindingPanel keyBindingPanel => Game.Settings From 5806153cfd6dd176cb584ea700a8416f0bb52a5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 12:00:14 +0900 Subject: [PATCH 1372/1400] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 39c10c2014..fdec4e575b 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -11,7 +11,7 @@ manifestmerger.jar - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index d179d354fb..ce03dca949 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -36,7 +36,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index 85cbe3f14b..86694e268a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -16,6 +16,6 @@ iossimulator-x64 - + From 922fe927ac62ddd2af867093d7c36d26fe043f7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 15:18:56 +0900 Subject: [PATCH 1373/1400] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index ce03dca949..b4d8dd513f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,7 +37,7 @@ - + From 0dced4610035b07c48856324314c3be5a18af92f Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 25 Jun 2023 20:46:28 +0900 Subject: [PATCH 1374/1400] remove `#nullable disable` in `LadderInfo` --- osu.Game.Tournament/Models/LadderInfo.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 229837c94e..3defd517cd 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.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. -#nullable disable - using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -27,7 +25,7 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] // updated manually in TournamentGameBase - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); public Bindable ChromaKeyWidth = new BindableInt(1024) { From a3cd0d14a3f3caea616a3ab635a9f5f67463787e Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 25 Jun 2023 20:46:58 +0900 Subject: [PATCH 1375/1400] null guard for Current Match in MatchMessage --- .../TestSceneTournamentMatchChatDisplay.cs | 24 +++++++++---------- .../Components/TournamentMatchChatDisplay.cs | 10 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index f627bd2ad2..bf59678ac5 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -63,18 +63,6 @@ namespace osu.Game.Tournament.Tests.Components Origin = Anchor.Centre, }); - ladderInfo.CurrentMatch.Value = new TournamentMatch - { - Team1 = - { - Value = new TournamentTeam { Players = new BindableList { redUser } } - }, - Team2 = - { - Value = new TournamentTeam { Players = new BindableList { blueUser, blueUserWithCustomColour } } - } - }; - chatDisplay.Channel.Value = testChannel; } @@ -88,6 +76,18 @@ namespace osu.Game.Tournament.Tests.Components Content = "I am a wang!" })); + AddStep("set Current match", () => ladderInfo.CurrentMatch.Value = new TournamentMatch + { + Team1 = + { + Value = new TournamentTeam { Players = new BindableList { redUser } } + }, + Team2 = + { + Value = new TournamentTeam { Players = new BindableList { blueUser, blueUserWithCustomColour } } + } + }); + AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId()) { Sender = redUser.ToAPIUser(), diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index 2a2e45d70c..bb8d86e7e2 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.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. -#nullable disable - using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -19,10 +17,10 @@ namespace osu.Game.Tournament.Components { private readonly Bindable chatChannel = new Bindable(); - private ChannelManager manager; + private ChannelManager? manager; [Resolved] - private LadderInfo ladderInfo { get; set; } + private LadderInfo ladderInfo { get; set; } = null!; public TournamentMatchChatDisplay() { @@ -35,7 +33,7 @@ namespace osu.Game.Tournament.Components } [BackgroundDependencyLoader(true)] - private void load(MatchIPCInfo ipc, IAPIProvider api) + private void load(MatchIPCInfo? ipc, IAPIProvider api) { if (ipc != null) { @@ -92,6 +90,8 @@ namespace osu.Game.Tournament.Components public MatchMessage(Message message, LadderInfo info) : base(message) { + if (info.CurrentMatch.Value == null) return; + if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) UsernameColour = TournamentGame.COLOUR_RED; else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) From 95e8dd2e8ef27669bf9a19a326fde1d6397c35f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 21:25:07 +0900 Subject: [PATCH 1376/1400] Don't attempt to access notifications before loaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- osu.Game/Overlays/NotificationOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 28803fe590..f1e39b947d 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays public const float TRANSITION_LENGTH = 600; public IEnumerable AllNotifications => - toastTray.Notifications.Concat(sections.SelectMany(s => s.Notifications)); + IsLoaded ? toastTray.Notifications.Concat(sections.SelectMany(s => s.Notifications)) : Array.Empty(); private FlowContainer sections = null!; From 3d1a8aeb540799e3d62fc915805b3dd3678beb69 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 21:24:39 +0900 Subject: [PATCH 1377/1400] Use more understandable cancel button text --- osu.Game/Screens/Menu/ConfirmExitDialog.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ConfirmExitDialog.cs b/osu.Game/Screens/Menu/ConfirmExitDialog.cs index fb22f7eff8..0041d047bd 100644 --- a/osu.Game/Screens/Menu/ConfirmExitDialog.cs +++ b/osu.Game/Screens/Menu/ConfirmExitDialog.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; +using osu.Game.Localisation; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; @@ -52,7 +53,7 @@ namespace osu.Game.Screens.Menu }, new PopupDialogCancelButton { - Text = @"Cancel", + Text = CommonStrings.Back, Action = onCancel }, }; From cf43cd2bdcc165eca96d7b569b2f26a617e049bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 25 Jun 2023 21:26:08 +0900 Subject: [PATCH 1378/1400] Rename test scene to match updated class name --- ...dToConfirmOverlay.cs => TestSceneHoldToExitGameOverlay.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/UserInterface/{TestSceneHoldToConfirmOverlay.cs => TestSceneHoldToExitGameOverlay.cs} (94%) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToExitGameOverlay.cs similarity index 94% rename from osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneHoldToExitGameOverlay.cs index 58d1637ca7..df423268b6 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHoldToExitGameOverlay.cs @@ -8,11 +8,11 @@ using osu.Game.Screens.Menu; namespace osu.Game.Tests.Visual.UserInterface { - public partial class TestSceneHoldToConfirmOverlay : OsuTestScene + public partial class TestSceneHoldToExitGameOverlay : OsuTestScene { protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms - public TestSceneHoldToConfirmOverlay() + public TestSceneHoldToExitGameOverlay() { bool fired = false; From 4215ca313f17f147d3b0ca2d2feaeb04abf062bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jun 2023 14:36:21 +0200 Subject: [PATCH 1379/1400] Add missing using --- osu.Game/Overlays/NotificationOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index f1e39b947d..21027b0931 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.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 System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; From e02a06e3e557f793f4c61d688cf8712524f9bc08 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 25 Jun 2023 22:47:36 +0900 Subject: [PATCH 1380/1400] Revert "remove `#nullable disable` in `LadderInfo`" This reverts commit 0dced4610035b07c48856324314c3be5a18af92f. --- osu.Game.Tournament/Models/LadderInfo.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Models/LadderInfo.cs b/osu.Game.Tournament/Models/LadderInfo.cs index 3defd517cd..229837c94e 100644 --- a/osu.Game.Tournament/Models/LadderInfo.cs +++ b/osu.Game.Tournament/Models/LadderInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable disable + using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -25,7 +27,7 @@ namespace osu.Game.Tournament.Models public List Progressions = new List(); [JsonIgnore] // updated manually in TournamentGameBase - public Bindable CurrentMatch = new Bindable(); + public Bindable CurrentMatch = new Bindable(); public Bindable ChromaKeyWidth = new BindableInt(1024) { From 14e26d2a850e8e366c25ed0e39456024cca39e42 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Sun, 25 Jun 2023 22:42:02 +0900 Subject: [PATCH 1381/1400] use BeatmapCache for populate beatmap information --- osu.Game.Tournament/TournamentGameBase.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 634cc87a9f..2067295eb6 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -15,6 +15,7 @@ using osu.Framework.Input; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Framework.Platform; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Online; using osu.Game.Online.API.Requests; @@ -35,6 +36,7 @@ namespace osu.Game.Tournament private TournamentStorage storage; private DependencyContainer dependencies; private FileBasedIPC ipc; + private BeatmapLookupCache beatmapCache; protected Task BracketLoadTask => bracketLoadTaskCompletionSource.Task; @@ -75,6 +77,8 @@ namespace osu.Game.Tournament Textures.AddTextureSource(new TextureLoaderStore(new StorageBackedResourceStore(storage))); dependencies.CacheAs(new StableInfo(storage)); + + beatmapCache = dependencies.Get(); } protected override void LoadComplete() @@ -241,9 +245,7 @@ namespace osu.Game.Tournament { var b = beatmapsRequiringPopulation[i]; - var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); - API.Perform(req); - b.Beatmap = new TournamentBeatmap(req.Response ?? new APIBeatmap()); + b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetAwaiter().GetResult() ?? new APIBeatmap()); updateLoadProgressMessage($"Populating round beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } @@ -268,9 +270,7 @@ namespace osu.Game.Tournament { var b = beatmapsRequiringPopulation[i]; - var req = new GetBeatmapRequest(new APIBeatmap { OnlineID = b.ID }); - API.Perform(req); - b.Beatmap = new TournamentBeatmap(req.Response ?? new APIBeatmap()); + b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetAwaiter().GetResult() ?? new APIBeatmap()); updateLoadProgressMessage($"Populating seeding beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } From 9862992af0b415b3bfb4685196d35347ddd9397b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jun 2023 17:36:44 +0200 Subject: [PATCH 1382/1400] Use alternative guard Early-returning from ctors feels pretty bad. Also saves on some nested accesses. --- .../Components/TournamentMatchChatDisplay.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index bb8d86e7e2..15c37474f5 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -90,12 +90,13 @@ namespace osu.Game.Tournament.Components public MatchMessage(Message message, LadderInfo info) : base(message) { - if (info.CurrentMatch.Value == null) return; - - if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) - UsernameColour = TournamentGame.COLOUR_RED; - else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) - UsernameColour = TournamentGame.COLOUR_BLUE; + if (info.CurrentMatch.Value is TournamentMatch match) + { + if (match.Team1.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + UsernameColour = TournamentGame.COLOUR_RED; + else if (match.Team2.Value.Players.Any(u => u.OnlineID == Message.Sender.OnlineID)) + UsernameColour = TournamentGame.COLOUR_BLUE; + } } } } From 7d9d7066cd525ae6d20afeef6f206e9b27457730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jun 2023 17:39:15 +0200 Subject: [PATCH 1383/1400] Remove no-longer-needed BDL `permitNulls` spec --- osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs index 15c37474f5..e943cb8b8c 100644 --- a/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Tournament.Components CornerRadius = 0; } - [BackgroundDependencyLoader(true)] + [BackgroundDependencyLoader] private void load(MatchIPCInfo? ipc, IAPIProvider api) { if (ipc != null) From 44a3f401887a1d1fa5f1c7076e3b694e8ce17386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 25 Jun 2023 17:39:36 +0200 Subject: [PATCH 1384/1400] Rename test step --- .../Components/TestSceneTournamentMatchChatDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs index bf59678ac5..044e5ebbbf 100644 --- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs +++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentMatchChatDisplay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tournament.Tests.Components Content = "I am a wang!" })); - AddStep("set Current match", () => ladderInfo.CurrentMatch.Value = new TournamentMatch + AddStep("set current match", () => ladderInfo.CurrentMatch.Value = new TournamentMatch { Team1 = { From 1b671b8c6e3296d373d168f643745af660a81399 Mon Sep 17 00:00:00 2001 From: cdwcgt Date: Mon, 26 Jun 2023 00:45:59 +0900 Subject: [PATCH 1385/1400] Use `GetResultSafely()` --- osu.Game.Tournament/TournamentGameBase.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 2067295eb6..7d0571dde0 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Allocation; +using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Input; @@ -245,7 +246,7 @@ namespace osu.Game.Tournament { var b = beatmapsRequiringPopulation[i]; - b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetAwaiter().GetResult() ?? new APIBeatmap()); + b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetResultSafely() ?? new APIBeatmap()); updateLoadProgressMessage($"Populating round beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } @@ -270,7 +271,7 @@ namespace osu.Game.Tournament { var b = beatmapsRequiringPopulation[i]; - b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetAwaiter().GetResult() ?? new APIBeatmap()); + b.Beatmap = new TournamentBeatmap(beatmapCache.GetBeatmapAsync(b.ID).GetResultSafely() ?? new APIBeatmap()); updateLoadProgressMessage($"Populating seeding beatmaps ({i} / {beatmapsRequiringPopulation.Count})"); } From 25c9bf40614b2c89683b5415f43163baf7760b77 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 11:22:05 -0700 Subject: [PATCH 1386/1400] Improve and refactor `LoginPanel` test scene to use `LoginOverlay` --- .../Visual/Menus/TestSceneLoginOverlay.cs | 89 +++++++++++++++++++ .../Visual/Menus/TestSceneLoginPanel.cs | 78 ---------------- osu.Game/Online/API/DummyAPIAccess.cs | 8 ++ 3 files changed, 97 insertions(+), 78 deletions(-) create mode 100644 osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs delete mode 100644 osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs new file mode 100644 index 0000000000..5c2edac84d --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -0,0 +1,89 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API; +using osu.Game.Overlays; +using osu.Game.Users.Drawables; +using osuTK.Input; + +namespace osu.Game.Tests.Visual.Menus +{ + [TestFixture] + public partial class TestSceneLoginOverlay : OsuManualInputManagerTestScene + { + private LoginOverlay loginOverlay = null!; + + [BackgroundDependencyLoader] + private void load() + { + Child = loginOverlay = new LoginOverlay + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; + } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("show login overlay", () => loginOverlay.Show()); + } + + [Test] + public void TestLoginSuccess() + { + AddStep("logout", () => API.Logout()); + + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + } + + [Test] + public void TestLoginFailure() + { + AddStep("logout", () => + { + API.Logout(); + ((DummyAPIAccess)API).FailNextLogin(); + }); + + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + } + + [Test] + public void TestLoginConnecting() + { + AddStep("logout", () => + { + API.Logout(); + ((DummyAPIAccess)API).StayConnectingNextLogin(); + }); + + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + } + + [Test] + public void TestClickingOnFlagClosesOverlay() + { + AddStep("logout", () => API.Logout()); + AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); + AddStep("submit", () => loginOverlay.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); + + AddStep("click on flag", () => + { + InputManager.MoveMouseTo(loginOverlay.ChildrenOfType().First()); + InputManager.Click(MouseButton.Left); + }); + AddAssert("login overlay is hidden", () => loginOverlay.State.Value == Visibility.Hidden); + } + } +} diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs deleted file mode 100644 index 738220f5ce..0000000000 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginPanel.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -#nullable disable - -using System.Linq; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.Testing; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Overlays.Login; -using osu.Game.Users.Drawables; -using osuTK.Input; - -namespace osu.Game.Tests.Visual.Menus -{ - [TestFixture] - public partial class TestSceneLoginPanel : OsuManualInputManagerTestScene - { - private LoginPanel loginPanel; - private int hideCount; - - [SetUpSteps] - public void SetUpSteps() - { - AddStep("create login dialog", () => - { - Add(loginPanel = new LoginPanel - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 0.5f, - RequestHide = () => hideCount++, - }); - }); - } - - [Test] - public void TestLoginSuccess() - { - AddStep("logout", () => API.Logout()); - - AddStep("enter password", () => loginPanel.ChildrenOfType().First().Text = "password"); - AddStep("submit", () => loginPanel.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); - } - - [Test] - public void TestLoginFailure() - { - AddStep("logout", () => - { - API.Logout(); - ((DummyAPIAccess)API).FailNextLogin(); - }); - - AddStep("enter password", () => loginPanel.ChildrenOfType().First().Text = "password"); - AddStep("submit", () => loginPanel.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); - } - - [Test] - public void TestClickingOnFlagClosesPanel() - { - AddStep("reset hide count", () => hideCount = 0); - - AddStep("logout", () => API.Logout()); - AddStep("enter password", () => loginPanel.ChildrenOfType().First().Text = "password"); - AddStep("submit", () => loginPanel.ChildrenOfType().First(b => b.Text.ToString() == "Sign in").TriggerClick()); - - AddStep("click on flag", () => - { - InputManager.MoveMouseTo(loginPanel.ChildrenOfType().First()); - InputManager.Click(MouseButton.Left); - }); - AddAssert("hide requested", () => hideCount == 1); - } - } -} diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index bf9baa4414..c2ef0b4e92 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -56,6 +56,7 @@ namespace osu.Game.Online.API private readonly Bindable state = new Bindable(APIState.Online); private bool shouldFailNextLogin; + private bool stayConnectingNextLogin; /// /// The current connectivity state of the API. @@ -94,6 +95,12 @@ namespace osu.Game.Online.API { state.Value = APIState.Connecting; + if (stayConnectingNextLogin) + { + stayConnectingNextLogin = false; + return; + } + if (shouldFailNextLogin) { LastLoginError = new APIException("Not powerful enough to login.", new ArgumentException(nameof(shouldFailNextLogin))); @@ -138,6 +145,7 @@ namespace osu.Game.Online.API IBindable IAPIProvider.Activity => Activity; public void FailNextLogin() => shouldFailNextLogin = true; + public void StayConnectingNextLogin() => stayConnectingNextLogin = true; protected override void Dispose(bool isDisposing) { From 1058f434d75d74f3814c5f90756e14824decda26 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 10:07:30 -0700 Subject: [PATCH 1387/1400] Update login overlay background to conform to other overlays --- osu.Game/Overlays/LoginOverlay.cs | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 8b60024682..b16cc5bd4b 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -4,9 +4,10 @@ #nullable disable using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; +using osu.Framework.Graphics.Effects; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; @@ -21,13 +22,24 @@ namespace osu.Game.Overlays private const float transition_time = 400; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + public LoginOverlay() { AutoSizeAxes = Axes.Both; + Masking = true; + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0), + Type = EdgeEffectType.Shadow, + Radius = 10, + Hollow = true, + }; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Children = new Drawable[] { @@ -40,8 +52,7 @@ namespace osu.Game.Overlays new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, + Colour = colourProvider.Background4, }, new Container { @@ -50,23 +61,11 @@ namespace osu.Game.Overlays Masking = true, AutoSizeDuration = transition_time, AutoSizeEasing = Easing.OutQuint, - Children = new Drawable[] + Child = panel = new LoginPanel { - panel = new LoginPanel - { - Padding = new MarginPadding(10), - RequestHide = Hide, - }, - new Box - { - RelativeSizeAxes = Axes.X, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Height = 3, - Colour = colours.Yellow, - Alpha = 1, - }, - } + Padding = new MarginPadding(10), + RequestHide = Hide, + }, } } } @@ -77,6 +76,7 @@ namespace osu.Game.Overlays { panel.Bounding = true; this.FadeIn(transition_time, Easing.OutQuint); + FadeEdgeEffectTo(WaveContainer.SHADOW_OPACITY, WaveContainer.APPEAR_DURATION, Easing.Out); ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(panel)); } @@ -87,6 +87,7 @@ namespace osu.Game.Overlays panel.Bounding = false; this.FadeOut(transition_time); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.In); } } } From 442fda3598699f69853d739634473a60378389e8 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 10:15:16 -0700 Subject: [PATCH 1388/1400] Remove using aliases --- osu.Game/Overlays/Login/LoginPanel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 79569ada65..80238f5474 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -18,8 +19,6 @@ using osu.Game.Localisation; using osu.Game.Online.API; using osu.Game.Users; using osuTK; -using RectangleF = osu.Framework.Graphics.Primitives.RectangleF; -using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Overlays.Login { From 4a3b8c405eeb27ab6b7e7e7743f332d0940ab14c Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 11:47:32 -0700 Subject: [PATCH 1389/1400] Fix login error text adding unnecessary spacing --- osu.Game/Overlays/Login/LoginForm.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 47e706fe58..f56753dbe7 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -73,6 +73,7 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Alpha = 0, }, new SettingsCheckbox { @@ -128,7 +129,10 @@ namespace osu.Game.Overlays.Login password.OnCommit += (_, _) => performLogin(); if (api.LastLoginError?.Message is string error) + { + errorText.Alpha = 1; errorText.AddErrors(new[] { error }); + } } public override bool AcceptsFocus => true; From 59fa46bbdd6933f304521d298ef61720d3ed8929 Mon Sep 17 00:00:00 2001 From: Bastian Pedersen Date: Sun, 25 Jun 2023 21:02:41 +0200 Subject: [PATCH 1390/1400] Create localisation string class for multiplayer countdown buttons --- .../MultiplayerCountdownButtonStrings.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs diff --git a/osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs b/osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs new file mode 100644 index 0000000000..926b15386a --- /dev/null +++ b/osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class MultiplayerCountdownButtonStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerCountdownButton"; + + /// + /// "Stop countdown" + /// + public static LocalisableString StopCountdown => new TranslatableString(getKey(@"stop_countdown"), @"Stop countdown"); + + /// + /// "Countdown settings" + /// + public static LocalisableString CountdownSettings => new TranslatableString(getKey(@"countdown_settings"), @"Countdown settings"); + + /// + /// "Start match in {0} minute/seconds" + /// + public static LocalisableString StartMatchInTime(string humanReadableTime) => new TranslatableString(getKey(@"start_match_in"), @"Start match in {0}", humanReadableTime); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} From a7153478d6e9c143cbe203a26bfeb24b0ffd47ca Mon Sep 17 00:00:00 2001 From: Bastian Pedersen Date: Sun, 25 Jun 2023 21:03:07 +0200 Subject: [PATCH 1391/1400] Use newly create localised strings for buttons --- .../Multiplayer/Match/MultiplayerCountdownButton.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs index 6dc343f00a..72c3a8122d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; +using osu.Game.Localisation; using osu.Game.Online.Multiplayer; using osuTK; @@ -56,7 +57,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match base.Action = this.ShowPopover; - TooltipText = "Countdown settings"; + TooltipText = MultiplayerCountdownButtonStrings.CountdownSettings; } [BackgroundDependencyLoader] @@ -112,7 +113,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, - Text = $"Start match in {duration.Humanize()}", + Text = MultiplayerCountdownButtonStrings.StartMatchInTime(duration.Humanize()), BackgroundColour = colours.Green, Action = () => { @@ -127,7 +128,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, - Text = "Stop countdown", + Text = MultiplayerCountdownButtonStrings.StopCountdown, BackgroundColour = colours.Red, Action = () => { From 4582faee7988c4c0b3a49c1c47058edb39217174 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 12:06:02 -0700 Subject: [PATCH 1392/1400] Refactor login panel to not inherit `FillFlowContainer` --- osu.Game/Overlays/Login/LoginForm.cs | 6 ++ osu.Game/Overlays/Login/LoginPanel.cs | 101 ++++++++++++-------------- 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index f56753dbe7..55490198f8 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -11,6 +11,7 @@ using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Overlays.Settings; @@ -56,6 +57,11 @@ namespace osu.Game.Overlays.Login Children = new Drawable[] { + new OsuSpriteText + { + Text = LoginPanelStrings.Account.ToUpper(), + Font = OsuFont.GetFont(weight: FontWeight.Bold), + }, username = new OsuTextBox { PlaceholderText = UsersStrings.LoginUsername.ToLower(), diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 80238f5474..6c09b2e6ed 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -22,7 +22,7 @@ using osuTK; namespace osu.Game.Overlays.Login { - public partial class LoginPanel : FillFlowContainer + public partial class LoginPanel : Container { private bool bounding = true; private LoginForm form; @@ -59,8 +59,6 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Direction = FillDirection.Vertical; - Spacing = new Vector2(0f, 5f); } [BackgroundDependencyLoader] @@ -77,18 +75,9 @@ namespace osu.Game.Overlays.Login switch (state.NewValue) { case APIState.Offline: - Children = new Drawable[] + Child = form = new LoginForm { - new OsuSpriteText - { - Text = LoginPanelStrings.Account.ToUpper(), - Margin = new MarginPadding { Bottom = 5 }, - Font = OsuFont.GetFont(weight: FontWeight.Bold), - }, - form = new LoginForm - { - RequestHide = RequestHide - } + RequestHide = RequestHide }; break; @@ -96,22 +85,29 @@ namespace osu.Game.Overlays.Login case APIState.Connecting: LinkFlowContainer linkFlow; - Children = new Drawable[] + Child = new FillFlowContainer { - new LoadingSpinner + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, 5f), + Children = new Drawable[] { - State = { Value = Visibility.Visible }, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - }, - linkFlow = new LinkFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextAnchor = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Text = state.NewValue == APIState.Failing ? ToolbarStrings.AttemptingToReconnect : ToolbarStrings.Connecting, - Margin = new MarginPadding { Top = 10, Bottom = 10 }, + new LoadingSpinner + { + State = { Value = Visibility.Visible }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + linkFlow = new LinkFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextAnchor = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Text = state.NewValue == APIState.Failing ? ToolbarStrings.AttemptingToReconnect : ToolbarStrings.Connecting, + Margin = new MarginPadding { Top = 10, Bottom = 10 }, + }, }, }; @@ -119,40 +115,37 @@ namespace osu.Game.Overlays.Login break; case APIState.Online: - Children = new Drawable[] + Child = new FillFlowContainer { - new FillFlowContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 20, Right = 20 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, 10f), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 20, Right = 20 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0f, 10f), - Children = new Drawable[] + new Container { - new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] + new OsuSpriteText { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = LoginPanelStrings.SignedIn, - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), - Margin = new MarginPadding { Top = 5, Bottom = 5 }, - }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = LoginPanelStrings.SignedIn, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), + Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, }, - panel = new UserGridPanel(api.LocalUser.Value) - { - RelativeSizeAxes = Axes.X, - Action = RequestHide - }, - dropdown = new UserDropdown { RelativeSizeAxes = Axes.X }, }, + panel = new UserGridPanel(api.LocalUser.Value) + { + RelativeSizeAxes = Axes.X, + Action = RequestHide + }, + dropdown = new UserDropdown { RelativeSizeAxes = Axes.X }, }, }; From 671f84e32b26f6a92cdd5a3d82b0215d8b65f708 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 12:15:03 -0700 Subject: [PATCH 1393/1400] Remove unnecessary container --- osu.Game/Overlays/Login/LoginPanel.cs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 6c09b2e6ed..885f5639a7 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -124,21 +124,13 @@ namespace osu.Game.Overlays.Login Spacing = new Vector2(0f, 10f), Children = new Drawable[] { - new Container + new OsuSpriteText { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new[] - { - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = LoginPanelStrings.SignedIn, - Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), - Margin = new MarginPadding { Top = 5, Bottom = 5 }, - }, - }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = LoginPanelStrings.SignedIn, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), + Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, panel = new UserGridPanel(api.LocalUser.Value) { From 6ebc2581c2a207fe45ee1b6cac2adb2a9bfe04cf Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 12:26:01 -0700 Subject: [PATCH 1394/1400] Normalise login overlay padding/spacing --- osu.Game/Overlays/Login/LoginForm.cs | 67 +++++++++++++------------ osu.Game/Overlays/Login/LoginPanel.cs | 10 ++-- osu.Game/Overlays/Login/UserDropdown.cs | 3 -- osu.Game/Overlays/LoginOverlay.cs | 3 +- 4 files changed, 42 insertions(+), 41 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginForm.cs b/osu.Game/Overlays/Login/LoginForm.cs index 55490198f8..0eef55162f 100644 --- a/osu.Game/Overlays/Login/LoginForm.cs +++ b/osu.Game/Overlays/Login/LoginForm.cs @@ -43,43 +43,50 @@ namespace osu.Game.Overlays.Login [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuConfigManager config, AccountCreationOverlay accountCreation) { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; Spacing = new Vector2(0, SettingsSection.ITEM_SPACING); - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; - Padding = new MarginPadding - { - Top = 5, - Bottom = 24, - }; + ErrorTextFlowContainer errorText; LinkFlowContainer forgottenPasswordLink; Children = new Drawable[] { - new OsuSpriteText - { - Text = LoginPanelStrings.Account.ToUpper(), - Font = OsuFont.GetFont(weight: FontWeight.Bold), - }, - username = new OsuTextBox - { - PlaceholderText = UsersStrings.LoginUsername.ToLower(), - RelativeSizeAxes = Axes.X, - Text = api.ProvidedUsername, - TabbableContentContainer = this - }, - password = new OsuPasswordTextBox - { - PlaceholderText = UsersStrings.LoginPassword.ToLower(), - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - }, - errorText = new ErrorTextFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Alpha = 0, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), + Children = new Drawable[] + { + new OsuSpriteText + { + Text = LoginPanelStrings.Account.ToUpper(), + Font = OsuFont.GetFont(weight: FontWeight.Bold), + }, + username = new OsuTextBox + { + PlaceholderText = UsersStrings.LoginUsername.ToLower(), + RelativeSizeAxes = Axes.X, + Text = api.ProvidedUsername, + TabbableContentContainer = this + }, + password = new OsuPasswordTextBox + { + PlaceholderText = UsersStrings.LoginPassword.ToLower(), + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + }, + errorText = new ErrorTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Alpha = 0, + }, + }, }, new SettingsCheckbox { @@ -93,11 +100,7 @@ namespace osu.Game.Overlays.Login }, forgottenPasswordLink = new LinkFlowContainer { - Padding = new MarginPadding - { - Left = SettingsPanel.CONTENT_MARGINS, - Bottom = SettingsSection.ITEM_SPACING - }, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, }, diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 885f5639a7..a84a211dfc 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -17,6 +17,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; using osu.Game.Online.API; +using osu.Game.Overlays.Settings; using osu.Game.Users; using osuTK; @@ -89,8 +90,9 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, Direction = FillDirection.Vertical, - Spacing = new Vector2(0f, 5f), + Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), Children = new Drawable[] { new LoadingSpinner @@ -106,7 +108,6 @@ namespace osu.Game.Overlays.Login TextAnchor = Anchor.TopCentre, AutoSizeAxes = Axes.Both, Text = state.NewValue == APIState.Failing ? ToolbarStrings.AttemptingToReconnect : ToolbarStrings.Connecting, - Margin = new MarginPadding { Top = 10, Bottom = 10 }, }, }, }; @@ -119,9 +120,9 @@ namespace osu.Game.Overlays.Login { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 20, Right = 20 }, + Padding = new MarginPadding { Horizontal = SettingsPanel.CONTENT_MARGINS }, Direction = FillDirection.Vertical, - Spacing = new Vector2(0f, 10f), + Spacing = new Vector2(0f, SettingsSection.ITEM_SPACING), Children = new Drawable[] { new OsuSpriteText @@ -130,7 +131,6 @@ namespace osu.Game.Overlays.Login Origin = Anchor.TopCentre, Text = LoginPanelStrings.SignedIn, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), - Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, panel = new UserGridPanel(api.LocalUser.Value) { diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index 78b5271ca0..9ffaaff8bf 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -36,8 +36,6 @@ namespace osu.Game.Overlays.Login Masking = true; CornerRadius = 5; - Margin = new MarginPadding { Bottom = 5 }; - EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -86,7 +84,6 @@ namespace osu.Game.Overlays.Login public UserDropdownHeader() { Foreground.Padding = new MarginPadding { Left = 10, Right = 10 }; - Margin = new MarginPadding { Bottom = 5 }; Masking = true; CornerRadius = 5; EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index b16cc5bd4b..ecf2e7a634 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Overlays.Login; +using osu.Game.Overlays.Settings; namespace osu.Game.Overlays { @@ -63,7 +64,7 @@ namespace osu.Game.Overlays AutoSizeEasing = Easing.OutQuint, Child = panel = new LoginPanel { - Padding = new MarginPadding(10), + Padding = new MarginPadding { Vertical = SettingsSection.ITEM_SPACING }, RequestHide = Hide, }, } From ccc4d1609617e20fed35c212fd0782b7a6e43230 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 12:46:00 -0700 Subject: [PATCH 1395/1400] Remove most custom styling of user dropdown --- osu.Game/Overlays/Login/UserDropdown.cs | 51 +------------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index 9ffaaff8bf..f0449d50b5 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -31,27 +31,6 @@ namespace osu.Game.Overlays.Login protected partial class UserDropdownMenu : OsuDropdownMenu { - public UserDropdownMenu() - { - Masking = true; - CornerRadius = 5; - - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BackgroundColour = colours.Gray3; - SelectionColour = colours.Gray4; - HoverColour = colours.Gray5; - } - protected override DrawableDropdownMenuItem CreateDrawableDropdownMenuItem(MenuItem item) => new DrawableUserDropdownMenuItem(item); private partial class DrawableUserDropdownMenuItem : DrawableOsuDropdownMenuItem @@ -60,20 +39,12 @@ namespace osu.Game.Overlays.Login : base(item) { Foreground.Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 5 }; - CornerRadius = 5; } - - protected override Drawable CreateContent() => new Content - { - Label = { Margin = new MarginPadding { Left = UserDropdownHeader.LABEL_LEFT_MARGIN - 11 } } - }; } } private partial class UserDropdownHeader : OsuDropdownHeader { - public const float LABEL_LEFT_MARGIN = 20; - private readonly StatusIcon statusIcon; public Color4 StatusColour @@ -83,19 +54,6 @@ namespace osu.Game.Overlays.Login public UserDropdownHeader() { - Foreground.Padding = new MarginPadding { Left = 10, Right = 10 }; - Masking = true; - CornerRadius = 5; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - - Icon.Size = new Vector2(14); - Icon.Margin = new MarginPadding(0); - Foreground.Add(statusIcon = new StatusIcon { Anchor = Anchor.CentreLeft, @@ -103,14 +61,7 @@ namespace osu.Game.Overlays.Login Size = new Vector2(14), }); - Text.Margin = new MarginPadding { Left = LABEL_LEFT_MARGIN }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - BackgroundColour = colours.Gray3; - BackgroundColourHover = colours.Gray5; + Text.Margin = new MarginPadding { Left = 20 }; } } } From 5477ef6bfb7a253ed1bc93356c48de7ceb218bcb Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Sun, 25 Jun 2023 12:58:51 -0700 Subject: [PATCH 1396/1400] Remove unused usings --- osu.Game/Overlays/Login/UserDropdown.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Overlays/Login/UserDropdown.cs b/osu.Game/Overlays/Login/UserDropdown.cs index f0449d50b5..f2a12f9a1e 100644 --- a/osu.Game/Overlays/Login/UserDropdown.cs +++ b/osu.Game/Overlays/Login/UserDropdown.cs @@ -1,12 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Users.Drawables; using osuTK; From 8d2dccbda56eb768f0255a6746fccdd56de73eec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jun 2023 13:19:07 +0900 Subject: [PATCH 1397/1400] Remove pointless zero opacity specification --- osu.Game/Overlays/LoginOverlay.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index ecf2e7a634..de37aaa291 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -4,7 +4,6 @@ #nullable disable using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; @@ -32,7 +31,7 @@ namespace osu.Game.Overlays Masking = true; EdgeEffect = new EdgeEffectParameters { - Colour = Color4.Black.Opacity(0), + Colour = Color4.Black, Type = EdgeEffectType.Shadow, Radius = 10, Hollow = true, From ac0c988d4932f4e5efe826963188b0e17a705247 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jun 2023 13:21:29 +0900 Subject: [PATCH 1398/1400] Fix weirdly named test method and add xmldoc --- osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs | 2 +- osu.Game/Online/API/DummyAPIAccess.cs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs index 5c2edac84d..0bc71924ce 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoginOverlay.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Menus AddStep("logout", () => { API.Logout(); - ((DummyAPIAccess)API).StayConnectingNextLogin(); + ((DummyAPIAccess)API).PauseOnConnectingNextLogin(); }); AddStep("enter password", () => loginOverlay.ChildrenOfType().First().Text = "password"); diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index c2ef0b4e92..45a4737c21 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -144,8 +144,15 @@ namespace osu.Game.Online.API IBindableList IAPIProvider.Friends => Friends; IBindable IAPIProvider.Activity => Activity; + /// + /// During the next simulated login, the process will fail immediately. + /// public void FailNextLogin() => shouldFailNextLogin = true; - public void StayConnectingNextLogin() => stayConnectingNextLogin = true; + + /// + /// During the next simulated login, the process will pause indefinitely at "connecting". + /// + public void PauseOnConnectingNextLogin() => stayConnectingNextLogin = true; protected override void Dispose(bool isDisposing) { From 1abce098b4876946690ae69c69002127a0f0b070 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jun 2023 13:26:07 +0900 Subject: [PATCH 1399/1400] Apply nullability to login form related classes --- osu.Game/Online/API/DummyAPIAccess.cs | 10 ++++------ osu.Game/Overlays/Login/LoginPanel.cs | 15 +++++++-------- osu.Game/Overlays/LoginOverlay.cs | 4 +--- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 45a4737c21..01169828b0 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.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. -#nullable disable - using System; using System.Threading; using System.Threading.Tasks; @@ -45,13 +43,13 @@ namespace osu.Game.Online.API public int APIVersion => int.Parse(DateTime.Now.ToString("yyyyMMdd")); - public Exception LastLoginError { get; private set; } + public Exception? LastLoginError { get; private set; } /// /// Provide handling logic for an arbitrary API request. /// Should return true is a request was handled. If null or false return, the request will be failed with a . /// - public Func HandleRequest; + public Func? HandleRequest; private readonly Bindable state = new Bindable(APIState.Online); @@ -128,11 +126,11 @@ namespace osu.Game.Online.API LocalUser.Value = new GuestUser(); } - public IHubClientConnector GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; + public IHubClientConnector? GetHubConnector(string clientName, string endpoint, bool preferMessagePack) => null; public NotificationsClientConnector GetNotificationsConnector() => new PollingNotificationsClientConnector(this); - public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) + public RegistrationRequest.RegistrationRequestErrors? CreateAccount(string email, string username, string password) { Thread.Sleep(200); return null; diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index a84a211dfc..71ecf2e75a 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.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. -#nullable disable - using System; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -26,23 +24,24 @@ namespace osu.Game.Overlays.Login public partial class LoginPanel : Container { private bool bounding = true; - private LoginForm form; + + private LoginForm? form; [Resolved] - private OsuColour colours { get; set; } + private OsuColour colours { get; set; } = null!; - private UserGridPanel panel; - private UserDropdown dropdown; + private UserGridPanel panel = null!; + private UserDropdown dropdown = null!; /// /// Called to request a hide of a parent displaying this container. /// - public Action RequestHide; + public Action? RequestHide; private readonly IBindable apiState = new Bindable(); [Resolved] - private IAPIProvider api { get; set; } + private IAPIProvider api { get; set; } = null!; public override RectangleF BoundingBox => bounding ? base.BoundingBox : RectangleF.Empty; diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index de37aaa291..a575253e71 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.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. -#nullable disable - using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,7 +16,7 @@ namespace osu.Game.Overlays { public partial class LoginOverlay : OsuFocusedOverlayContainer { - private LoginPanel panel; + private LoginPanel panel = null!; private const float transition_time = 400; From b240ce295b76c91ee6c2c2839ab2173e16eea75c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 26 Jun 2023 13:38:34 +0900 Subject: [PATCH 1400/1400] Rename class and key to better match expectations --- ...untdownButtonStrings.cs => MultiplayerMatchStrings.cs} | 8 ++++---- .../Multiplayer/Match/MultiplayerCountdownButton.cs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Localisation/{MultiplayerCountdownButtonStrings.cs => MultiplayerMatchStrings.cs} (72%) diff --git a/osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs b/osu.Game/Localisation/MultiplayerMatchStrings.cs similarity index 72% rename from osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs rename to osu.Game/Localisation/MultiplayerMatchStrings.cs index 926b15386a..95c7168a09 100644 --- a/osu.Game/Localisation/MultiplayerCountdownButtonStrings.cs +++ b/osu.Game/Localisation/MultiplayerMatchStrings.cs @@ -5,9 +5,9 @@ using osu.Framework.Localisation; namespace osu.Game.Localisation { - public static class MultiplayerCountdownButtonStrings + public static class MultiplayerMatchStrings { - private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerCountdownButton"; + private const string prefix = @"osu.Game.Resources.Localisation.MultiplayerMatchStrings"; /// /// "Stop countdown" @@ -20,9 +20,9 @@ namespace osu.Game.Localisation public static LocalisableString CountdownSettings => new TranslatableString(getKey(@"countdown_settings"), @"Countdown settings"); /// - /// "Start match in {0} minute/seconds" + /// "Start match in {0}" /// - public static LocalisableString StartMatchInTime(string humanReadableTime) => new TranslatableString(getKey(@"start_match_in"), @"Start match in {0}", humanReadableTime); + public static LocalisableString StartMatchWithCountdown(string humanReadableTime) => new TranslatableString(getKey(@"start_match_width_countdown"), @"Start match in {0}", humanReadableTime); private static string getKey(string key) => $@"{prefix}:{key}"; } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs index 72c3a8122d..e1543eaceb 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerCountdownButton.cs @@ -57,7 +57,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match base.Action = this.ShowPopover; - TooltipText = MultiplayerCountdownButtonStrings.CountdownSettings; + TooltipText = MultiplayerMatchStrings.CountdownSettings; } [BackgroundDependencyLoader] @@ -113,7 +113,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, - Text = MultiplayerCountdownButtonStrings.StartMatchInTime(duration.Humanize()), + Text = MultiplayerMatchStrings.StartMatchWithCountdown(duration.Humanize()), BackgroundColour = colours.Green, Action = () => { @@ -128,7 +128,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match flow.Add(new RoundedButton { RelativeSizeAxes = Axes.X, - Text = MultiplayerCountdownButtonStrings.StopCountdown, + Text = MultiplayerMatchStrings.StopCountdown, BackgroundColour = colours.Red, Action = () => {