diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index dcc25a997a..68c5ec0a45 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -38,7 +38,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Colour = AccentColour, Hit = () => { - if (Judgement.Result.HasValue) return false; + if (Judgement.Result != HitResult.None) return false; Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value UpdateJudgement(true); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs index 1e270c6751..5217fd9085 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -47,7 +47,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - return !Judgement.Result.HasValue && UpdateJudgement(true); + return Judgement.Result == HitResult.None && UpdateJudgement(true); } } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index ae328fe9ca..c8a7355e3c 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -68,7 +68,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - if (Judgement.Result.HasValue) + if (Judgement.Result != HitResult.None) return false; validKeyPressed = HitKeys.Contains(key); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs index 5e225e1dce..a77fd1d6be 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs @@ -5,6 +5,7 @@ using OpenTK.Input; using System; using System.Linq; using osu.Framework.Input; +using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -27,7 +28,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void CheckJudgement(bool userTriggered) { - if (!Judgement.Result.HasValue) + if (Judgement.Result == HitResult.None) { base.CheckJudgement(userTriggered); return; @@ -45,7 +46,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { // Check if we've handled the first key - if (!Judgement.Result.HasValue) + if (Judgement.Result == HitResult.None) { // First key hasn't been handled yet, attempt to handle it bool handled = base.HandleKeyPress(key); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 15584ac73f..22fa4dea6f 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -64,7 +64,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - if (Judgement.Result.HasValue) + if (Judgement.Result != HitResult.None) return false; UpdateJudgement(true); diff --git a/osu.Game/Modes/Judgements/IPartialJudgement.cs b/osu.Game/Modes/Judgements/IPartialJudgement.cs new file mode 100644 index 0000000000..2ca1ffce4d --- /dev/null +++ b/osu.Game/Modes/Judgements/IPartialJudgement.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Scoring; + +namespace osu.Game.Modes.Judgements +{ + /// + /// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change. + /// + /// This judgement will be continually processed by + /// unless the result is a miss and will trigger a full re-process of the when changed. + /// + /// + public interface IPartialJudgement + { + /// + /// Indicates that this partial judgement has changed and requires a full re-process of the . + /// + /// This is set to false once the judgement has been re-processed. + /// + /// + bool Changed { get; set; } + } +} diff --git a/osu.Game/Modes/Judgements/Judgement.cs b/osu.Game/Modes/Judgements/Judgement.cs index d916fc15de..5b1e4ddac6 100644 --- a/osu.Game/Modes/Judgements/Judgement.cs +++ b/osu.Game/Modes/Judgements/Judgement.cs @@ -10,7 +10,7 @@ namespace osu.Game.Modes.Judgements /// /// Whether this judgement is the result of a hit or a miss. /// - public HitResult? Result; + public HitResult Result; /// /// The offset at which this judgement occurred. diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 3998a3e385..2939980ac6 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -93,16 +93,26 @@ namespace osu.Game.Modes.Objects.Drawables /// Whether a hit was processed. protected bool UpdateJudgement(bool userTriggered) { - if (Judgement.Result != null) + IPartialJudgement partial = Judgement as IPartialJudgement; + + // Never re-process non-partial hits, or partial judgements that were previously judged as misses + if (Judgement.Result != HitResult.None && (partial == null || Judgement.Result == HitResult.Miss)) return false; + // Update the judgement state double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - Judgement.TimeOffset = Time.Current - endTime; + // Update the judgement state + bool hadResult = Judgement.Result != HitResult.None; CheckJudgement(userTriggered); - if (Judgement.Result == null) + // Don't process judgements with no result + if (Judgement.Result == HitResult.None) + return false; + + // Don't process judgements that previously had results but the results were unchanged + if (hadResult && partial?.Changed != true) return false; switch (Judgement.Result) @@ -117,6 +127,9 @@ namespace osu.Game.Modes.Objects.Drawables OnJudgement?.Invoke(this); + if (partial != null) + partial.Changed = false; + return true; } diff --git a/osu.Game/Modes/Objects/Drawables/HitResult.cs b/osu.Game/Modes/Objects/Drawables/HitResult.cs index 1bbf9269bb..e036610ae2 100644 --- a/osu.Game/Modes/Objects/Drawables/HitResult.cs +++ b/osu.Game/Modes/Objects/Drawables/HitResult.cs @@ -7,8 +7,19 @@ namespace osu.Game.Modes.Objects.Drawables { public enum HitResult { + /// + /// Indicates that the object has not been judged yet. + /// + [Description("")] + None, + /// + /// Indicates that the object has been judged as a miss. + /// [Description(@"Miss")] Miss, + /// + /// Indicates that the object has been judged as a hit. + /// [Description(@"Hit")] Hit, } diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 3d108b895d..1681da2ba9 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -149,7 +149,7 @@ namespace osu.Game.Modes.UI public event Action OnJudgement; protected override Container Content => content; - protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result.HasValue); + protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None); /// /// The playfield. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a5bdf1df69..fcb45f91fd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -97,6 +97,7 @@ +