1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 14:12:55 +08:00

Make sliders respond to control point changes

This commit is contained in:
smoogipoo 2018-10-29 15:36:43 +09:00
parent b0f5ace0e8
commit acd703c27b
10 changed files with 92 additions and 17 deletions

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{
public class TestCaseSliderSelectionMask : HitObjectSelectionMaskTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new Type[]
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(SliderSelectionMask),
typeof(SliderCircleSelectionMask),

View File

@ -73,10 +73,27 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
protected override bool OnDrag(DragEvent e)
{
var newControlPoints = slider.ControlPoints.ToArray();
newControlPoints[index] += e.Delta;
if (index == 0)
{
// Special handling for the head - only the position of the slider changes
slider.Position += e.Delta;
slider.ControlPoints = newControlPoints;
// Since control points are relative to the position of the slider, they all need to be offset backwards by the delta
var newControlPoints = slider.ControlPoints.ToArray();
for (int i = 1; i < newControlPoints.Length; i++)
newControlPoints[i] -= e.Delta;
slider.ControlPoints = newControlPoints;
slider.Curve.Calculate(true);
}
else
{
var newControlPoints = slider.ControlPoints.ToArray();
newControlPoints[index] += e.Delta;
slider.ControlPoints = newControlPoints;
slider.Curve.Calculate(true);
}
return true;
}

View File

@ -46,6 +46,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
// Need to cause one update
body.UpdateProgress(0);
body.Refresh();
}
}
}

View File

@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Masks.SliderMasks.Components
{
this.slider = slider;
this.position = position;
slider.ControlPointsChanged += _ => UpdatePosition();
}
protected override void UpdatePosition()

View File

@ -85,6 +85,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
slider.ControlPointsChanged += _ => Body.Refresh();
}
public override Color4 AccentColour

View File

@ -16,7 +16,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
this.slider = slider;
Position = HitObject.Position - slider.Position;
h.PositionChanged += _ => updatePosition();
slider.ControlPointsChanged += _ => updatePosition();
updatePosition();
}
protected override void Update()
@ -33,5 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public Action<double> OnShake;
protected override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength);
private void updatePosition() => Position = HitObject.Position - slider.Position;
}
}

View File

@ -8,6 +8,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking
{
private readonly Slider slider;
/// <summary>
/// The judgement text is provided by the <see cref="DrawableSlider"/>.
/// </summary>
@ -18,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle)
: base(hitCircle)
{
this.slider = slider;
Origin = Anchor.Centre;
RelativeSizeAxes = Axes.Both;
@ -25,7 +29,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
AlwaysPresent = true;
Position = HitObject.Position - slider.Position;
hitCircle.PositionChanged += _ => updatePosition();
slider.ControlPointsChanged += _ => updatePosition();
updatePosition();
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
@ -33,5 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (!userTriggered && timeOffset >= 0)
ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss);
}
private void updatePosition() => Position = HitObject.Position - slider.Position;
}
}

View File

@ -45,15 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
[BackgroundDependencyLoader]
private void load()
{
// Generate the entire curve
slider.Curve.GetPathToProgress(CurrentCurve, 0, 1);
SetVertices(CurrentCurve);
// The body is sized to the full path size to avoid excessive autosize computations
Size = Path.Size;
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
Refresh();
}
public void UpdateProgress(double completionProgress)
@ -80,6 +72,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
setRange(start, end);
}
public void Refresh()
{
// Generate the entire curve
slider.Curve.GetPathToProgress(CurrentCurve, 0, 1);
SetVertices(CurrentCurve);
// The body is sized to the full path size to avoid excessive autosize computations
Size = Path.Size;
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
var lastSnakedStart = SnakedStart ?? 0;
var lastSnakedEnd = SnakedEnd ?? 0;
SnakedStart = null;
SnakedEnd = null;
setRange(lastSnakedStart, lastSnakedEnd);
}
private void setRange(double p0, double p1)
{
if (p0 > p1)

View File

@ -64,6 +64,9 @@ namespace osu.Game.Rulesets.Osu.Objects
Curve.ControlPoints = value;
ControlPointsChanged?.Invoke(value);
if (TailCircle != null)
TailCircle.Position = EndPosition;
}
}

View File

@ -124,10 +124,33 @@ namespace osu.Game.Rulesets.Objects
}
}
public void Calculate()
private void calculateCumulativeLength()
{
double l = 0;
cumulativeLength.Clear();
cumulativeLength.Add(l);
for (int i = 0; i < calculatedPath.Count - 1; ++i)
{
Vector2 diff = calculatedPath[i + 1] - calculatedPath[i];
double d = diff.Length;
l += d;
cumulativeLength.Add(l);
}
Distance = l;
}
public void Calculate(bool updateDistance = false)
{
calculatePath();
calculateCumulativeLengthAndTrimPath();
if (!updateDistance)
calculateCumulativeLengthAndTrimPath();
else
calculateCumulativeLength();
}
private int indexOfDistance(double d)