diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index af2a889f03..6a0457efc6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -111,6 +111,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; } + protected void BeginHold() + { + holdStartTime = Time.Current; + bodyPiece.Hitting = true; + } + + protected void EndHold() + { + holdStartTime = null; + bodyPiece.Hitting = false; + } + public bool OnPressed(ManiaAction action) { // Make sure the action happened within the body of the hold note @@ -123,8 +135,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // The user has pressed during the body of the hold note, after the head note and its hit windows have passed // and within the limited range of the above if-statement. This state will be managed by the head note if the // user has pressed during the hit windows of the head note. - holdStartTime = Time.Current; - + BeginHold(); return true; } @@ -137,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (action != Action.Value) return false; - holdStartTime = null; + EndHold(); // If the key has been released too early, the user should not receive full score for the release if (!Tail.IsHit) @@ -170,7 +181,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held // The body doesn't handle these early early hits, so we have to explicitly set the holding state here - holdNote.holdStartTime = Time.Current; + holdNote.BeginHold(); return true; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 4ab2da208a..619fe06c73 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces background = new Box { RelativeSizeAxes = Axes.Both }, foreground = new BufferedContainer { + Blending = BlendingMode.Additive, RelativeSizeAxes = Axes.Both, CacheDrawnFrameBuffer = true, Children = new Drawable[] @@ -73,6 +74,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } private Color4 accentColour; + public Color4 AccentColour { get { return accentColour; } @@ -86,6 +88,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } } + public bool Hitting + { + get { return hitting; } + set + { + hitting = value; + updateAccentColour(); + } + } + private Cached subtractionCache = new Cached(); public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) @@ -118,13 +130,26 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } } + private bool hitting; + private void updateAccentColour() { if (!IsLoaded) return; - foreground.Colour = AccentColour.Opacity(0.9f); - background.Colour = AccentColour.Opacity(0.6f); + foreground.Colour = AccentColour.Opacity(0.5f); + background.Colour = AccentColour.Opacity(0.7f); + + const float animation_length = 50; + + foreground.ClearTransforms(false, nameof(foreground.Colour)); + if (hitting) + { + // wait for the next sync point + double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2); + using (foreground.BeginDelayedSequence(synchronisedOffset)) + foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(foreground.Colour, animation_length).Loop(); + } subtractionCache.Invalidate(); }