Move mania-specific conversion to converter

This commit is contained in:
Dean Herbert
2021-09-06 21:05:43 +09:00
parent 52b6b05883
commit 3c7a34bdbd
7 changed files with 86 additions and 35 deletions

View File

@ -8,6 +8,8 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Mania.Beatmaps.Patterns; using osu.Game.Rulesets.Mania.Beatmaps.Patterns;
@ -47,6 +49,26 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
if (IsForCurrentRuleset) if (IsForCurrentRuleset)
{ {
if (beatmap.ControlPointInfo is LegacyControlPointInfo legacyControlPoints)
{
// convert all slider velocity adjustments to scroll speed adjustments.
foreach (var controlPoint in legacyControlPoints.DifficultyPoints.ToArray())
{
double time = controlPoint.Time;
var reference = legacyControlPoints.EffectPointAt(time);
var scrollControlPoint = new EffectControlPoint();
scrollControlPoint.CopyFrom(reference);
scrollControlPoint.ScrollSpeed = controlPoint.SliderVelocity;
legacyControlPoints.Add(time, scrollControlPoint);
// remove the DifficultyControlPoint as we don't need them any more.
legacyControlPoints.GroupAt(time).Remove(controlPoint);
}
}
TargetColumns = GetColumnCountForNonConvert(beatmap.BeatmapInfo); TargetColumns = GetColumnCountForNonConvert(beatmap.BeatmapInfo);
if (TargetColumns > ManiaRuleset.MAX_STAGE_KEYS) if (TargetColumns > ManiaRuleset.MAX_STAGE_KEYS)

View File

@ -172,7 +172,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.AreEqual(4, controlPoints.TimingPoints.Count); Assert.AreEqual(4, controlPoints.TimingPoints.Count);
Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); Assert.AreEqual(5, controlPoints.DifficultyPoints.Count);
Assert.AreEqual(34, controlPoints.SamplePoints.Count); Assert.AreEqual(34, controlPoints.SamplePoints.Count);
Assert.AreEqual(13, controlPoints.EffectPoints.Count); Assert.AreEqual(8, controlPoints.EffectPoints.Count);
var timingPoint = controlPoints.TimingPointAt(0); var timingPoint = controlPoints.TimingPointAt(0);
Assert.AreEqual(956, timingPoint.Time); Assert.AreEqual(956, timingPoint.Time);

View File

@ -387,7 +387,6 @@ namespace osu.Game.Beatmaps.Formats
{ {
KiaiMode = kiaiMode, KiaiMode = kiaiMode,
OmitFirstBarLine = omitFirstBarSignature, OmitFirstBarLine = omitFirstBarSignature,
ScrollSpeed = speedMultiplier,
}, timingChange); }, timingChange);
addControlPoint(time, new LegacySampleControlPoint addControlPoint(time, new LegacySampleControlPoint

View File

@ -170,24 +170,22 @@ namespace osu.Game.Beatmaps.Formats
if (beatmap.ControlPointInfo.Groups.Count == 0) if (beatmap.ControlPointInfo.Groups.Count == 0)
return; return;
writer.WriteLine("[TimingPoints]");
if (!(beatmap.ControlPointInfo is LegacyControlPointInfo))
{
var legacyControlPoints = new LegacyControlPointInfo(); var legacyControlPoints = new LegacyControlPointInfo();
foreach (var point in beatmap.ControlPointInfo.AllControlPoints) foreach (var point in beatmap.ControlPointInfo.AllControlPoints)
legacyControlPoints.Add(point.Time, point.DeepClone()); legacyControlPoints.Add(point.Time, point.DeepClone());
beatmap.ControlPointInfo = legacyControlPoints; writer.WriteLine("[TimingPoints]");
SampleControlPoint lastRelevantSamplePoint = null; SampleControlPoint lastRelevantSamplePoint = null;
DifficultyControlPoint lastRelevantDifficultyPoint = null; DifficultyControlPoint lastRelevantDifficultyPoint = null;
bool isOsuRuleset = beatmap.BeatmapInfo.RulesetID == 0;
// iterate over hitobjects and pull out all required sample and difficulty changes // iterate over hitobjects and pull out all required sample and difficulty changes
foreach (var h in beatmap.HitObjects) foreach (var h in beatmap.HitObjects)
{ {
var hSamplePoint = h.SampleControlPoint; if (isOsuRuleset)
{
var hDifficultyPoint = h.DifficultyControlPoint; var hDifficultyPoint = h.DifficultyControlPoint;
if (!hDifficultyPoint.IsRedundant(lastRelevantDifficultyPoint)) if (!hDifficultyPoint.IsRedundant(lastRelevantDifficultyPoint))
@ -195,6 +193,9 @@ namespace osu.Game.Beatmaps.Formats
legacyControlPoints.Add(hDifficultyPoint.Time, hDifficultyPoint); legacyControlPoints.Add(hDifficultyPoint.Time, hDifficultyPoint);
lastRelevantDifficultyPoint = hDifficultyPoint; lastRelevantDifficultyPoint = hDifficultyPoint;
} }
}
var hSamplePoint = h.SampleControlPoint;
if (!hSamplePoint.IsRedundant(lastRelevantSamplePoint)) if (!hSamplePoint.IsRedundant(lastRelevantSamplePoint))
{ {
@ -203,11 +204,15 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
// In the future we may want to pull out approach rate changes from EffectPoints (and create DifficultyControlPoints to handle them). // handle scroll speed, which is stored as "slider velocity" in legacy formats.
// This requires special consideration due to precision mismatches (see implementation of LegacyDifficultyControlPoint). // note that this is only relevant for mania beatmaps.
if (!isOsuRuleset)
{
foreach (var point in legacyControlPoints.EffectPoints)
legacyControlPoints.Add(point.Time, new DifficultyControlPoint { SliderVelocity = point.ScrollSpeed });
} }
foreach (var group in beatmap.ControlPointInfo.Groups) foreach (var group in legacyControlPoints.Groups)
{ {
var groupTimingPoint = group.ControlPoints.OfType<TimingControlPoint>().FirstOrDefault(); var groupTimingPoint = group.ControlPoints.OfType<TimingControlPoint>().FirstOrDefault();
@ -220,7 +225,7 @@ namespace osu.Game.Beatmaps.Formats
} }
// Output any remaining effects as secondary non-timing control point. // Output any remaining effects as secondary non-timing control point.
var difficultyPoint = ((LegacyControlPointInfo)beatmap.ControlPointInfo).DifficultyPointAt(group.Time); var difficultyPoint = legacyControlPoints.DifficultyPointAt(group.Time);
writer.Write(FormattableString.Invariant($"{group.Time},")); writer.Write(FormattableString.Invariant($"{group.Time},"));
writer.Write(FormattableString.Invariant($"{-100 / difficultyPoint.SliderVelocity},")); writer.Write(FormattableString.Invariant($"{-100 / difficultyPoint.SliderVelocity},"));
outputControlPointAt(group.Time, false); outputControlPointAt(group.Time, false);
@ -228,8 +233,8 @@ namespace osu.Game.Beatmaps.Formats
void outputControlPointAt(double time, bool isTimingPoint) void outputControlPointAt(double time, bool isTimingPoint)
{ {
var samplePoint = ((LegacyControlPointInfo)beatmap.ControlPointInfo).SamplePointAt(time); var samplePoint = legacyControlPoints.SamplePointAt(time);
var effectPoint = beatmap.ControlPointInfo.EffectPointAt(time); var effectPoint = legacyControlPoints.EffectPointAt(time);
// Apply the control point to a hit sample to uncover legacy properties (e.g. suffix) // Apply the control point to a hit sample to uncover legacy properties (e.g. suffix)
HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty)); HitSampleInfo tempHitSample = samplePoint.ApplyTo(new ConvertHitObjectParser.LegacyHitSampleInfo(string.Empty));
@ -241,7 +246,7 @@ namespace osu.Game.Beatmaps.Formats
if (effectPoint.OmitFirstBarLine) if (effectPoint.OmitFirstBarLine)
effectFlags |= LegacyEffectFlags.OmitFirstBarLine; effectFlags |= LegacyEffectFlags.OmitFirstBarLine;
writer.Write(FormattableString.Invariant($"{(int)beatmap.ControlPointInfo.TimingPointAt(time).TimeSignature},")); writer.Write(FormattableString.Invariant($"{(int)legacyControlPoints.TimingPointAt(time).TimeSignature},"));
writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},")); writer.Write(FormattableString.Invariant($"{(int)toLegacySampleBank(tempHitSample.Bank)},"));
writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},")); writer.Write(FormattableString.Invariant($"{toLegacyCustomSampleBank(tempHitSample)},"));
writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},")); writer.Write(FormattableString.Invariant($"{tempHitSample.Volume},"));

View File

@ -148,10 +148,16 @@ namespace osu.Game.Rulesets.UI.Scrolling
// Generate the timing points, making non-timing changes use the previous timing change and vice-versa // Generate the timing points, making non-timing changes use the previous timing change and vice-versa
var timingChanges = allPoints.Select(c => var timingChanges = allPoints.Select(c =>
{ {
if (c is TimingControlPoint timingPoint) switch (c)
{
case TimingControlPoint timingPoint:
lastTimingPoint = timingPoint; lastTimingPoint = timingPoint;
else if (c is EffectControlPoint difficultyPoint) break;
case EffectControlPoint difficultyPoint:
lastEffectPoint = difficultyPoint; lastEffectPoint = difficultyPoint;
break;
}
return new MultiplierControlPoint(c.Time) return new MultiplierControlPoint(c.Time)
{ {

View File

@ -3,6 +3,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Graphics.UserInterfaceV2;
@ -13,13 +14,20 @@ namespace osu.Game.Screens.Edit.Timing
private LabelledSwitchButton kiai; private LabelledSwitchButton kiai;
private LabelledSwitchButton omitBarLine; private LabelledSwitchButton omitBarLine;
private SliderWithTextBoxInput<double> scrollSpeedSlider;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Flow.AddRange(new[] Flow.AddRange(new Drawable[]
{ {
kiai = new LabelledSwitchButton { Label = "Kiai Time" }, kiai = new LabelledSwitchButton { Label = "Kiai Time" },
omitBarLine = new LabelledSwitchButton { Label = "Skip Bar Line" }, omitBarLine = new LabelledSwitchButton { Label = "Skip Bar Line" },
scrollSpeedSlider = new SliderWithTextBoxInput<double>("Scroll Speed")
{
Current = new EffectControlPoint().ScrollSpeedBindable,
KeyboardStep = 0.1f
}
}); });
} }
@ -32,6 +40,9 @@ namespace osu.Game.Screens.Edit.Timing
omitBarLine.Current = point.NewValue.OmitFirstBarLineBindable; omitBarLine.Current = point.NewValue.OmitFirstBarLineBindable;
omitBarLine.Current.BindValueChanged(_ => ChangeHandler?.SaveState()); omitBarLine.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
scrollSpeedSlider.Current = point.NewValue.ScrollSpeedBindable;
scrollSpeedSlider.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
} }
} }
@ -42,7 +53,8 @@ namespace osu.Game.Screens.Edit.Timing
return new EffectControlPoint return new EffectControlPoint
{ {
KiaiMode = reference.KiaiMode, KiaiMode = reference.KiaiMode,
OmitFirstBarLine = reference.OmitFirstBarLine OmitFirstBarLine = reference.OmitFirstBarLine,
ScrollSpeed = reference.ScrollSpeed,
}; };
} }
} }

