diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
index 264a1bd5ec..25d0573a82 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
@@ -69,8 +69,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
///
private double? releaseTime;
- public override double MaximumJudgementOffset => Tail.MaximumJudgementOffset;
-
public DrawableHoldNote()
: this(null)
{
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
index bf477277c6..20ea962994 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTail.cs
@@ -15,13 +15,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
///
public partial class DrawableHoldNoteTail : DrawableNote
{
- ///
- /// Lenience of release hit windows. This is to make cases where the hold note release
- /// is timed alongside presses of other hit objects less awkward.
- /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps
- ///
- private const double release_window_lenience = 1.5;
-
protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteTail;
protected DrawableHoldNote HoldNote => (DrawableHoldNote)ParentHitObject;
@@ -40,14 +33,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
public void UpdateResult() => base.UpdateResult(true);
- public override double MaximumJudgementOffset => base.MaximumJudgementOffset * release_window_lenience;
-
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
Debug.Assert(HitObject.HitWindows != null);
// Factor in the release lenience
- timeOffset /= release_window_lenience;
+ timeOffset /= TailNote.RELEASE_WINDOW_LENIENCE;
if (!userTriggered)
{
diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
index 22fab15c1b..c367886efe 100644
--- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs
@@ -81,6 +81,8 @@ namespace osu.Game.Rulesets.Mania.Objects
///
public TailNote Tail { get; private set; }
+ public override double MaximumJudgementOffset => Tail.MaximumJudgementOffset;
+
///
/// The time between ticks of this hold.
///
diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs
index cda8e2fa31..d6dc25079a 100644
--- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs
@@ -10,6 +10,15 @@ namespace osu.Game.Rulesets.Mania.Objects
{
public class TailNote : Note
{
+ ///
+ /// Lenience of release hit windows. This is to make cases where the hold note release
+ /// is timed alongside presses of other hit objects less awkward.
+ /// Todo: This shouldn't exist for non-LegacyBeatmapDecoder beatmaps
+ ///
+ public const double RELEASE_WINDOW_LENIENCE = 1.5;
+
public override Judgement CreateJudgement() => new ManiaJudgement();
+
+ public override double MaximumJudgementOffset => base.MaximumJudgementOffset * RELEASE_WINDOW_LENIENCE;
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
index b9ce07363c..34253e3d4f 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
@@ -25,8 +25,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Origin = Anchor.Centre;
}
- public override double MaximumJudgementOffset => DrawableSpinner.HitObject.Duration;
-
///
/// Apply a judgement result.
///
diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs
index 0e1fe56cea..ed6f8a9a6a 100644
--- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs
@@ -71,8 +71,8 @@ namespace osu.Game.Rulesets.Osu.Objects
double startTime = StartTime + (float)(i + 1) / totalSpins * Duration;
AddNested(i < SpinsRequired
- ? new SpinnerTick { StartTime = startTime }
- : new SpinnerBonusTick { StartTime = startTime });
+ ? new SpinnerTick { StartTime = startTime, SpinnerDuration = Duration }
+ : new SpinnerBonusTick { StartTime = startTime, SpinnerDuration = Duration });
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs
index 650d02c675..c890f3771b 100644
--- a/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/SpinnerTick.cs
@@ -11,10 +11,17 @@ namespace osu.Game.Rulesets.Osu.Objects
{
public class SpinnerTick : OsuHitObject
{
+ ///
+ /// Duration of the containing this spinner tick.
+ ///
+ public double SpinnerDuration { get; set; }
+
public override Judgement CreateJudgement() => new OsuSpinnerTickJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
+ public override double MaximumJudgementOffset => SpinnerDuration;
+
public class OsuSpinnerTickJudgement : OsuJudgement
{
public override HitResult MaxResult => HitResult.SmallBonus;
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
index 45e25ee7dc..abecd19545 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
@@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected override SkinnableDrawable CreateMainPiece() => new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.DrumRollTick), _ => new TickPiece());
- public override double MaximumJudgementOffset => HitObject.HitWindow;
-
protected override void OnApply()
{
base.OnApply();
diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs
index 433fdab908..6bcb8674e6 100644
--- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs
@@ -31,6 +31,8 @@ namespace osu.Game.Rulesets.Taiko.Objects
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
+ public override double MaximumJudgementOffset => HitWindow;
+
protected override StrongNestedHitObject CreateStrongNestedHit(double startTime) => new StrongNestedHit { StartTime = startTime };
public class StrongNestedHit : StrongNestedHitObject
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 39f0888882..40b51ddcca 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -650,18 +650,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
UpdateResult(false);
}
- ///
- /// The maximum offset from the end time of at which this can be judged.
- /// The time offset of will be clamped to this value during .
- ///
- /// Defaults to the miss window of .
- ///
- ///
- ///
- /// This does not affect the time offset provided to invocations of .
- ///
- public virtual double MaximumJudgementOffset => HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? 0;
-
///
/// Applies the of this , notifying responders such as
/// the of the .
@@ -683,7 +671,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
$"{GetType().ReadableName()} applied an invalid hit result (was: {Result.Type}, expected: [{Result.Judgement.MinResult} ... {Result.Judgement.MaxResult}]).");
}
- Result.TimeOffset = Math.Min(MaximumJudgementOffset, Time.Current - HitObject.GetEndTime());
+ Result.TimeOffset = Math.Min(HitObject.MaximumJudgementOffset, Time.Current - HitObject.GetEndTime());
if (Result.HasResult)
updateState(Result.IsHit ? ArmedState.Hit : ArmedState.Miss);
diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs
index 0f79e58201..25f538d211 100644
--- a/osu.Game/Rulesets/Objects/HitObject.cs
+++ b/osu.Game/Rulesets/Objects/HitObject.cs
@@ -200,6 +200,14 @@ namespace osu.Game.Rulesets.Objects
[NotNull]
protected virtual HitWindows CreateHitWindows() => new HitWindows();
+ ///
+ /// The maximum offset from the end time of at which this can be judged.
+ ///
+ /// Defaults to the miss window.
+ ///
+ ///
+ public virtual double MaximumJudgementOffset => HitWindows?.WindowFor(HitResult.Miss) ?? 0;
+
public IList CreateSlidingSamples()
{
var slidingSamples = new List();
diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
index 3559a1521c..b93a427196 100644
--- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
+++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs
@@ -232,8 +232,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
double computedStartTime = computeDisplayStartTime(entry);
// always load the hitobject before its first judgement offset
- double judgementOffset = entry.HitObject.HitWindows?.WindowFor(Scoring.HitResult.Miss) ?? 0;
- entry.LifetimeStart = Math.Min(entry.HitObject.StartTime - judgementOffset, computedStartTime);
+ entry.LifetimeStart = Math.Min(entry.HitObject.StartTime - entry.HitObject.MaximumJudgementOffset, computedStartTime);
}
private void updateLayoutRecursive(DrawableHitObject hitObject, double? parentHitObjectStartTime = null)