From a1efd25ac19298f7cb5efb4f29c94a6fa088b84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 3 Dec 2016 13:25:31 +0100 Subject: [PATCH] Improve code clarity and allow snaking "away" the beginning of the slider that has already been tracked. --- osu-framework | 2 +- .../Objects/Drawables/DrawableSlider.cs | 50 +++++++++++-------- osu.Game.Mode.Osu/Objects/SliderCurve.cs | 29 +++++++++-- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/osu-framework b/osu-framework index 7ca1719b5c..3d9bf09831 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 7ca1719b5cdc8b0a9600abe6472b38a426abedb0 +Subproject commit 3d9bf098319583fc4fbbab5117702d000ad4fb9b diff --git a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs index 57f8d6055e..b5b4ea0541 100644 --- a/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Mode.Osu/Objects/Drawables/DrawableSlider.cs @@ -63,16 +63,21 @@ namespace osu.Game.Modes.Osu.Objects.Drawables ball.Alpha = Time.Current >= slider.StartTime && Time.Current <= slider.EndTime ? 1 : 0; - double t = (Time.Current - slider.StartTime) / slider.Duration; - if (slider.RepeatCount > 1) - { - int currentRepeat = (int)(t * slider.RepeatCount); - t = (t * slider.RepeatCount) % 1; - if (currentRepeat % 2 == 1) - t = 1 - t; - } + double currentProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); + double drawStartProgress = 0; - ball.Position = slider.Curve.PositionAt(t); + int currentRepeat = (int)(currentProgress * slider.RepeatCount); + currentProgress = (currentProgress * slider.RepeatCount) % 1; + if (currentRepeat % 2 == 1) + currentProgress = 1 - currentProgress; + + if (currentRepeat >= slider.RepeatCount - 1) + drawStartProgress = currentProgress; + + ball.Position = slider.Curve.PositionAt(currentProgress); + + double drawEndProgress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + body.SetRange(drawStartProgress, drawEndProgress); } protected override void CheckJudgement(bool userTriggered) @@ -187,7 +192,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private Path path; private BufferedContainer container; - private double? drawnProgress; + private double drawnProgressStart; + private double drawnProgressEnd; private Slider slider; public Body(Slider s) @@ -227,33 +233,37 @@ namespace osu.Game.Modes.Osu.Objects.Drawables path.PathWidth = 32; } - protected override void Update() + public void SetRange(double p0, double p1) { - base.Update(); + if (p0 > p1) + MathHelper.Swap(ref p0, ref p1); - if (updateSnaking()) + if (updateSnaking(p0, p1)) { // Autosizing does not give us the desired behaviour here. // We want the container to have the same size as the slider, // and to be positioned such that the slider head is at (0,0). container.Size = path.Size; - container.Position = -path.HeadPosition; + container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]); container.ForceRedraw(); } } - private bool updateSnaking() + private List currentCurve = new List(); + private bool updateSnaking(double p0, double p1) { - double progress = MathHelper.Clamp((Time.Current - slider.StartTime + TIME_PREEMPT) / TIME_FADEIN, 0, 1); + if (drawnProgressStart == p0 && drawnProgressEnd == p1) return false; - if (progress == drawnProgress) return false; - drawnProgress = progress; + drawnProgressStart = p0; + drawnProgressEnd = p1; - Vector2 startPosition = slider.Curve.PositionAt(0); + slider.Curve.GetPathToProgress(currentCurve, p0, p1); path.ClearVertices(); - slider.Curve.FillCurveUntilProgress(p => path.AddVertex(p - startPosition), progress); + foreach (Vector2 p in currentCurve) + path.AddVertex(p - currentCurve[0]); + return true; } } diff --git a/osu.Game.Mode.Osu/Objects/SliderCurve.cs b/osu.Game.Mode.Osu/Objects/SliderCurve.cs index 8faccc1516..92d5650403 100644 --- a/osu.Game.Mode.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Mode.Osu/Objects/SliderCurve.cs @@ -102,17 +102,36 @@ namespace osu.Game.Modes.Osu.Objects return p0 + (p1 - p0) * (float)w; } - public void FillCurveUntilProgress(Action action, double progress) + /// + /// Computes the slider curve until a given progress that ranges from 0 (beginning of the slider) + /// to 1 (end of the slider) and stores the generated path in the given list. + /// + /// The list to be filled with the computed curve. + /// Ranges from 0 (beginning of the slider) to 1 (end of the slider). + public void GetPathToProgress(List path, double p0, double p1) { - double d = progressToDistance(progress); + double d0 = progressToDistance(p0); + double d1 = progressToDistance(p1); + + path.Clear(); int i = 0; - for (; i < calculatedPath.Count && cumulativeLength[i] <= d; ++i) - action.Invoke(calculatedPath[i]); + for (; i < calculatedPath.Count && cumulativeLength[i] < d0; ++i); - action.Invoke(interpolateVertices(i, d)); + path.Add(interpolateVertices(i, d0)); + + for (; i < calculatedPath.Count && cumulativeLength[i] <= d1; ++i) + path.Add(calculatedPath[i]); + + path.Add(interpolateVertices(i, d1)); } + /// + /// Computes the position on the slider at a given progress that ranges from 0 (beginning of the slider) + /// to 1 (end of the slider). + /// + /// Ranges from 0 (beginning of the slider) to 1 (end of the slider). + /// public Vector2 PositionAt(double progress) { double d = progressToDistance(progress);