diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index d28b7bdf58..2b75bcdc3d 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -12,12 +12,6 @@ namespace osu.Game.Rulesets.Mania.Judgements { switch (result) { - case HitResult.LargeTickHit: - return DEFAULT_MAX_HEALTH_INCREASE * 0.1; - - case HitResult.LargeTickMiss: - return -DEFAULT_MAX_HEALTH_INCREASE * 0.1; - case HitResult.Meh: return -DEFAULT_MAX_HEALTH_INCREASE * 0.5; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index b977c07dfb..ff34b69d19 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -385,22 +385,9 @@ namespace osu.Game.Rulesets.Mania HitResult.Good, HitResult.Ok, HitResult.Meh, - - HitResult.LargeTickHit, }; } - public override LocalisableString GetDisplayNameForHitResult(HitResult result) - { - switch (result) - { - case HitResult.LargeTickHit: - return "hold tick"; - } - - return base.GetDisplayNameForHitResult(result); - } - public override StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => new[] { new StatisticItem("Performance Breakdown", () => new PerformanceBreakdownChart(score, playableBeatmap) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs index f117569657..dae6dc7b4b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneJudgementCounter.cs @@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play.HUD.JudgementCounter; @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; }); - protected override Ruleset CreateRuleset() => new ManiaRuleset(); + protected override Ruleset CreateRuleset() => new OsuRuleset(); private void applyOneJudgement(HitResult result) { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs index 2d953fe9ad..b7cf3fef9b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSwitchTiny.cs @@ -2,16 +2,19 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Framework.Utils; using osu.Game.Overlays; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.UI; @@ -34,6 +37,49 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestMania() => createSwitchTestFor(new ManiaRuleset()); + [Test] + public void TestShowRateAdjusts() + { + AddStep("create mod icons", () => + { + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Full, + ChildrenEnumerable = Ruleset.Value.CreateInstance().CreateAllMods() + .OfType() + .SelectMany(m => + { + List icons = new List { new TestModSwitchTiny(m) }; + + for (double i = m.SpeedChange.MinValue; i < m.SpeedChange.MaxValue; i += m.SpeedChange.Precision * 10) + { + m = (ModRateAdjust)m.DeepClone(); + m.SpeedChange.Value = i; + icons.Add(new TestModSwitchTiny(m, true)); + } + + return icons; + }), + }; + }); + + AddStep("adjust rates", () => + { + foreach (var icon in this.ChildrenOfType()) + { + if (icon.Mod is ModRateAdjust rateAdjust) + { + rateAdjust.SpeedChange.Value = RNG.NextDouble() > 0.9 + ? rateAdjust.SpeedChange.Default + : RNG.NextDouble(rateAdjust.SpeedChange.MinValue, rateAdjust.SpeedChange.MaxValue); + } + } + }); + + AddToggleStep("toggle active", active => this.ChildrenOfType().ForEach(s => s.Active.Value = active)); + } + private void createSwitchTestFor(Ruleset ruleset) { AddStep("no colour scheme", () => Child = createContent(ruleset, null)); @@ -43,7 +89,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep($"{scheme} colour scheme", () => Child = createContent(ruleset, scheme)); } - AddToggleStep("toggle active", active => this.ChildrenOfType().ForEach(s => s.Active.Value = active)); + AddToggleStep("toggle active", active => this.ChildrenOfType().ForEach(s => s.Active.Value = active)); } private static Drawable createContent(Ruleset ruleset, OverlayColourScheme? colourScheme) @@ -62,7 +108,7 @@ namespace osu.Game.Tests.Visual.UserInterface AutoSizeAxes = Axes.Y, Direction = FillDirection.Full, Spacing = new Vector2(5), - ChildrenEnumerable = group.Select(mod => new ModSwitchTiny(mod)) + ChildrenEnumerable = group.Select(mod => new TestModSwitchTiny(mod)) }) }; @@ -81,5 +127,15 @@ namespace osu.Game.Tests.Visual.UserInterface return switchFlow; } + + private partial class TestModSwitchTiny : ModSwitchTiny + { + public new IMod Mod => base.Mod; + + public TestModSwitchTiny(IMod mod, bool showExtendedInformation = false) + : base(mod, showExtendedInformation) + { + } + } } } diff --git a/osu.Game/Rulesets/UI/ModSwitchTiny.cs b/osu.Game/Rulesets/UI/ModSwitchTiny.cs index a5cf75bd07..a3e325ace8 100644 --- a/osu.Game/Rulesets/UI/ModSwitchTiny.cs +++ b/osu.Game/Rulesets/UI/ModSwitchTiny.cs @@ -3,15 +3,16 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; +using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Rulesets.Mods; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.UI @@ -21,8 +22,10 @@ namespace osu.Game.Rulesets.UI public BindableBool Active { get; } = new BindableBool(); public const float DEFAULT_HEIGHT = 30; + private const float width = 73; - private readonly IMod mod; + protected readonly IMod Mod; + private readonly bool showExtendedInformation; private readonly Box background; private readonly OsuSpriteText acronymText; @@ -33,33 +36,69 @@ namespace osu.Game.Rulesets.UI private Color4 activeBackgroundColour; private Color4 inactiveBackgroundColour; - public ModSwitchTiny(IMod mod) - { - this.mod = mod; - Size = new Vector2(73, DEFAULT_HEIGHT); + private readonly CircularContainer extendedContent; + private readonly Box extendedBackground; + private readonly OsuSpriteText extendedText; + private ModSettingChangeTracker? modSettingsChangeTracker; - InternalChild = new CircularContainer + public ModSwitchTiny(IMod mod, bool showExtendedInformation = false) + { + Mod = mod; + this.showExtendedInformation = showExtendedInformation; + AutoSizeAxes = Axes.X; + Height = DEFAULT_HEIGHT; + + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] + extendedContent = new CircularContainer { - background = new Box + Name = "extended content", + Width = 100 + DEFAULT_HEIGHT / 2, + RelativeSizeAxes = Axes.Y, + Masking = true, + X = width, + Margin = new MarginPadding { Left = -DEFAULT_HEIGHT }, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both - }, - acronymText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Shadow = false, - Font = OsuFont.Numeric.With(size: 24, weight: FontWeight.Black), - Text = mod.Acronym, - Margin = new MarginPadding + extendedBackground = new Box { - Top = 4 - } + RelativeSizeAxes = Axes.Both, + }, + extendedText = new OsuSpriteText + { + Margin = new MarginPadding { Left = 3 * DEFAULT_HEIGHT / 4 }, + Font = OsuFont.Default.With(size: 30f, weight: FontWeight.Bold), + UseFullGlyphHeight = false, + Text = mod.ExtendedIconInformation, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, } + }, + new CircularContainer + { + Width = width, + RelativeSizeAxes = Axes.Y, + Masking = true, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + acronymText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Shadow = false, + Font = OsuFont.Numeric.With(size: 24, weight: FontWeight.Black), + Text = mod.Acronym, + Margin = new MarginPadding + { + Top = 4 + } + }, + }, } }; } @@ -68,7 +107,7 @@ namespace osu.Game.Rulesets.UI private void load(OsuColour colours, OverlayColourProvider? colourProvider) { inactiveBackgroundColour = colourProvider?.Background5 ?? colours.Gray3; - activeBackgroundColour = colours.ForModType(mod.Type); + activeBackgroundColour = colours.ForModType(Mod.Type); inactiveForegroundColour = colourProvider?.Background2 ?? colours.Gray5; activeForegroundColour = Interpolation.ValueAt(0.1f, Colour4.Black, activeForegroundColour, 0, 1); @@ -80,12 +119,37 @@ namespace osu.Game.Rulesets.UI Active.BindValueChanged(_ => updateState(), true); FinishTransforms(true); + + if (Mod is Mod actualMod) + { + modSettingsChangeTracker = new ModSettingChangeTracker(new[] { actualMod }); + modSettingsChangeTracker.SettingChanged = _ => updateExtendedInformation(); + } + + updateExtendedInformation(); + } + + private void updateExtendedInformation() + { + bool showExtended = showExtendedInformation && !string.IsNullOrEmpty(Mod.ExtendedIconInformation); + + extendedContent.Alpha = showExtended ? 1 : 0; + extendedText.Text = Mod.ExtendedIconInformation; } private void updateState() { acronymText.FadeColour(Active.Value ? activeForegroundColour : inactiveForegroundColour, 200, Easing.OutQuint); background.FadeColour(Active.Value ? activeBackgroundColour : inactiveBackgroundColour, 200, Easing.OutQuint); + + extendedText.Colour = Active.Value ? activeBackgroundColour.Lighten(0.2f) : inactiveBackgroundColour; + extendedBackground.Colour = Active.Value ? activeBackgroundColour.Darken(2.4f) : inactiveBackgroundColour.Darken(2.8f); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + modSettingsChangeTracker?.Dispose(); } } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2efea2105c..8531408555 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -346,7 +346,7 @@ namespace osu.Game.Scoring case HitResult.LargeBonus: case HitResult.SmallBonus: if (MaximumStatistics.TryGetValue(r.result, out int count) && count > 0) - yield return new HitResultDisplayStatistic(r.result, value, null, r.displayName); + yield return new HitResultDisplayStatistic(r.result, value, count, r.displayName); break;