Clone and copy ControlPointInfo when retrieving a playable beatmap

This commit is contained in:
Dean Herbert
2021-01-04 16:37:07 +09:00
parent cd7a5ca23a
commit ba4e411422
11 changed files with 86 additions and 6 deletions

View File

@ -28,5 +28,22 @@ namespace osu.Game.Beatmaps.ControlPoints
/// <param name="existing">An existing control point to compare with.</param> /// <param name="existing">An existing control point to compare with.</param>
/// <returns>Whether this <see cref="ControlPoint"/> is redundant when placed alongside <paramref name="existing"/>.</returns> /// <returns>Whether this <see cref="ControlPoint"/> is redundant when placed alongside <paramref name="existing"/>.</returns>
public abstract bool IsRedundant(ControlPoint existing); public abstract bool IsRedundant(ControlPoint existing);
/// <summary>
/// Create a copy of this room without online information.
/// Should be used to create a local copy of a room for submitting in the future.
/// </summary>
public ControlPoint CreateCopy()
{
var copy = (ControlPoint)Activator.CreateInstance(GetType());
copy.CopyFrom(this);
return copy;
}
public virtual void CopyFrom(ControlPoint other)
{
}
} }
} }

View File

@ -11,7 +11,7 @@ using osu.Framework.Lists;
namespace osu.Game.Beatmaps.ControlPoints namespace osu.Game.Beatmaps.ControlPoints
{ {
[Serializable] [Serializable]
public class ControlPointInfo public class ControlPointInfo : ICloneable
{ {
/// <summary> /// <summary>
/// All control points grouped by time. /// All control points grouped by time.
@ -297,5 +297,15 @@ namespace osu.Game.Beatmaps.ControlPoints
break; break;
} }
} }
public object Clone()
{
var controlPointInfo = new ControlPointInfo();
foreach (var point in AllControlPoints)
controlPointInfo.Add(point.Time, point.CreateCopy());
return controlPointInfo;
}
} }
} }

View File

@ -39,5 +39,12 @@ namespace osu.Game.Beatmaps.ControlPoints
public override bool IsRedundant(ControlPoint existing) public override bool IsRedundant(ControlPoint existing)
=> existing is DifficultyControlPoint existingDifficulty => existing is DifficultyControlPoint existingDifficulty
&& SpeedMultiplier == existingDifficulty.SpeedMultiplier; && SpeedMultiplier == existingDifficulty.SpeedMultiplier;
public override void CopyFrom(ControlPoint other)
{
SpeedMultiplier = ((DifficultyControlPoint)other).SpeedMultiplier;
base.CopyFrom(other);
}
} }
} }

View File

@ -50,5 +50,13 @@ namespace osu.Game.Beatmaps.ControlPoints
&& existing is EffectControlPoint existingEffect && existing is EffectControlPoint existingEffect
&& KiaiMode == existingEffect.KiaiMode && KiaiMode == existingEffect.KiaiMode
&& OmitFirstBarLine == existingEffect.OmitFirstBarLine; && OmitFirstBarLine == existingEffect.OmitFirstBarLine;
public override void CopyFrom(ControlPoint other)
{
KiaiMode = ((EffectControlPoint)other).KiaiMode;
OmitFirstBarLine = ((EffectControlPoint)other).OmitFirstBarLine;
base.CopyFrom(other);
}
} }
} }

View File

@ -72,5 +72,13 @@ namespace osu.Game.Beatmaps.ControlPoints
=> existing is SampleControlPoint existingSample => existing is SampleControlPoint existingSample
&& SampleBank == existingSample.SampleBank && SampleBank == existingSample.SampleBank
&& SampleVolume == existingSample.SampleVolume; && SampleVolume == existingSample.SampleVolume;
public override void CopyFrom(ControlPoint other)
{
SampleVolume = ((SampleControlPoint)other).SampleVolume;
SampleBank = ((SampleControlPoint)other).SampleBank;
base.CopyFrom(other);
}
} }
} }

View File

@ -69,5 +69,13 @@ namespace osu.Game.Beatmaps.ControlPoints
// Timing points are never redundant as they can change the time signature. // Timing points are never redundant as they can change the time signature.
public override bool IsRedundant(ControlPoint existing) => false; public override bool IsRedundant(ControlPoint existing) => false;
public override void CopyFrom(ControlPoint other)
{
TimeSignature = ((TimingControlPoint)other).TimeSignature;
BeatLength = ((TimingControlPoint)other).BeatLength;
base.CopyFrom(other);
}
} }
} }

View File

@ -164,13 +164,24 @@ namespace osu.Game.Beatmaps.Formats
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
/// DO NOT USE THIS UNLESS 100% SURE. /// DO NOT USE THIS UNLESS 100% SURE.
/// </summary> /// </summary>
public readonly float BpmMultiplier; public float BpmMultiplier { get; set; }
public LegacyDifficultyControlPoint(double beatLength) public LegacyDifficultyControlPoint(double beatLength)
: this()
{
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100f : 1;
}
public LegacyDifficultyControlPoint()
{ {
SpeedMultiplierBindable.Precision = double.Epsilon; SpeedMultiplierBindable.Precision = double.Epsilon;
}
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100f : 1; public override void CopyFrom(ControlPoint other)
{
base.CopyFrom(other);
BpmMultiplier = ((LegacyDifficultyControlPoint)other).BpmMultiplier;
} }
} }

View File

@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps
/// <summary> /// <summary>
/// The control points in this beatmap. /// The control points in this beatmap.
/// </summary> /// </summary>
ControlPointInfo ControlPointInfo { get; } ControlPointInfo ControlPointInfo { get; set; }
/// <summary> /// <summary>
/// The breaks in this beatmap. /// The breaks in this beatmap.

View File

@ -14,6 +14,7 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Statistics; using osu.Framework.Statistics;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -111,6 +112,8 @@ namespace osu.Game.Beatmaps
// Convert // Convert
IBeatmap converted = converter.Convert(cancellationSource.Token); IBeatmap converted = converter.Convert(cancellationSource.Token);
converted.ControlPointInfo = (ControlPointInfo)converted.ControlPointInfo.Clone();
// Apply conversion mods to the result // Apply conversion mods to the result
foreach (var mod in mods.OfType<IApplicableAfterBeatmapConversion>()) foreach (var mod in mods.OfType<IApplicableAfterBeatmapConversion>())
{ {

View File

@ -74,7 +74,11 @@ namespace osu.Game.Screens.Edit
public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; public BeatmapMetadata Metadata => PlayableBeatmap.Metadata;
public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; public ControlPointInfo ControlPointInfo
{
get => PlayableBeatmap.ControlPointInfo;
set => PlayableBeatmap.ControlPointInfo = value;
}
public List<BreakPeriod> Breaks => PlayableBeatmap.Breaks; public List<BreakPeriod> Breaks => PlayableBeatmap.Breaks;

View File

@ -29,7 +29,11 @@ namespace osu.Game.Screens.Play
public BeatmapMetadata Metadata => PlayableBeatmap.Metadata; public BeatmapMetadata Metadata => PlayableBeatmap.Metadata;
public ControlPointInfo ControlPointInfo => PlayableBeatmap.ControlPointInfo; public ControlPointInfo ControlPointInfo
{
get => PlayableBeatmap.ControlPointInfo;
set => PlayableBeatmap.ControlPointInfo = value;
}
public List<BreakPeriod> Breaks => PlayableBeatmap.Breaks; public List<BreakPeriod> Breaks => PlayableBeatmap.Breaks;