diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs index dae6dc7b4bd1..894f08e5b27e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs @@ -147,6 +147,16 @@ public void TestMaxValueHiddenOnModeChange() AddAssert("Assert max judgement hidden", () => counterDisplay.CounterFlow.ChildrenOfType().First().Alpha == 0); } + [Test] + public void TestNoDuplicates() + { + AddStep("create counter", () => Child = counterDisplay = new TestJudgementCounterDisplay()); + AddStep("Show all judgements", () => counterDisplay.Mode.Value = JudgementCounterDisplay.DisplayMode.All); + AddAssert("Check no duplicates", + () => counterDisplay.CounterFlow.ChildrenOfType().Count(), + () => Is.EqualTo(counterDisplay.CounterFlow.ChildrenOfType().Select(c => c.ResultName.Text).Distinct().Count())); + } + [Test] public void TestCycleDisplayModes() { @@ -163,7 +173,7 @@ public void TestCycleDisplayModes() private int hiddenCount() { - var num = counterDisplay.CounterFlow.Children.First(child => child.Result.Type == HitResult.LargeTickHit); + var num = counterDisplay.CounterFlow.Children.First(child => child.Result.Types.Contains(HitResult.LargeTickHit)); return num.Result.ResultCount.Value; } diff --git a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCountController.cs b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCountController.cs index 43c2ae442aee..8134c97bac3b 100644 --- a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCountController.cs +++ b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCountController.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Localisation; using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -21,18 +22,30 @@ public partial class JudgementCountController : Component [Resolved] private ScoreProcessor scoreProcessor { get; set; } = null!; - public List Results = new List(); + private readonly Dictionary results = new Dictionary(); + + public IEnumerable Counters => counters; + + private readonly List counters = new List(); [BackgroundDependencyLoader] private void load(IBindable ruleset) { - foreach (var result in ruleset.Value.CreateInstance().GetHitResults()) + // Due to weirdness in judgements, some results have the same name and should be aggregated for display purposes. + // There's only one case of this right now ("slider end"). + foreach (var group in ruleset.Value.CreateInstance().GetHitResults().GroupBy(r => r.displayName)) { - Results.Add(new JudgementCount + var judgementCount = new JudgementCount { - Type = result.result, + DisplayName = group.Key, + Types = group.Select(r => r.result).ToArray(), ResultCount = new BindableInt() - }); + }; + + counters.Add(judgementCount); + + foreach (var r in group) + results[r.result] = judgementCount; } } @@ -46,13 +59,20 @@ protected override void LoadComplete() private void updateCount(JudgementResult judgement, bool revert) { - foreach (JudgementCount result in Results.Where(result => result.Type == judgement.Type)) - result.ResultCount.Value = revert ? result.ResultCount.Value - 1 : result.ResultCount.Value + 1; + if (!results.TryGetValue(judgement.Type, out var count)) + return; + + if (revert) + count.ResultCount.Value--; + else + count.ResultCount.Value++; } public struct JudgementCount { - public HitResult Type { get; set; } + public LocalisableString DisplayName { get; set; } + + public HitResult[] Types { get; set; } public BindableInt ResultCount { get; set; } } diff --git a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounter.cs b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounter.cs index 6c417faac245..45ed8d749bda 100644 --- a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounter.cs +++ b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounter.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.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -44,14 +45,14 @@ private void load(OsuColour colours, IBindable ruleset) { Alpha = 0, Font = OsuFont.Numeric.With(size: 8), - Text = ruleset.Value.CreateInstance().GetDisplayNameForHitResult(Result.Type) + Text = Result.DisplayName, } } }; - var result = Result.Type; + var result = Result.Types.First(); - Colour = result.IsBasic() ? colours.ForHitResult(Result.Type) : !result.IsBonus() ? colours.PurpleLight : colours.PurpleLighter; + Colour = result.IsBasic() ? colours.ForHitResult(result) : !result.IsBonus() ? colours.PurpleLight : colours.PurpleLighter; } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounterDisplay.cs b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounterDisplay.cs index 128897dddeaf..326be552221a 100644 --- a/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounterDisplay.cs +++ b/osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounterDisplay.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -49,7 +50,7 @@ private void load() AutoSizeAxes = Axes.Both }; - foreach (var result in judgementCountController.Results) + foreach (var result in judgementCountController.Counters) CounterFlow.Add(createCounter(result)); } @@ -88,7 +89,9 @@ bool shouldShow(int index, JudgementCounter counter) if (index == 0 && !ShowMaxJudgement.Value) return false; - if (counter.Result.Type.IsBasic()) + var hitResult = counter.Result.Types.First(); + + if (hitResult.IsBasic()) return true; switch (Mode.Value) @@ -97,7 +100,7 @@ bool shouldShow(int index, JudgementCounter counter) return false; case DisplayMode.Normal: - return !counter.Result.Type.IsBonus(); + return !hitResult.IsBonus(); case DisplayMode.All: return true;