diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs
index 3a35fd4433..e3b2501cdc 100644
--- a/osu.Game/Rulesets/Judgements/JudgementResult.cs
+++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs
@@ -36,6 +36,12 @@ namespace osu.Game.Rulesets.Judgements
///
public double TimeOffset { get; internal set; }
+ ///
+ /// The absolute time at which this occurred.
+ /// Equal to the (end) time of the + .
+ ///
+ public double TimeAbsolute => HitObject.GetEndTime() + TimeOffset;
+
///
/// The combo prior to this occurring.
///
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 1ef6c8c207..5939443cf1 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -255,18 +255,19 @@ namespace osu.Game.Rulesets.Objects.Drawables
base.ClearTransformsAfter(double.MinValue, true);
using (BeginAbsoluteSequence(transformTime, true))
- {
UpdateInitialTransforms();
- var judgementOffset = Result?.TimeOffset ?? 0;
+ using (BeginAbsoluteSequence(StateUpdateTime, true))
+ UpdateStateTransforms(newState);
- using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true))
- {
- UpdateStateTransforms(newState);
- state.Value = newState;
- }
+ if (newState != ArmedState.Idle)
+ {
+ using (BeginAbsoluteSequence(HitStateUpdateTime, true))
+ UpdateHitStateTransforms(newState);
}
+ state.Value = newState;
+
if (LifetimeEnd == double.MaxValue && (state.Value != ArmedState.Idle || HitObject.HitWindows == null))
Expire();
@@ -301,6 +302,16 @@ namespace osu.Game.Rulesets.Objects.Drawables
{
}
+ ///
+ /// Apply transforms based on the current . This call is offset by (HitObject.EndTime + Result.Offset), equivalent to when the user hit the object.
+ /// This method is only called on or .
+ /// Previous states are automatically cleared.
+ ///
+ /// The new armed state.
+ protected virtual void UpdateHitStateTransforms(ArmedState state)
+ {
+ }
+
public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null)
{
// Parent calls to this should be blocked for safety, as we are manually handling this in updateState.
@@ -454,6 +465,18 @@ namespace osu.Game.Rulesets.Objects.Drawables
///
protected virtual double InitialLifetimeOffset => 10000;
+ ///
+ /// The time at which state transforms should be applied that line up to 's StartTime.
+ /// This is used to offset calls to .
+ ///
+ public double StateUpdateTime => HitObject.StartTime;
+
+ ///
+ /// The time at which judgement dependent state transforms should be applied. This is equivalent of the (end) time of the object, in addition to any judgement offset.
+ /// This is used to offset calls to .
+ ///
+ public double HitStateUpdateTime => Result?.TimeAbsolute ?? HitObject.GetEndTime();
+
///
/// Will be called at least once after this has become not alive.
///