From 7566fcf536df736934fbe258abd433106a660af7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Jan 2019 10:57:14 +0900 Subject: [PATCH] Slider press fix --- .../Objects/Drawables/DrawableHitCircle.cs | 4 +++ .../Objects/Drawables/DrawableSlider.cs | 1 + .../Objects/Drawables/Pieces/CirclePiece.cs | 10 +++++- .../Objects/Drawables/Pieces/SliderBall.cs | 31 +++++++++++++++---- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 18c28deb9d..e909216508 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); + public OsuAction? HitAction => circle.HitAction; + private readonly Container explodeContainer; private readonly Container scaleContainer; @@ -150,6 +152,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); + circle.HitAction = null; + // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 89521736c7..b55ec10d1d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { + GetInitialHitAction = () => HeadCircle.HitAction, BypassAutoSizeAxes = Axes.Both, Scale = new Vector2(s.Scale), AlwaysPresent = true, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index b7e2748ca9..786cac7198 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Func Hit; + public OsuAction? HitAction; + public CirclePiece() { Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); @@ -35,7 +37,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { case OsuAction.LeftButton: case OsuAction.RightButton: - return IsHovered && (Hit?.Invoke() ?? false); + if (IsHovered && (Hit?.Invoke() ?? false)) + { + HitAction = action; + return true; + } + + break; } return false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index db9fee242a..93c655797a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -1,6 +1,7 @@ // 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 System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private Color4 accentColour = Color4.Black; + public Func GetInitialHitAction; + /// /// The colour that is used for the slider ball. /// @@ -145,19 +148,35 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime; + private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime && lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value); + + /// + /// The point in time up to which we need to include the key which was used to press the head circle in tracking conditions. + /// + private double? initialHitConditionDismissed; protected override void Update() { base.Update(); - if (Time.Current < slider.EndTime) + var initialHitAction = GetInitialHitAction(); + + if (initialHitAction == null) + initialHitConditionDismissed = null; + + if (canCurrentlyTrack) { + var pressed = drawableSlider?.OsuActionInputManager?.PressedActions; + + if (initialHitConditionDismissed == null && !pressed.Contains(initialHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton)) + initialHitConditionDismissed = Time.Current; + // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = canCurrentlyTrack - && lastScreenSpaceMousePosition.HasValue - && ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) - && (drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + Tracking = drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => !initialHitConditionDismissed.HasValue || initialHitConditionDismissed.Value < Time.Current ? x == OsuAction.LeftButton || x == OsuAction.RightButton : x == initialHitAction) ?? false; + } + else + { + Tracking = false; } }