From 8f87957c7089fb731aa28063486b356ee031cb75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 14:44:45 +0900 Subject: [PATCH 1/5] Make all control point attributes bindable Properties are left intact for compatibility reasons. --- .../ControlPoints/DifficultyControlPoint.cs | 19 +++++++---- .../ControlPoints/EffectControlPoint.cs | 26 +++++++++++++-- .../ControlPoints/SampleControlPoint.cs | 27 ++++++++++++++-- .../ControlPoints/TimingControlPoint.cs | 32 ++++++++++++++----- ...egacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 42651fd0ca..7726eb0245 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,24 +1,31 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps.ControlPoints { public class DifficultyControlPoint : ControlPoint { + /// + /// The speed multiplier at this control point. + /// + public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) + { + MinValue = 0.1, + MaxValue = 10 + }; + /// /// The speed multiplier at this control point. /// public double SpeedMultiplier { - get => speedMultiplier; - set => speedMultiplier = MathHelper.Clamp(value, 0.1, 10); + get => SpeedMultiplierBindable.Value; + set => SpeedMultiplierBindable.Value = value; } - private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) => - other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(speedMultiplier); + other is DifficultyControlPoint otherTyped && otherTyped.SpeedMultiplier.Equals(SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 928f2a51ad..369b93ff3d 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,19 +1,39 @@ // 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.Beatmaps.ControlPoints { public class EffectControlPoint : ControlPoint { /// - /// Whether this control point enables Kiai mode. + /// Whether the first bar line of this control point is ignored. /// - public bool KiaiMode; + public readonly BindableBool OmitFirstBarLineBindable = new BindableBool(); /// /// Whether the first bar line of this control point is ignored. /// - public bool OmitFirstBarLine; + public bool OmitFirstBarLine + { + get => OmitFirstBarLineBindable.Value; + set => OmitFirstBarLineBindable.Value = value; + } + + /// + /// Whether this control point enables Kiai mode. + /// + public readonly BindableBool KiaiModeBindable = new BindableBool(); + + /// + /// Whether this control point enables Kiai mode. + /// + public bool KiaiMode + { + get => KiaiModeBindable.Value; + set => KiaiModeBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is EffectControlPoint otherTyped && diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 07f5aa6c90..37607c716e 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints @@ -12,12 +13,34 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The default sample bank at this control point. /// - public string SampleBank = DEFAULT_BANK; + public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK); + + /// + /// The speed multiplier at this control point. + /// + public string SampleBank + { + get => SampleBankBindable.Value; + set => SampleBankBindable.Value = value; + } + + /// + /// The default sample bank at this control point. + /// + public readonly BindableInt SampleVolumeBindable = new BindableInt(100) + { + MinValue = 0, + MaxValue = 100 + }; /// /// The default sample volume at this control point. /// - public int SampleVolume = 100; + public int SampleVolume + { + get => SampleVolumeBindable.Value; + set => SampleVolumeBindable.Value = value; + } /// /// Create a SampleInfo based on the sample settings in this control point. diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index f8c84c79dd..d25d08c5bd 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.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 osuTK; +using osu.Framework.Bindables; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints @@ -11,23 +11,39 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time signature at this control point. /// - public TimeSignatures TimeSignature = TimeSignatures.SimpleQuadruple; + public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple); + + /// + /// The time signature at this control point. + /// + public TimeSignatures TimeSignature + { + get => TimeSignatureBindable.Value; + set => TimeSignatureBindable.Value = value; + } public const double DEFAULT_BEAT_LENGTH = 1000; /// /// The beat length at this control point. /// - public virtual double BeatLength + public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { - get => beatLength; - set => beatLength = MathHelper.Clamp(value, 6, 60000); - } + MinValue = 6, + MaxValue = 60000 + }; - private double beatLength = DEFAULT_BEAT_LENGTH; + /// + /// The beat length at this control point. + /// + public double BeatLength + { + get => BeatLengthBindable.Value; + set => BeatLengthBindable.Value = value; + } public override bool EquivalentTo(ControlPoint other) => other is TimingControlPoint otherTyped - && TimeSignature == otherTyped.TimeSignature && beatLength.Equals(otherTyped.beatLength); + && TimeSignature == otherTyped.TimeSignature && BeatLength.Equals(otherTyped.BeatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 238187bf8f..a16d391b99 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -32,7 +32,11 @@ namespace osu.Game.Beatmaps.Formats private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint { - public override double BeatLength { get; set; } = DEFAULT_BEAT_LENGTH; + public LegacyDifficultyCalculatorControlPoint() + { + BeatLengthBindable.MinValue = double.MinValue; + BeatLengthBindable.MaxValue = double.MaxValue; + } } } } From 090881cf6f742637e7b2546fab04853bd3df048b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 16:21:14 +0900 Subject: [PATCH 2/5] Add default bindable values --- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 ++ osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 5 +++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 7726eb0245..8b21098a51 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -12,6 +12,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly BindableDouble SpeedMultiplierBindable = new BindableDouble(1) { + Precision = 0.1, + Default = 1, MinValue = 0.1, MaxValue = 10 }; diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 37607c716e..42865c686c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The default sample bank at this control point. /// - public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK); + public readonly Bindable SampleBankBindable = new Bindable(DEFAULT_BANK) { Default = DEFAULT_BANK }; /// /// The speed multiplier at this control point. @@ -30,7 +30,8 @@ namespace osu.Game.Beatmaps.ControlPoints public readonly BindableInt SampleVolumeBindable = new BindableInt(100) { MinValue = 0, - MaxValue = 100 + MaxValue = 100, + Default = 100 }; /// diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index d25d08c5bd..c00b04b660 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time signature at this control point. /// - public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple); + public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple }; /// /// The time signature at this control point. @@ -29,6 +29,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly BindableDouble BeatLengthBindable = new BindableDouble(DEFAULT_BEAT_LENGTH) { + Default = DEFAULT_BEAT_LENGTH, MinValue = 6, MaxValue = 60000 }; From 1a4817879e57800bf1ab7f829c5ca2c7d5b28623 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Oct 2019 19:10:39 +0900 Subject: [PATCH 3/5] Fix precision changes in legacy control point types --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 8 ++++++++ .../Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 786b7611b5..c5b9ddc23b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -376,7 +376,7 @@ namespace osu.Game.Beatmaps.Formats handleTimingControlPoint(controlPoint); } - handleDifficultyControlPoint(new DifficultyControlPoint + handleDifficultyControlPoint(new LegacyDifficultyControlPoint { Time = time, SpeedMultiplier = speedMultiplier, diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index a5a4380d4a..49457833f2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,6 +189,14 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } + internal class LegacyDifficultyControlPoint : DifficultyControlPoint + { + public LegacyDifficultyControlPoint() + { + SpeedMultiplierBindable.Precision = Double.Epsilon; + } + } + internal class LegacySampleControlPoint : SampleControlPoint { public int CustomSampleBank; diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index a16d391b99..527f520172 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -28,11 +28,11 @@ namespace osu.Game.Beatmaps.Formats } protected override TimingControlPoint CreateTimingControlPoint() - => new LegacyDifficultyCalculatorControlPoint(); + => new LegacyDifficultyCalculatorTimingControlPoint(); - private class LegacyDifficultyCalculatorControlPoint : TimingControlPoint + private class LegacyDifficultyCalculatorTimingControlPoint : TimingControlPoint { - public LegacyDifficultyCalculatorControlPoint() + public LegacyDifficultyCalculatorTimingControlPoint() { BeatLengthBindable.MinValue = double.MinValue; BeatLengthBindable.MaxValue = double.MaxValue; From 7c6ccce3ba1b271309185d5587a76924f95d82b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Oct 2019 18:02:30 +0900 Subject: [PATCH 4/5] Add tests covering precision case --- .../Formats/LegacyBeatmapDecoderTest.cs | 17 +++++++++++++++++ .../controlpoint-difficulty-multiplier.osu | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index de516d3142..8545072199 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -362,6 +362,23 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeControlPointDifficultyChange() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("controlpoint-difficulty-multiplier.osu")) + using (var stream = new LineBufferedReader(resStream)) + { + var controlPointInfo = decoder.Decode(stream).ControlPointInfo; + + Assert.That(controlPointInfo.DifficultyPointAt(5).SpeedMultiplier, Is.EqualTo(1)); + Assert.That(controlPointInfo.DifficultyPointAt(1000).SpeedMultiplier, Is.EqualTo(10)); + Assert.That(controlPointInfo.DifficultyPointAt(2000).SpeedMultiplier, Is.EqualTo(1.8518518518518519d)); + Assert.That(controlPointInfo.DifficultyPointAt(3000).SpeedMultiplier, Is.EqualTo(0.5)); + } + } + [Test] public void TestDecodeControlPointCustomSampleBank() { diff --git a/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu b/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu new file mode 100644 index 0000000000..5f06fc33c8 --- /dev/null +++ b/osu.Game.Tests/Resources/controlpoint-difficulty-multiplier.osu @@ -0,0 +1,8 @@ +osu file format v7 + +[TimingPoints] +0,100,4,2,0,100,1,0 +12,500,4,2,0,100,1,0 +1000,-10,4,2,0,100,0,0 +2000,-54,4,2,0,100,0,0 +3000,-200,4,2,0,100,0,0 From ced6042b3e977dcfcd18ca1e77872e061e0a8811 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 30 Oct 2019 15:51:09 +0900 Subject: [PATCH 5/5] Use internal type name --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 49457833f2..2b914669cb 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -193,7 +193,7 @@ namespace osu.Game.Beatmaps.Formats { public LegacyDifficultyControlPoint() { - SpeedMultiplierBindable.Precision = Double.Epsilon; + SpeedMultiplierBindable.Precision = double.Epsilon; } }