diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
index 3751ff0975..f5bcecccdf 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking
{
- private readonly Slider slider;
+ private readonly SliderTailCircle tailCircle;
///
/// The judgement text is provided by the .
@@ -29,10 +29,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly Container scaleContainer;
- public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle)
- : base(hitCircle)
+ public DrawableSliderTail(Slider slider, SliderTailCircle tailCircle)
+ : base(tailCircle)
{
- this.slider = slider;
+ this.tailCircle = tailCircle;
Origin = Anchor.Centre;
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
@@ -98,9 +98,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ApplyResult(r => r.Type = Tracking ? r.Judgement.MaxResult : r.Judgement.MinResult);
}
- public void UpdateSnakingPosition(Vector2 start, Vector2 end)
- {
- Position = end;
- }
+ public void UpdateSnakingPosition(Vector2 start, Vector2 end) =>
+ Position = tailCircle.RepeatIndex % 2 == 0 ? end : start;
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs
index 51f6a44a87..9cc3f17c55 100644
--- a/osu.Game.Rulesets.Osu/Objects/Slider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs
@@ -174,8 +174,10 @@ namespace osu.Game.Rulesets.Osu.Objects
// we need to use the LegacyLastTick here for compatibility reasons (difficulty).
// it is *okay* to use this because the TailCircle is not used for any meaningful purpose in gameplay.
// if this is to change, we should revisit this.
- AddNested(TailCircle = new SliderTailCircle(this)
+ AddNested(TailCircle = new SliderTailCircle
{
+ RepeatIndex = e.SpanIndex,
+ SpanDuration = SpanDuration,
StartTime = e.Time,
Position = EndPosition,
StackHeight = StackHeight
diff --git a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs
index d9ae520f5c..a34eec0c79 100644
--- a/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SliderEndCircle.cs
@@ -1,9 +1,34 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.ControlPoints;
+using osu.Game.Rulesets.Scoring;
+
namespace osu.Game.Rulesets.Osu.Objects
{
- public class SliderEndCircle : HitCircle
+ ///
+ /// A hitcircle which is at the end of a slider path (either repeat or final tail).
+ ///
+ public abstract class SliderEndCircle : HitCircle
{
+ public int RepeatIndex { get; set; }
+ public double SpanDuration { get; set; }
+
+ protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
+ {
+ base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
+
+ // Out preempt should be one span early to give the user ample warning.
+ TimePreempt += SpanDuration;
+
+ // We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders
+ // we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time.
+ if (RepeatIndex > 0)
+ TimePreempt = Math.Min(SpanDuration * 2, TimePreempt);
+ }
+
+ protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs
index b6c58a75d1..6bf0ec0355 100644
--- a/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SliderRepeat.cs
@@ -1,35 +1,14 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
-using osu.Game.Beatmaps;
-using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects
{
- public class SliderRepeat : OsuHitObject
+ public class SliderRepeat : SliderEndCircle
{
- public int RepeatIndex { get; set; }
- public double SpanDuration { get; set; }
-
- protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
- {
- base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
-
- // Out preempt should be one span early to give the user ample warning.
- TimePreempt += SpanDuration;
-
- // We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders
- // we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time.
- if (RepeatIndex > 0)
- TimePreempt = Math.Min(SpanDuration * 2, TimePreempt);
- }
-
- protected override HitWindows CreateHitWindows() => HitWindows.Empty;
-
public override Judgement CreateJudgement() => new SliderRepeatJudgement();
public class SliderRepeatJudgement : OsuJudgement
diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
index aff3f38e17..2f1bfdfcc0 100644
--- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using osu.Framework.Bindables;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
@@ -13,18 +12,8 @@ namespace osu.Game.Rulesets.Osu.Objects
/// Note that this should not be used for timing correctness.
/// See usage in for more information.
///
- public class SliderTailCircle : SliderCircle
+ public class SliderTailCircle : SliderEndCircle
{
- private readonly IBindable pathVersion = new Bindable();
-
- public SliderTailCircle(Slider slider)
- {
- pathVersion.BindTo(slider.Path.Version);
- pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
- }
-
- protected override HitWindows CreateHitWindows() => HitWindows.Empty;
-
public override Judgement CreateJudgement() => new SliderTailJudgement();
public class SliderTailJudgement : OsuJudgement