From 2882981f9c2494a84ddf8f055f860434437d0608 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 18:08:46 +0900 Subject: [PATCH 01/11] Implement and use equality comparers for ControlPoint --- .../Beatmaps/ControlPoints/ControlPoint.cs | 8 +- .../ControlPoints/DifficultyControlPoint.cs | 5 ++ .../ControlPoints/EffectControlPoint.cs | 6 ++ .../ControlPoints/SampleControlPoint.cs | 6 ++ .../ControlPoints/TimingControlPoint.cs | 6 ++ .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 81 ++++++++++++------- 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index db9e712d86..e1e5affc78 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -14,6 +14,12 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - public bool Equals(ControlPoint other) => Time.Equals(other?.Time); + public virtual bool Equals(ControlPoint other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + + return Time.Equals(other.Time); + } } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 9f717d21e3..9c6735a36a 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -17,5 +17,10 @@ namespace osu.Game.Beatmaps.ControlPoints } private double speedMultiplier = 1; + + public override bool Equals(ControlPoint other) + => base.Equals(other) + && other is DifficultyControlPoint difficulty + && SpeedMultiplier == difficulty.SpeedMultiplier; } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 73d5232f44..6fdddc44bb 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -14,5 +14,11 @@ namespace osu.Game.Beatmaps.ControlPoints /// Whether the first bar line of this control point is ignored. /// public bool OmitFirstBarLine; + + public override bool Equals(ControlPoint other) + => base.Equals(other) + && other is EffectControlPoint effect + && KiaiMode == effect.KiaiMode + && OmitFirstBarLine == effect.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 5d801a1163..69c00e463c 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -30,5 +30,11 @@ namespace osu.Game.Beatmaps.ControlPoints Name = sampleName, Volume = SampleVolume, }; + + public override bool Equals(ControlPoint other) + => base.Equals(other) + && other is SampleControlPoint sample + && SampleBank == sample.SampleBank + && SampleVolume == sample.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index d20b1b87a6..cc1546675b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -23,5 +23,11 @@ namespace osu.Game.Beatmaps.ControlPoints } private double beatLength = 1000; + + public override bool Equals(ControlPoint other) + => base.Equals(other) + && other is TimingControlPoint timing + && TimeSignature == timing.TimeSignature + && BeatLength == timing.beatLength; } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 581207607a..603de5949e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -314,13 +314,9 @@ namespace osu.Game.Beatmaps.Formats if (stringSampleSet == @"none") stringSampleSet = @"normal"; - DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(time); - SampleControlPoint samplePoint = beatmap.ControlPointInfo.SamplePointAt(time); - EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(time); - if (timingChange) { - beatmap.ControlPointInfo.TimingPoints.Add(new TimingControlPoint + handleTimingControlPoint(new TimingControlPoint { Time = time, BeatLength = beatLength, @@ -328,41 +324,68 @@ namespace osu.Game.Beatmaps.Formats }); } - if (speedMultiplier != difficultyPoint.SpeedMultiplier) + handleDifficultyControlPoint(new DifficultyControlPoint { - beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time); - beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint - { - Time = time, - SpeedMultiplier = speedMultiplier - }); - } + Time = time, + SpeedMultiplier = speedMultiplier + }); - if (stringSampleSet != samplePoint.SampleBank || sampleVolume != samplePoint.SampleVolume) + handleEffectControlPoint(new EffectControlPoint { - beatmap.ControlPointInfo.SamplePoints.Add(new SampleControlPoint - { - Time = time, - SampleBank = stringSampleSet, - SampleVolume = sampleVolume - }); - } + Time = time, + KiaiMode = kiaiMode, + OmitFirstBarLine = omitFirstBarSignature + }); - if (kiaiMode != effectPoint.KiaiMode || omitFirstBarSignature != effectPoint.OmitFirstBarLine) + handleSampleControlPoint(new LegacySampleControlPoint { - beatmap.ControlPointInfo.EffectPoints.Add(new EffectControlPoint - { - Time = time, - KiaiMode = kiaiMode, - OmitFirstBarLine = omitFirstBarSignature - }); - } + Time = time, + SampleBank = stringSampleSet, + SampleVolume = sampleVolume, + CustomSampleBank = customSampleBank + }); } catch (FormatException e) { } } + private void handleTimingControlPoint(TimingControlPoint newPoint) + { + beatmap.ControlPointInfo.TimingPoints.Add(newPoint); + } + + private void handleDifficultyControlPoint(DifficultyControlPoint newPoint) + { + var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); + + if (newPoint.Equals(existing)) + return; + + beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == newPoint.Time); + beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); + } + + private void handleEffectControlPoint(EffectControlPoint newPoint) + { + var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); + + if (newPoint.Equals(existing)) + return; + + beatmap.ControlPointInfo.EffectPoints.Add(newPoint); + } + + private void handleSampleControlPoint(SampleControlPoint newPoint) + { + var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); + + if (newPoint.Equals(existing)) + return; + + beatmap.ControlPointInfo.SamplePoints.Add(newPoint); + } + private void handleHitObject(string line) { // If the ruleset wasn't specified, assume the osu!standard ruleset. From 781095b96bd781bc930ed65a571cadc42467fc64 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 18:20:29 +0900 Subject: [PATCH 02/11] Encapsulate the method to apply SampleControlPoints to SampleInfos --- .../Beatmaps/ControlPoints/SampleControlPoint.cs | 12 ++++++++++++ .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 13 ++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 69c00e463c..ae65e7ea42 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -31,6 +31,18 @@ namespace osu.Game.Beatmaps.ControlPoints Volume = SampleVolume, }; + /// + /// Applies and to a if necessary, returning the modified . + /// + /// The . This will not be modified. + /// The modified . This does not share a reference with . + public virtual SampleInfo ApplyTo(SampleInfo sampleInfo) => new SampleInfo + { + Bank = sampleInfo.Bank ?? SampleBank, + Name = sampleInfo.Name, + Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume + }; + public override bool Equals(ControlPoint other) => base.Equals(other) && other is SampleControlPoint sample diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 88990d435c..4892e20814 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -90,13 +90,12 @@ namespace osu.Game.Rulesets.Objects.Drawables if (HitObject.SampleControlPoint == null) throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{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}."); - AddInternal(Samples = new SkinnableSound(samples.Select(s => new SampleInfo - { - Bank = s.Bank ?? HitObject.SampleControlPoint.SampleBank, - Name = s.Name, - Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume, - Namespace = SampleNamespace - }).ToArray())); + + samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); + foreach (var s in samples) + s.Namespace = SampleNamespace; + + AddInternal(Samples = new SkinnableSound(samples)); } } From 3a9a82c80c5c2d6a2843fa5cb64432d2d0ce455b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 18:20:43 +0900 Subject: [PATCH 03/11] Add back legacy custom sample banks --- .../Formats/LegacyBeatmapDecoderTest.cs | 17 ++++++++++++++ osu.Game.Tests/Resources/custom-samples.osu | 16 ++++++++++++++ .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 ++--- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 22 +++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Tests/Resources/custom-samples.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 1628423fe8..a77730c453 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -8,6 +8,7 @@ using OpenTK.Graphics; using osu.Game.Tests.Resources; using System.Linq; using osu.Game.Audio; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; @@ -211,5 +212,21 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsTrue(hitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); } } + + [Test] + public void TestDecodeCustomSamples() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + using (var resStream = Resource.OpenResource("custom-samples.osu")) + using (var stream = new StreamReader(resStream)) + { + var hitObjects = decoder.Decode(stream).HitObjects; + + Assert.AreEqual(0, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[0].SampleControlPoint).CustomSampleBank); + Assert.AreEqual(1, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[1].SampleControlPoint).CustomSampleBank); + Assert.AreEqual(2, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[2].SampleControlPoint).CustomSampleBank); + Assert.AreEqual(0, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[3].SampleControlPoint).CustomSampleBank); + } + } } } diff --git a/osu.Game.Tests/Resources/custom-samples.osu b/osu.Game.Tests/Resources/custom-samples.osu new file mode 100644 index 0000000000..1e0e6f558e --- /dev/null +++ b/osu.Game.Tests/Resources/custom-samples.osu @@ -0,0 +1,16 @@ +osu file format v14 + +[General] +SampleSet: Normal + +[TimingPoints] +2170,468.75,4,1,0,40,1,0 +2638,-100,4,1,1,40,0,0 +3107,-100,4,1,2,40,0,0 +3576,-100,4,1,0,40,0,0 + +[HitObjects] +255,193,2170,1,0,0:0:0:0: +256,191,2638,5,0,0:0:0:0: +255,193,3107,1,0,0:0:0:0: +256,191,3576,1,0,0:0:0:0: diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 603de5949e..f33e963f08 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -289,9 +289,9 @@ namespace osu.Game.Beatmaps.Formats if (split.Length >= 4) sampleSet = (LegacySampleBank)int.Parse(split[3]); - //SampleBank sampleBank = SampleBank.Default; - //if (split.Length >= 5) - // sampleBank = (SampleBank)int.Parse(split[4]); + int customSampleBank = 0; + if (split.Length >= 5) + customSampleBank = int.Parse(split[4]); int sampleVolume = defaultSampleVolume; if (split.Length >= 6) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index e77efd8508..c207761866 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; using System.IO; using osu.Framework.Logging; +using osu.Game.Audio; +using osu.Game.Beatmaps.ControlPoints; using OpenTK.Graphics; namespace osu.Game.Beatmaps.Formats @@ -167,5 +169,25 @@ namespace osu.Game.Beatmaps.Formats Pass = 2, Foreground = 3 } + + internal class LegacySampleControlPoint : SampleControlPoint + { + public int CustomSampleBank; + + public override SampleInfo ApplyTo(SampleInfo sampleInfo) + { + var baseInfo = base.ApplyTo(sampleInfo); + + if (CustomSampleBank > 0) + baseInfo.Name += CustomSampleBank; + + return baseInfo; + } + + public override bool Equals(ControlPoint other) + => base.Equals(other) + && other is LegacySampleControlPoint legacy + && CustomSampleBank == legacy.CustomSampleBank; + } } } From 94f1b2eeb867d2ff457b66a6a4b26f1ca8a8ff72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 18:27:33 +0900 Subject: [PATCH 04/11] Only custom sample banks > 1 modify the filename --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 11 +++++++---- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index a77730c453..4be6eeef0d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -12,6 +12,7 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Objects; using osu.Game.Skinning; namespace osu.Game.Tests.Beatmaps.Formats @@ -222,11 +223,13 @@ namespace osu.Game.Tests.Beatmaps.Formats { var hitObjects = decoder.Decode(stream).HitObjects; - Assert.AreEqual(0, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[0].SampleControlPoint).CustomSampleBank); - Assert.AreEqual(1, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[1].SampleControlPoint).CustomSampleBank); - Assert.AreEqual(2, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[2].SampleControlPoint).CustomSampleBank); - Assert.AreEqual(0, ((LegacyDecoder.LegacySampleControlPoint)hitObjects[3].SampleControlPoint).CustomSampleBank); + Assert.AreEqual("hitnormal", getTestableSampleInfo(hitObjects[0]).Name); + Assert.AreEqual("hitnormal", getTestableSampleInfo(hitObjects[1]).Name); + Assert.AreEqual("hitnormal2", getTestableSampleInfo(hitObjects[2]).Name); + Assert.AreEqual("hitnormal", getTestableSampleInfo(hitObjects[3]).Name); } + + SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(new SampleInfo { Name = "hitnormal" }); } } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index c207761866..60fff4bd7f 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -178,7 +178,7 @@ namespace osu.Game.Beatmaps.Formats { var baseInfo = base.ApplyTo(sampleInfo); - if (CustomSampleBank > 0) + if (CustomSampleBank > 1) baseInfo.Name += CustomSampleBank; return baseInfo; From 9fd9af22f0f2a2370177fe93568340a0d7e1fd49 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 28 Jun 2018 18:40:12 +0900 Subject: [PATCH 05/11] Remove unused using --- 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 4be6eeef0d..d3c61960bb 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -8,7 +8,6 @@ using OpenTK.Graphics; using osu.Game.Tests.Resources; using System.Linq; using osu.Game.Audio; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; From aea50e770b6a58f4e196cbf33bb2db1701248862 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Jul 2018 13:23:59 +0900 Subject: [PATCH 06/11] Use .Equals everywhere --- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 +- osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 9c6735a36a..296dcf66b1 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -21,6 +21,6 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool Equals(ControlPoint other) => base.Equals(other) && other is DifficultyControlPoint difficulty - && SpeedMultiplier == difficulty.SpeedMultiplier; + && SpeedMultiplier.Equals(difficulty.SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 6fdddc44bb..e41fb3a1d3 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -18,7 +18,7 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool Equals(ControlPoint other) => base.Equals(other) && other is EffectControlPoint effect - && KiaiMode == effect.KiaiMode - && OmitFirstBarLine == effect.OmitFirstBarLine; + && KiaiMode.Equals(effect.KiaiMode) + && OmitFirstBarLine.Equals(effect.OmitFirstBarLine); } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index ae65e7ea42..c4d6ad24a0 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -46,7 +46,7 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool Equals(ControlPoint other) => base.Equals(other) && other is SampleControlPoint sample - && SampleBank == sample.SampleBank - && SampleVolume == sample.SampleVolume; + && SampleBank.Equals(sample.SampleBank) + && SampleVolume.Equals(sample.SampleVolume); } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index cc1546675b..3e4e2a0bb1 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -27,7 +27,7 @@ namespace osu.Game.Beatmaps.ControlPoints public override bool Equals(ControlPoint other) => base.Equals(other) && other is TimingControlPoint timing - && TimeSignature == timing.TimeSignature - && BeatLength == timing.beatLength; + && TimeSignature.Equals(timing.TimeSignature) + && BeatLength.Equals(timing.BeatLength); } } From c78bfbfa55f9d49f0a20d1184820ede77259c964 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Jul 2018 13:24:09 +0900 Subject: [PATCH 07/11] Fix failing json conversion testcases --- osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index b834be71f1..64bd563897 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -118,7 +118,11 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestParity(string beatmap) { var legacy = decode(beatmap, out Beatmap json); - json.WithDeepEqual(legacy).IgnoreProperty(r => r.DeclaringType == typeof(HitWindows)).Assert(); + json.WithDeepEqual(legacy) + .IgnoreProperty(r => r.DeclaringType == typeof(HitWindows) + // Todo: CustomSampleBank shouldn't exist going forward, we need a conversion mechanism + || r.Name == nameof(LegacyDecoder.LegacySampleControlPoint.CustomSampleBank)) + .Assert(); } /// From b664d3ef8176662bfe44855394fcba78a268955b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Jul 2018 13:33:59 +0900 Subject: [PATCH 08/11] Fix time being a part of controlpoint change comparisons --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 15 +++++++++------ .../ControlPoints/DifficultyControlPoint.cs | 4 ++-- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 4 ++-- .../Beatmaps/ControlPoints/SampleControlPoint.cs | 4 ++-- .../Beatmaps/ControlPoints/TimingControlPoint.cs | 4 ++-- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +++--- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ++-- 7 files changed, 22 insertions(+), 19 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index e1e5affc78..cf6d9a3ccd 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -14,12 +14,15 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - public virtual bool Equals(ControlPoint other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; + /// + /// Whether this provides the same changes to gameplay as another . + /// + /// The to compare to. + /// Whether this provides the same changes to gameplay as . + public virtual bool ChangeEquals(ControlPoint other) => !ReferenceEquals(null, other); - return Time.Equals(other.Time); - } + public bool Equals(ControlPoint other) + => ChangeEquals(other) + && Time.Equals(other.Time); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 296dcf66b1..f821ff11f4 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -18,8 +18,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public override bool Equals(ControlPoint other) - => base.Equals(other) + public override bool ChangeEquals(ControlPoint other) + => base.ChangeEquals(other) && other is DifficultyControlPoint difficulty && SpeedMultiplier.Equals(difficulty.SpeedMultiplier); } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index e41fb3a1d3..0cbdf7fdf2 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -15,8 +15,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; - public override bool Equals(ControlPoint other) - => base.Equals(other) + public override bool ChangeEquals(ControlPoint other) + => base.ChangeEquals(other) && other is EffectControlPoint effect && KiaiMode.Equals(effect.KiaiMode) && OmitFirstBarLine.Equals(effect.OmitFirstBarLine); diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index c4d6ad24a0..11de392d14 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -43,8 +43,8 @@ namespace osu.Game.Beatmaps.ControlPoints Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume }; - public override bool Equals(ControlPoint other) - => base.Equals(other) + public override bool ChangeEquals(ControlPoint other) + => base.ChangeEquals(other) && other is SampleControlPoint sample && SampleBank.Equals(sample.SampleBank) && SampleVolume.Equals(sample.SampleVolume); diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 3e4e2a0bb1..8fe3257786 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -24,8 +24,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = 1000; - public override bool Equals(ControlPoint other) - => base.Equals(other) + public override bool ChangeEquals(ControlPoint other) + => base.ChangeEquals(other) && other is TimingControlPoint timing && TimeSignature.Equals(timing.TimeSignature) && BeatLength.Equals(timing.BeatLength); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index f33e963f08..fe55d19908 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -359,7 +359,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - if (newPoint.Equals(existing)) + if (newPoint.ChangeEquals(existing)) return; beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == newPoint.Time); @@ -370,7 +370,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - if (newPoint.Equals(existing)) + if (newPoint.ChangeEquals(existing)) return; beatmap.ControlPointInfo.EffectPoints.Add(newPoint); @@ -380,7 +380,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - if (newPoint.Equals(existing)) + if (newPoint.ChangeEquals(existing)) return; beatmap.ControlPointInfo.SamplePoints.Add(newPoint); diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 60fff4bd7f..f5e3a34462 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -184,8 +184,8 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public override bool Equals(ControlPoint other) - => base.Equals(other) + public override bool ChangeEquals(ControlPoint other) + => base.ChangeEquals(other) && other is LegacySampleControlPoint legacy && CustomSampleBank == legacy.CustomSampleBank; } From 37495c34faa7a02852934d2d9db0dab9e2492a66 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 2 Jul 2018 13:51:47 +0900 Subject: [PATCH 09/11] Fix possible nullreference --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index cf6d9a3ccd..90c0ded38f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -23,6 +23,7 @@ namespace osu.Game.Beatmaps.ControlPoints public bool Equals(ControlPoint other) => ChangeEquals(other) + && !ReferenceEquals(null, other) && Time.Equals(other.Time); } } From 8b0c6a4c855509aa3de33ddd97e33b70525ab5d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 2 Jul 2018 14:17:19 +0900 Subject: [PATCH 10/11] Make SampleControlPoint clone the existing SampleInfo --- osu.Game/Audio/SampleInfo.cs | 2 ++ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index f635b74030..53b6e439f5 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -32,5 +32,7 @@ namespace osu.Game.Audio /// The sample volume. /// public int Volume; + + public SampleInfo Clone() => (SampleInfo)MemberwiseClone(); } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 11de392d14..77d42551c6 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -36,12 +36,14 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The . This will not be modified. /// The modified . This does not share a reference with . - public virtual SampleInfo ApplyTo(SampleInfo sampleInfo) => new SampleInfo + public virtual SampleInfo ApplyTo(SampleInfo sampleInfo) { - Bank = sampleInfo.Bank ?? SampleBank, - Name = sampleInfo.Name, - Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume - }; + var newSampleInfo = sampleInfo.Clone(); + newSampleInfo.Bank = sampleInfo.Bank ?? SampleBank; + newSampleInfo.Name = sampleInfo.Name; + newSampleInfo.Volume = sampleInfo.Volume > 0 ? sampleInfo.Volume : SampleVolume; + return newSampleInfo; + } public override bool ChangeEquals(ControlPoint other) => base.ChangeEquals(other) From 44aecdc3a0ebd60873058cbb25922c6bc69ef1c3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Jul 2018 15:00:02 +0900 Subject: [PATCH 11/11] Rename method to EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 11 +++++------ .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 4 ++-- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 6 +++--- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ++-- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 90c0ded38f..9ed476d97c 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -15,15 +15,14 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// - /// Whether this provides the same changes to gameplay as another . + /// Whether this provides the same parametric changes as another . + /// Basically an equality check without considering the . /// /// The to compare to. - /// Whether this provides the same changes to gameplay as . - public virtual bool ChangeEquals(ControlPoint other) => !ReferenceEquals(null, other); + /// Whether this is equivalent to . + public virtual bool EquivalentTo(ControlPoint other) => true; public bool Equals(ControlPoint other) - => ChangeEquals(other) - && !ReferenceEquals(null, other) - && Time.Equals(other.Time); + => EquivalentTo(other) && Time.Equals(other?.Time); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index f821ff11f4..526bddf51a 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -18,8 +18,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public override bool ChangeEquals(ControlPoint other) - => base.ChangeEquals(other) + public override bool EquivalentTo(ControlPoint other) + => base.EquivalentTo(other) && other is DifficultyControlPoint difficulty && SpeedMultiplier.Equals(difficulty.SpeedMultiplier); } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 0cbdf7fdf2..dd9d568133 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -15,8 +15,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; - public override bool ChangeEquals(ControlPoint other) - => base.ChangeEquals(other) + public override bool EquivalentTo(ControlPoint other) + => base.EquivalentTo(other) && other is EffectControlPoint effect && KiaiMode.Equals(effect.KiaiMode) && OmitFirstBarLine.Equals(effect.OmitFirstBarLine); diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 77d42551c6..acccbcde46 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -45,8 +45,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public override bool ChangeEquals(ControlPoint other) - => base.ChangeEquals(other) + public override bool EquivalentTo(ControlPoint other) + => base.EquivalentTo(other) && other is SampleControlPoint sample && SampleBank.Equals(sample.SampleBank) && SampleVolume.Equals(sample.SampleVolume); diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 8fe3257786..eb60133fed 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -24,8 +24,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = 1000; - public override bool ChangeEquals(ControlPoint other) - => base.ChangeEquals(other) + public override bool EquivalentTo(ControlPoint other) + => base.EquivalentTo(other) && other is TimingControlPoint timing && TimeSignature.Equals(timing.TimeSignature) && BeatLength.Equals(timing.BeatLength); diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index fe55d19908..c79938e613 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -359,7 +359,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - if (newPoint.ChangeEquals(existing)) + if (newPoint.EquivalentTo(existing)) return; beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == newPoint.Time); @@ -370,7 +370,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - if (newPoint.ChangeEquals(existing)) + if (newPoint.EquivalentTo(existing)) return; beatmap.ControlPointInfo.EffectPoints.Add(newPoint); @@ -380,7 +380,7 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - if (newPoint.ChangeEquals(existing)) + if (newPoint.EquivalentTo(existing)) return; beatmap.ControlPointInfo.SamplePoints.Add(newPoint); diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index f5e3a34462..22a6acf459 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -184,8 +184,8 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public override bool ChangeEquals(ControlPoint other) - => base.ChangeEquals(other) + public override bool EquivalentTo(ControlPoint other) + => base.EquivalentTo(other) && other is LegacySampleControlPoint legacy && CustomSampleBank == legacy.CustomSampleBank; }