1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 13:37:25 +08:00

Merge pull request #23431 from peppy/base-s-v

Add beatmap-level velocity setting to difficulty settings
This commit is contained in:
Bartłomiej Dach 2023-05-09 21:16:58 +02:00 committed by GitHub
commit e85afeb3f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 15 deletions

View File

@ -34,7 +34,8 @@ namespace osu.Game.Beatmaps
float ApproachRate { get; }
/// <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>
double SliderMultiplier { get; }

View File

@ -126,6 +126,16 @@ namespace osu.Game.Localisation
public static LocalisableString OverallDifficultyDescription =>
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>
/// "Metadata"
/// </summary>

View File

@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (selected is IHasSliderVelocity sliderVelocity)
{
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)

View File

@ -96,7 +96,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
RelativeSizeAxes = Axes.X,
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
{
private readonly Bindable<double?> current;
public SliderVelocityInspector(Bindable<double?> current)
{
this.current = current;
}
[BackgroundDependencyLoader]
private void load()
{
EditorBeatmap.TransactionBegan += updateInspectorText;
EditorBeatmap.TransactionEnded += updateInspectorText;
EditorBeatmap.BeatmapReprocessed += updateInspectorText;
current.ValueChanged += _ => updateInspectorText();
updateInspectorText();
}
private void updateInspectorText()
{
double beatmapVelocity = EditorBeatmap.Difficulty.SliderMultiplier;
InspectorText.Clear();
double[] sliderVelocities = EditorBeatmap.HitObjects.OfType<IHasSliderVelocity>().Select(sv => sv.SliderVelocity).OrderBy(v => v).ToArray();
if (sliderVelocities.Length < 2)
return;
AddHeader("Base velocity (from beatmap setup)");
AddValue($"{beatmapVelocity:#,0.00}x");
double? modeSliderVelocity = sliderVelocities.GroupBy(v => v).MaxBy(v => v.Count())?.Key;
double? medianSliderVelocity = sliderVelocities[sliderVelocities.Length / 2];
AddHeader("Final velocity");
AddValue($"{beatmapVelocity * current.Value:#,0.00}x");
AddHeader("Average velocity");
AddValue($"{medianSliderVelocity:#,0.00}x");
if (sliderVelocities.First() != sliderVelocities.Last())
{
AddHeader("Beatmap velocity range");
AddHeader("Most used velocity");
AddValue($"{modeSliderVelocity:#,0.00}x");
string range = $"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x";
if (beatmapVelocity != 1)
range += $" ({beatmapVelocity * sliderVelocities.First():#,0.00}x - {beatmapVelocity * sliderVelocities.Last():#,0.00}x)";
AddHeader("Velocity range");
AddValue($"{sliderVelocities.First():#,0.00}x - {sliderVelocities.Last():#,0.00}x");
AddValue(range);
}
}
protected override void Dispose(bool isDisposing)
@ -181,6 +195,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
EditorBeatmap.TransactionBegan -= updateInspectorText;
EditorBeatmap.TransactionEnded -= updateInspectorText;
EditorBeatmap.BeatmapReprocessed -= updateInspectorText;
}
}
}

View File

@ -19,6 +19,7 @@ namespace osu.Game.Screens.Edit.Setup
private LabelledSliderBar<float> healthDrainSlider = null!;
private LabelledSliderBar<float> approachRateSlider = null!;
private LabelledSliderBar<float> overallDifficultySlider = null!;
private LabelledSliderBar<double> baseVelocitySlider = null!;
public override LocalisableString Title => EditorSetupStrings.DifficultyHeader;
@ -79,13 +80,29 @@ namespace osu.Game.Screens.Edit.Setup
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>>())
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.
// 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.ApproachRate = approachRateSlider.Current.Value;
Beatmap.Difficulty.OverallDifficulty = overallDifficultySlider.Current.Value;
Beatmap.Difficulty.SliderMultiplier = baseVelocitySlider.Current.Value;
Beatmap.UpdateAllHitObjects();
Beatmap.SaveState();