View File

@ -12,6 +12,8 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
{ {
private readonly Bindable<bool> kiaiMode; private readonly Bindable<bool> kiaiMode;
private readonly Bindable<bool> omitBarLine; private readonly Bindable<bool> omitBarLine;
private readonly BindableNumber<double> scrollSpeed;
private AttributeText kiaiModeBubble; private AttributeText kiaiModeBubble;
private AttributeText omitBarLineBubble; private AttributeText omitBarLineBubble;
@ -20,6 +22,7 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
{ {
kiaiMode = effect.KiaiModeBindable.GetBoundCopy(); kiaiMode = effect.KiaiModeBindable.GetBoundCopy();
omitBarLine = effect.OmitFirstBarLineBindable.GetBoundCopy(); omitBarLine = effect.OmitFirstBarLineBindable.GetBoundCopy();
scrollSpeed = effect.ScrollSpeedBindable.GetBoundCopy();
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -27,6 +30,10 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
{ {
Content.AddRange(new Drawable[] Content.AddRange(new Drawable[]
{ {
new AttributeProgressBar(Point)
{
Current = scrollSpeed,
},
kiaiModeBubble = new AttributeText(Point) { Text = "kiai" }, kiaiModeBubble = new AttributeText(Point) { Text = "kiai" },
omitBarLineBubble = new AttributeText(Point) { Text = "no barline" }, omitBarLineBubble = new AttributeText(Point) { Text = "no barline" },
}); });