Merge pull request #14619 from peppy/no-more-difficulty-control-points-info

Move `DifficultyControlPoint`s to be specified at a per-`HitObject` level
This commit is contained in:
Dan Balasescu
2021-10-14 17:24:32 +09:00
committed by GitHub
49 changed files with 436 additions and 267 deletions

View File

@ -5,14 +5,15 @@ using System;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Rulesets.Objects;
using osuTK;
namespace osu.Game.Screens.Edit.Compose.Components
{
public abstract class CircularDistanceSnapGrid : DistanceSnapGrid
{
protected CircularDistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null)
: base(startPosition, startTime, endTime)
protected CircularDistanceSnapGrid(HitObject referenceObject, Vector2 startPosition, double startTime, double? endTime = null)
: base(referenceObject, startPosition, startTime, endTime)
{
}
@ -79,7 +80,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
Vector2 normalisedDirection = direction * new Vector2(1f / distance);
Vector2 snappedPosition = StartPosition + normalisedDirection * radialCount * radius;
return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - StartPosition).Length));
return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(ReferenceObject, (snappedPosition - StartPosition).Length));
}
}
}

View File

@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Layout;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osuTK;
namespace osu.Game.Screens.Edit.Compose.Components
@ -54,15 +55,20 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly LayoutValue gridCache = new LayoutValue(Invalidation.RequiredParentSizeToFit);
private readonly double? endTime;
protected readonly HitObject ReferenceObject;
/// <summary>
/// Creates a new <see cref="DistanceSnapGrid"/>.
/// </summary>
/// <param name="referenceObject">A reference object to gather relevant difficulty values from.</param>
/// <param name="startPosition">The position at which the grid should start. The first tick is located one distance spacing length away from this point.</param>
/// <param name="startTime">The snapping time at <see cref="StartPosition"/>.</param>
/// <param name="endTime">The time at which the snapping grid should end. If null, the grid will continue until the bounds of the screen are exceeded.</param>
protected DistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null)
protected DistanceSnapGrid(HitObject referenceObject, Vector2 startPosition, double startTime, double? endTime = null)
{
ReferenceObject = referenceObject;
this.endTime = endTime;
StartPosition = startPosition;
StartTime = startTime;
@ -80,7 +86,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void updateSpacing()
{
DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime);
DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(ReferenceObject);
if (endTime == null)
MaxIntervals = int.MaxValue;
@ -88,7 +94,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
{
// +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors
double maxDuration = endTime.Value - StartTime + 1;
MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing));
MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(ReferenceObject, DistanceSpacing));
}
gridCache.Invalidate();

View File

@ -13,7 +13,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
public DifficultyPointPiece(DifficultyControlPoint point)
: base(point)
{
speedMultiplier = point.SpeedMultiplierBindable.GetBoundCopy();
speedMultiplier = point.SliderVelocityBindable.GetBoundCopy();
Y = Height;
}

View File

@ -15,6 +15,7 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osuTK;
namespace osu.Game.Screens.Edit.Compose.Components.Timeline
@ -298,14 +299,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private double getTimeFromPosition(Vector2 localPosition) =>
(localPosition.X / Content.DrawWidth) * track.Length;
public float GetBeatSnapDistanceAt(double referenceTime) => throw new NotImplementedException();
public float GetBeatSnapDistanceAt(HitObject referenceObject) => throw new NotImplementedException();
public float DurationToDistance(double referenceTime, double duration) => throw new NotImplementedException();
public float DurationToDistance(HitObject referenceObject, double duration) => throw new NotImplementedException();
public double DistanceToDuration(double referenceTime, float distance) => throw new NotImplementedException();
public double DistanceToDuration(HitObject referenceObject, float distance) => throw new NotImplementedException();
public double GetSnappedDurationFromDistance(double referenceTime, float distance) => throw new NotImplementedException();
public double GetSnappedDurationFromDistance(HitObject referenceObject, float distance) => throw new NotImplementedException();
public float GetSnappedDistanceFromDistance(double referenceTime, float distance) => throw new NotImplementedException();
public float GetSnappedDistanceFromDistance(HitObject referenceObject, float distance) => throw new NotImplementedException();
}
}

View File

