mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 19:42:55 +08:00
Merge pull request #23431 from peppy/base-s-v
Add beatmap-level velocity setting to difficulty settings
This commit is contained in:
commit
e85afeb3f7
@ -34,7 +34,8 @@ namespace osu.Game.Beatmaps
|
|||||||
float ApproachRate { get; }
|
float ApproachRate { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The slider multiplier of the associated beatmap.
|
/// The base slider velocity of the associated beatmap.
|
||||||
|
/// This was known as "SliderMultiplier" in the .osu format and stable editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
double SliderMultiplier { get; }
|
double SliderMultiplier { get; }
|
||||||
|
|
||||||
|
@ -126,6 +126,16 @@ namespace osu.Game.Localisation
|
|||||||
public static LocalisableString OverallDifficultyDescription =>
|
public static LocalisableString OverallDifficultyDescription =>
|
||||||
new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)");
|
new TranslatableString(getKey(@"overall_difficulty_description"), @"The harshness of hit windows and difficulty of special objects (ie. spinners)");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Base Velocity"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString BaseVelocity => new TranslatableString(getKey(@"base_velocity"), @"Base Velocity");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets."
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString BaseVelocityDescription => new TranslatableString(getKey(@"base_velocity_description"), @"The base velocity of the beatmap, affecting things like slider velocity and scroll speed in some rulesets.");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Metadata"
|
/// "Metadata"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
if (selected is IHasSliderVelocity sliderVelocity)
|
if (selected is IHasSliderVelocity sliderVelocity)
|
||||||
{
|
{
|
||||||
AddHeader("Slider Velocity");
|
AddHeader("Slider Velocity");
|
||||||
AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x");
|
AddValue($"{sliderVelocity.SliderVelocity:#,0.00}x ({sliderVelocity.SliderVelocity * EditorBeatmap.Difficulty.SliderMultiplier:#,0.00}x)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected is IHasRepeats repeats)
|
if (selected is IHasRepeats repeats)
|
||||||
|
@ -96,7 +96,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Text = "Hold shift while dragging the end of an object to adjust velocity while snapping."
|
Text = "Hold shift while dragging the end of an object to adjust velocity while snapping."
|
||||||
},
|
},
|
||||||
new SliderVelocityInspector(),
|
new SliderVelocityInspector(sliderVelocitySlider.Current),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -145,34 +145,48 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
internal partial class SliderVelocityInspector : EditorInspector
|
internal partial class SliderVelocityInspector : EditorInspector
|
||||||
{
|
{
|
||||||
|
private readonly Bindable<double?> current;
|
||||||
|
|
||||||
|
public SliderVelocityInspector(Bindable<double?> current)
|
||||||
|
{
|
||||||
|
this.current = current;
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
EditorBeatmap.TransactionBegan += updateInspectorText;
|
EditorBeatmap.TransactionBegan += updateInspectorText;
|
||||||
EditorBeatmap.TransactionEnded += updateInspectorText;
|
EditorBeatmap.TransactionEnded += updateInspectorText;
|
||||||
|
EditorBeatmap.BeatmapReprocessed += updateInspectorText;
|
||||||
|
current.ValueChanged += _ => updateInspectorText();
|
||||||
|
|
||||||
updateInspectorText();
|
updateInspectorText();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateInspectorText()
|
private void updateInspectorText()
|
||||||
{
|
{
|
||||||
|
double beatmapVelocity = EditorBeatmap.Difficulty.SliderMultiplier;
|
||||||
|
|
||||||
InspectorText.Clear();
|
InspectorText.Clear();
|
||||||
|
|
||||||
double[] sliderVelocities = EditorBeatmap.HitObjects.OfType<IHasSliderVelocity>().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray();
|
double[] sliderVelocities = EditorBeatmap.HitObjects.OfType<IHasSliderVelocity>().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray();
|
||||||
|
|
||||||
if (sliderVelocities.Length < 2)
|
AddHeader("Base velocity (from beatmap setup)");
|
||||||
return;
|
AddValue($"{beatmapVelocity:#,0.00}x");
|
||||||
|
|
||||||
double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key;
|
AddHeader("Final velocity");
|
||||||
double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2];
|
AddValue($"{beatmapVelocity * current.Value:#,0.00}x");
|
||||||
|
|
||||||
AddHeader("Average velocity");
|
if (sliderVelocities.First() != sliderVelocities.Last())
|
||||||
AddValue($"{medianSliderVelocity:#,0.00}x");
|
{
|
||||||
|
AddHeader("Beatmap velocity range");
|
||||||
|
|
||||||
AddHeader("Most used velocity");
|
string range = $"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x";
|
||||||
AddValue($"{modeSliderVelocity:#,0.00}x");
|
if (beatmapVelocity != 1)
|
||||||
|
range += $" ({beatmapVelocity * sliderVelocities.First():#,0.00}x - {beatmapVelocity * sliderVelocities.Last():#,0.00}x)";
|
||||||
|
|
||||||
AddHeader("Velocity range");
|
AddValue(range);
|
||||||
AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
@ -181,6 +195,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
EditorBeatmap.TransactionBegan -= updateInspectorText;
|
EditorBeatmap.TransactionBegan -= updateInspectorText;
|
||||||
EditorBeatmap.TransactionEnded -= updateInspectorText;
|
EditorBeatmap.TransactionEnded -= updateInspectorText;
|
||||||
|
EditorBeatmap.BeatmapReprocessed -= updateInspectorText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ namespace osu.Game.Screens.Edit.Setup
|
|||||||
private LabelledSliderBar<float> healthDrainSlider = null!;
|
private LabelledSliderBar<float> healthDrainSlider = null!;
|
||||||
private LabelledSliderBar<float> approachRateSlider = null!;
|
private LabelledSliderBar<float> approachRateSlider = null!;
|
||||||
private LabelledSliderBar<float> overallDifficultySlider = null!;
|
private LabelledSliderBar<float> overallDifficultySlider = null!;
|
||||||
|
private LabelledSliderBar<double> baseVelocitySlider = null!;
|
||||||
|
|
||||||
public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
|
public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
|
||||||
|
|
||||||
@ -79,13 +80,29 @@ namespace osu.Game.Screens.Edit.Setup
|
|||||||
Precision = 0.1f,
|
Precision = 0.1f,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
baseVelocitySlider = new LabelledSliderBar<double>
|
||||||
|
{
|
||||||
|
Label = EditorSetupStrings.BaseVelocity,
|
||||||
|
FixedLabelWidth = LABEL_WIDTH,
|
||||||
|
Description = EditorSetupStrings.BaseVelocityDescription,
|
||||||
|
Current = new BindableDouble(Beatmap.Difficulty.SliderMultiplier)
|
||||||
|
{
|
||||||
|
Default = 1,
|
||||||
|
MinValue = 0.4,
|
||||||
|
MaxValue = 3.6,
|
||||||
|
Precision = 0.01f,
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var item in Children.OfType<LabelledSliderBar<float>>())
|
foreach (var item in Children.OfType<LabelledSliderBar<float>>())
|
||||||
item.Current.ValueChanged += onValueChanged;
|
item.Current.ValueChanged += _ => updateValues();
|
||||||
|
|
||||||
|
foreach (var item in Children.OfType<LabelledSliderBar<double>>())
|
||||||
|
item.Current.ValueChanged += _ => updateValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onValueChanged(ValueChangedEvent<float> args)
|
private void updateValues()
|
||||||
{
|
{
|
||||||
// for now, update these on commit rather than making BeatmapMetadata bindables.
|
// for now, update these on commit rather than making BeatmapMetadata bindables.
|
||||||
// after switching database engines we can reconsider if switching to bindables is a good direction.
|
// after switching database engines we can reconsider if switching to bindables is a good direction.
|
||||||
@ -93,6 +110,7 @@ namespace osu.Game.Screens.Edit.Setup
|
|||||||
Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value;
|
Beatmap.Difficulty.DrainRate = healthDrainSlider.Current.Value;
|
||||||
Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value;
|
Beatmap.Difficulty.ApproachRate = approachRateSlider.Current.Value;
|
||||||
Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value;
|
Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value;
|
||||||
|
Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value;
|
||||||
|
|
||||||
Beatmap.UpdateAllHitObjects();
|
Beatmap.UpdateAllHitObjects();
|
||||||
Beatmap.SaveState();
|
Beatmap.SaveState();
|
||||||
|
Loading…
Reference in New Issue
Block a user