Automatic red control point generation & corner threshold

This commit is contained in:
Thomas Müller-Höhne 2023-11-14 16:52:45 +09:00
parent fa976a5aa0
commit 90ec6895d1
3 changed files with 65 additions and 10 deletions

View File

@ -86,6 +86,13 @@ protected override void LoadComplete()
bSplineBuilder.Tolerance = e.NewValue;
updateSliderPathFromBSplineBuilder();
}, true);
drawingSettingsProvider.CornerThreshold.BindValueChanged(e =>
{
if (bSplineBuilder.CornerThreshold != e.NewValue)
bSplineBuilder.CornerThreshold = e.NewValue;
updateSliderPathFromBSplineBuilder();
}, true);
}
[Resolved]
@ -100,8 +107,9 @@ public override void UpdateTimeAndPosition(SnapResult result)
case SliderPlacementState.Initial:
BeginPlacement();
double? nearestSliderVelocity = (editorBeatmap.HitObjects
.LastOrDefault(h => h is Slider && h.GetEndTime() < HitObject.StartTime) as Slider)?.SliderVelocityMultiplier;
double? nearestSliderVelocity = (editorBeatmap
.HitObjects
.LastOrDefault(h => h is Slider && h.GetEndTime() < HitObject.StartTime) as Slider)?.SliderVelocityMultiplier;
HitObject.SliderVelocityMultiplier = nearestSliderVelocity ?? 1;
HitObject.Position = ToLocalSpace(result.ScreenSpacePosition);
@ -193,9 +201,19 @@ private void updateSliderPathFromBSplineBuilder()
{
Scheduler.AddOnce(static self =>
{
var cps = self.bSplineBuilder.GetControlPoints();
self.HitObject.Path.ControlPoints.RemoveRange(1, self.HitObject.Path.ControlPoints.Count - 1);
self.HitObject.Path.ControlPoints.AddRange(cps.Skip(1).Select(v => new PathControlPoint(v)));
var cps = self.bSplineBuilder.ControlPoints;
var sliderCps = self.HitObject.Path.ControlPoints;
sliderCps.RemoveRange(1, sliderCps.Count - 1);
// Add the control points from the BSpline builder while converting control points that repeat
// three or more times to a single PathControlPoint with linear type.
for (int i = 1; i < cps.Count; i++)
{
bool isSharp = i < cps.Count - 2 && cps[i] == cps[i + 1] && cps[i] == cps[i + 2];
sliderCps.Add(new PathControlPoint(cps[i], isSharp ? PathType.BSpline(3) : null));
if (isSharp)
i += 2;
}
}, this);
}

View File

@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Osu.Edit
public interface ISliderDrawingSettingsProvider
{
BindableFloat Tolerance { get; }
BindableFloat CornerThreshold { get; }
}
}

View File

@ -12,20 +12,34 @@ namespace osu.Game.Rulesets.Osu.Edit
{
public partial class OsuSliderDrawingSettingsProvider : Drawable, ISliderDrawingSettingsProvider, IToolboxAttachment
{
public BindableFloat Tolerance { get; } = new BindableFloat(0.1f)
public BindableFloat Tolerance { get; } = new BindableFloat(1.5f)
{
MinValue = 0.05f,
MaxValue = 3f,
Precision = 0.01f
};
private readonly BindableInt sliderTolerance = new BindableInt(50)
{
MinValue = 5,
MaxValue = 100
};
public BindableFloat CornerThreshold { get; } = new BindableFloat(0.4f)
{
MinValue = 0.05f,
MaxValue = 1f,
Precision = 0.01f
};
private readonly BindableInt sliderTolerance = new BindableInt(10)
private readonly BindableInt sliderCornerThreshold = new BindableInt(40)
{
MinValue = 5,
MaxValue = 100
};
private ExpandableSlider<int> toleranceSlider = null!;
private ExpandableSlider<int> cornerThresholdSlider = null!;
protected override void LoadComplete()
{
@ -33,16 +47,28 @@ protected override void LoadComplete()
sliderTolerance.BindValueChanged(v =>
{
float newValue = v.NewValue / 100f;
if (!Precision.AlmostEquals(newValue, Tolerance.Value))
float newValue = v.NewValue / 33f;
if (!Precision.AlmostEquals(newValue, Tolerance.Value, 1e-7f))
Tolerance.Value = newValue;
});
Tolerance.BindValueChanged(v =>
{
int newValue = (int)Math.Round(v.NewValue * 100f);
int newValue = (int)Math.Round(v.NewValue * 33f);
if (sliderTolerance.Value != newValue)
sliderTolerance.Value = newValue;
});
sliderCornerThreshold.BindValueChanged(v =>
{
float newValue = v.NewValue / 100f;
if (!Precision.AlmostEquals(newValue, CornerThreshold.Value, 1e-7f))
CornerThreshold.Value = newValue;
});
CornerThreshold.BindValueChanged(v =>
{
int newValue = (int)Math.Round(v.NewValue * 100f);
if (sliderCornerThreshold.Value != newValue)
sliderCornerThreshold.Value = newValue;
});
}
public void AttachToToolbox(ExpandingToolboxContainer toolboxContainer)
@ -54,6 +80,10 @@ public void AttachToToolbox(ExpandingToolboxContainer toolboxContainer)
toleranceSlider = new ExpandableSlider<int>
{
Current = sliderTolerance
},
cornerThresholdSlider = new ExpandableSlider<int>
{
Current = sliderCornerThreshold
}
}
});
@ -63,6 +93,12 @@ public void AttachToToolbox(ExpandingToolboxContainer toolboxContainer)
toleranceSlider.ContractedLabelText = $"C. P. S.: {e.NewValue:N0}";
toleranceSlider.ExpandedLabelText = $"Control Point Spacing: {e.NewValue:N0}";
}, true);
sliderCornerThreshold.BindValueChanged(e =>
{
cornerThresholdSlider.ContractedLabelText = $"C. T.: {e.NewValue:N0}";
cornerThresholdSlider.ExpandedLabelText = $"Corner Threshold: {e.NewValue:N0}";
}, true);
}
}
}