@ -4,21 +4,22 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
namespace osu.Game.Screens.Edit.Timing
{
internal class DifficultySection : Section<DifficultyControlPoint>
{
private SliderWithTextBoxInput<double> multiplierSlider;
private SliderWithTextBoxInput<double> sliderVelocitySlider;
[BackgroundDependencyLoader]
private void load()
{
Flow.AddRange(new[]
{
multiplierSlider = new SliderWithTextBoxInput<double>("Speed Multiplier")
sliderVelocitySlider = new SliderWithTextBoxInput<double>("Slider Velocity")
{
Current = new DifficultyControlPoint().SpeedMultiplierBindable,
Current = new DifficultyControlPoint().SliderVelocityBindable,
KeyboardStep = 0.1f
}
});
@ -28,27 +29,27 @@ namespace osu.Game.Screens.Edit.Timing
{
if (point.NewValue != null)
{
var selectedPointBindable = point.NewValue.SpeedMultiplierBindable;
var selectedPointBindable = point.NewValue.SliderVelocityBindable;
// there may be legacy control points, which contain infinite precision for compatibility reasons (see LegacyDifficultyControlPoint).
// generally that level of precision could only be set by externally editing the .osu file, so at the point
// a user is looking to update this within the editor it should be safe to obliterate this additional precision.
double expectedPrecision = new DifficultyControlPoint().SpeedMultiplierBindable.Precision;
double expectedPrecision = new DifficultyControlPoint().SliderVelocityBindable.Precision;
if (selectedPointBindable.Precision < expectedPrecision)
selectedPointBindable.Precision = expectedPrecision;
multiplierSlider.Current = selectedPointBindable;
multiplierSlider.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
sliderVelocitySlider.Current = selectedPointBindable;
sliderVelocitySlider.Current.BindValueChanged(_ => ChangeHandler?.SaveState());
}
}
protected override DifficultyControlPoint CreatePoint()
{
var reference = Beatmap.ControlPointInfo.DifficultyPointAt(SelectedGroup.Value.Time);
var reference = (Beatmap.ControlPointInfo as LegacyControlPointInfo)?.DifficultyPointAt(SelectedGroup.Value.Time) ?? DifficultyControlPoint.DEFAULT;
return new DifficultyControlPoint
{
SpeedMultiplier = reference.SpeedMultiplier,
SliderVelocity = reference.SliderVelocity,
};
}
}

View File

@ -3,6 +3,7 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics.UserInterfaceV2;
@ -13,13 +14,20 @@ namespace osu.Game.Screens.Edit.Timing
private LabelledSwitchButton kiai;
private LabelledSwitchButton omitBarLine;
private SliderWithTextBoxInput<double> scrollSpeedSlider;
[BackgroundDependencyLoader]
private void load()
{
Flow.AddRange(new[]
Flow.AddRange(new Drawable[]
{
kiai = new LabelledSwitchButton { Label = "Kiai Time" },
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.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
{
KiaiMode = reference.KiaiMode,
OmitFirstBarLine = reference.OmitFirstBarLine
OmitFirstBarLine = reference.OmitFirstBarLine,
ScrollSpeed = reference.ScrollSpeed,
};
}
}

View File

@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
public DifficultyRowAttribute(DifficultyControlPoint difficulty)
: base(difficulty, "difficulty")
{
speedMultiplier = difficulty.SpeedMultiplierBindable.GetBoundCopy();
speedMultiplier = difficulty.SliderVelocityBindable.GetBoundCopy();
}
[BackgroundDependencyLoader]
@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
},
text = new AttributeText(Point)
{
Width = 40,
Width = 45,
},
});

View File

@ -12,14 +12,18 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
{
private readonly Bindable<bool> kiaiMode;
private readonly Bindable<bool> omitBarLine;
private readonly BindableNumber<double> scrollSpeed;
private AttributeText kiaiModeBubble;
private AttributeText omitBarLineBubble;
private AttributeText text;
public EffectRowAttribute(EffectControlPoint effect)
: base(effect, "effect")
{
kiaiMode = effect.KiaiModeBindable.GetBoundCopy();
omitBarLine = effect.OmitFirstBarLineBindable.GetBoundCopy();
scrollSpeed = effect.ScrollSpeedBindable.GetBoundCopy();
}
[BackgroundDependencyLoader]
@ -27,12 +31,20 @@ namespace osu.Game.Screens.Edit.Timing.RowAttributes
{
Content.AddRange(new Drawable[]
{
new AttributeProgressBar(Point)
{
Current = scrollSpeed,
},
text = new AttributeText(Point) { Width = 45 },
kiaiModeBubble = new AttributeText(Point) { Text = "kiai" },
omitBarLineBubble = new AttributeText(Point) { Text = "no barline" },
});
kiaiMode.BindValueChanged(enabled => kiaiModeBubble.FadeTo(enabled.NewValue ? 1 : 0), true);
omitBarLine.BindValueChanged(enabled => omitBarLineBubble.FadeTo(enabled.NewValue ? 1 : 0), true);
scrollSpeed.BindValueChanged(_ => updateText(), true);
}
private void updateText() => text.Text = $"{scrollSpeed.Value:n2}x";
}
}

View File

@ -5,6 +5,7 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Graphics.UserInterfaceV2;
namespace osu.Game.Screens.Edit.Timing
@ -42,6 +43,15 @@ namespace osu.Game.Screens.Edit.Timing
}
}
protected override SampleControlPoint CreatePoint() => new SampleControlPoint(); // TODO: remove
protected override SampleControlPoint CreatePoint()
{
var reference = (Beatmap.ControlPointInfo as LegacyControlPointInfo)?.SamplePointAt(SelectedGroup.Value.Time) ?? SampleControlPoint.DEFAULT;
return new SampleControlPoint
{
SampleBank = reference.SampleBank,
SampleVolume = reference.SampleVolume,
};
}
}
}