1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-13 17:27:48 +08:00

Block input to objects lying under already-hit hitcircles when classic note lock is active

This commit is contained in:
Bartłomiej Dach 2023-09-04 11:38:19 +02:00
parent 40d1196aea
commit 03c61a573e
No known key found for this signature in database
3 changed files with 26 additions and 1 deletions

View File

@ -549,6 +549,8 @@ namespace osu.Game.Rulesets.Osu.Tests
addJudgementOffsetAssert("first slider head", () => ((Slider)hitObjects[0]).HeadCircle, 0); addJudgementOffsetAssert("first slider head", () => ((Slider)hitObjects[0]).HeadCircle, 0);
addJudgementAssert(hitObjects[1], HitResult.Miss); addJudgementAssert(hitObjects[1], HitResult.Miss);
// the slider head of the first slider prevents the second slider's head from being hit, so the judgement offset should be very late. // the slider head of the first slider prevents the second slider's head from being hit, so the judgement offset should be very late.
// this is not strictly done by the hit policy implementation itself (see `OsuModClassic.blockInputToUnderlyingObjects()`),
// but we're testing this here anyways to just keep everything related to input handling and note lock in one place.
addJudgementOffsetAssert("second slider head", () => ((Slider)hitObjects[1]).HeadCircle, referenceHitWindows.WindowFor(HitResult.Meh)); addJudgementOffsetAssert("second slider head", () => ((Slider)hitObjects[1]).HeadCircle, referenceHitWindows.WindowFor(HitResult.Meh));
addClickActionAssert(0, ClickAction.Hit); addClickActionAssert(0, ClickAction.Hit);
} }

View File

@ -74,6 +74,10 @@ namespace osu.Game.Rulesets.Osu.Mods
head.TrackFollowCircle = !NoSliderHeadMovement.Value; head.TrackFollowCircle = !NoSliderHeadMovement.Value;
if (FadeHitCircleEarly.Value && !usingHiddenFading) if (FadeHitCircleEarly.Value && !usingHiddenFading)
applyEarlyFading(head); applyEarlyFading(head);
if (ClassicNoteLock.Value)
blockInputToUnderlyingObjects(head);
break; break;
case DrawableSliderTail tail: case DrawableSliderTail tail:
@ -83,10 +87,29 @@ namespace osu.Game.Rulesets.Osu.Mods
case DrawableHitCircle circle: case DrawableHitCircle circle:
if (FadeHitCircleEarly.Value && !usingHiddenFading) if (FadeHitCircleEarly.Value && !usingHiddenFading)
applyEarlyFading(circle); applyEarlyFading(circle);
if (ClassicNoteLock.Value)
blockInputToUnderlyingObjects(circle);
break; break;
} }
} }
/// <summary>
/// On stable, hitcircles that have already been hit block input from reaching objects that may be underneath them.
/// The purpose of this method is to restore that behaviour.
/// In order to avoid introducing yet another confusing config option, this behaviour is roped into the general notion of "note lock".
/// </summary>
private static void blockInputToUnderlyingObjects(DrawableHitCircle circle)
{
var oldHitAction = circle.HitArea.Hit;
circle.HitArea.Hit = () =>
{
oldHitAction?.Invoke();
return true;
};
}
private void applyEarlyFading(DrawableHitCircle circle) private void applyEarlyFading(DrawableHitCircle circle)
{ {
circle.ApplyCustomUpdateState += (dho, state) => circle.ApplyCustomUpdateState += (dho, state) =>

View File

@ -261,7 +261,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
case OsuAction.RightButton: case OsuAction.RightButton:
if (IsHovered && (Hit?.Invoke() ?? false)) if (IsHovered && (Hit?.Invoke() ?? false))
{ {
HitAction = e.Action; HitAction ??= e.Action;
return true; return true;
} }