From b31ff679fb1af632f8b40d980a3d3528a08e43a8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Mar 2022 19:16:19 +0900 Subject: [PATCH 1/4] Provide correct `HitResult` type for random judgements in `TestSceneHitErrorMeter` --- osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index c1260f0231..a93ab6810d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -48,7 +48,11 @@ namespace osu.Game.Tests.Visual.Gameplay { AddStep("create display", () => recreateDisplay(new OsuHitWindows(), 5)); - AddRepeatStep("New random judgement", () => newJudgement(), 40); + AddRepeatStep("New random judgement", () => + { + double offset = RNG.Next(-150, 150); + newJudgement(offset, drawableRuleset.HitWindows.ResultFor(offset)); + }, 400); AddRepeatStep("New max negative", () => newJudgement(-drawableRuleset.HitWindows.WindowFor(HitResult.Meh)), 20); AddRepeatStep("New max positive", () => newJudgement(drawableRuleset.HitWindows.WindowFor(HitResult.Meh)), 20); From 6eed2c35a4cb79877ced63626745d8768fb196a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Mar 2022 19:16:38 +0900 Subject: [PATCH 2/4] Adjust visual appearance of `BarHitErrorMeter` for easier reading --- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 157 ++++++++++-------- 1 file changed, 89 insertions(+), 68 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 7903e54960..2f9206e0fb 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play.HUD.HitErrorMeters { @@ -21,14 +20,15 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { private const int arrow_move_duration = 400; - private const int judgement_line_width = 6; + private const int judgement_line_width = 10; + private const int judgement_line_height = 3; + + private const int centre_marker_size = 6; private const int bar_height = 200; private const int bar_width = 2; - private const int spacing = 2; - private const float chevron_size = 8; private SpriteIcon arrow; @@ -50,54 +50,25 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters [BackgroundDependencyLoader] private void load() { - InternalChild = new FillFlowContainer + var hitWindows = HitWindows.GetAllAvailableWindows().ToArray(); + + InternalChild = new Container { AutoSizeAxes = Axes.X, Height = bar_height, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(spacing, 0), Margin = new MarginPadding(2), Children = new Drawable[] { - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Width = chevron_size, - RelativeSizeAxes = Axes.Y, - Child = arrow = new SpriteIcon - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Y, - Y = 0.5f, - Icon = FontAwesome.Solid.ChevronRight, - Size = new Vector2(chevron_size), - } - }, colourBars = new Container { - Width = bar_width, - RelativeSizeAxes = Axes.Y, + Name = "colour axis", + X = chevron_size, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, + Width = judgement_line_width, + RelativeSizeAxes = Axes.Y, Children = new Drawable[] { - colourBarsEarly = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - Scale = new Vector2(1, -1), - }, - colourBarsLate = new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Both, - Height = 0.5f, - }, iconEarly = new SpriteIcon { Y = -10, @@ -113,20 +84,72 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Icon = FontAwesome.Solid.Bicycle, Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, - } + }, + colourBarsEarly = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + Width = bar_width, + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + Scale = new Vector2(1, -1), + }, + colourBarsLate = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.TopCentre, + Width = bar_width, + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + }, + judgementsContainer = new Container + { + Name = "judgements", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Y, + Width = judgement_line_width, + }, + new Circle + { + Name = "middle marker behind", + Colour = GetColourForHitResult(hitWindows.Last().result), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(centre_marker_size), + }, + new Circle + { + Name = "middle marker in front", + Colour = GetColourForHitResult(hitWindows.Last().result).Darken(0.5f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(centre_marker_size), + Scale = new Vector2(0.5f), + }, } }, - judgementsContainer = new Container + new Container { + Name = "average chevron", Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Width = judgement_line_width, + Width = chevron_size, RelativeSizeAxes = Axes.Y, + Child = arrow = new SpriteIcon + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Y, + Y = 0.5f, + Icon = FontAwesome.Solid.ChevronRight, + Size = new Vector2(chevron_size), + } }, } }; - createColourBars(); + createColourBars(hitWindows); } protected override void LoadComplete() @@ -149,10 +172,8 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters iconLate.Rotation = -Rotation; } - private void createColourBars() + private void createColourBars((HitResult result, double length)[] windows) { - var windows = HitWindows.GetAllAvailableWindows().ToArray(); - // max to avoid div-by-zero. maxHitWindow = Math.Max(1, windows.First().length); @@ -166,17 +187,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters colourBarsLate.Add(createColourBar(result, hitWindow, i == 0)); } - // a little nub to mark the centre point. - var centre = createColourBar(windows.Last().result, 0.01f); - centre.Anchor = centre.Origin = Anchor.CentreLeft; - centre.Width = 2.5f; - colourBars.Add(centre); - - Drawable createColourBar(HitResult result, float height, bool first = false) + Drawable createColourBar(HitResult result, float height, bool requireGradient = false) { var colour = GetColourForHitResult(result); - if (first) + if (requireGradient) { // the first bar needs gradient rendering. const float gradient_start = 0.8f; @@ -243,7 +258,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters judgementsContainer.Add(new JudgementLine { Y = getRelativeJudgementPosition(judgement.TimeOffset), - Origin = Anchor.CentreLeft, + Colour = GetColourForHitResult(judgement.Type), }); arrow.MoveToY( @@ -255,34 +270,40 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters internal class JudgementLine : CompositeDrawable { - private const int judgement_fade_duration = 5000; - public JudgementLine() { RelativeSizeAxes = Axes.X; RelativePositionAxes = Axes.Y; - Height = 3; + Height = judgement_line_height; - InternalChild = new CircularContainer + Blending = BlendingParameters.Additive; + + Origin = Anchor.Centre; + Anchor = Anchor.TopCentre; + + InternalChild = new Circle { - Masking = true, RelativeSizeAxes = Axes.Both, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - } }; } protected override void LoadComplete() { + const int judgement_fade_in_duration = 100; + const int judgement_fade_out_duration = 5000; + base.LoadComplete(); + Alpha = 0; Width = 0; - this.ResizeWidthTo(1, 200, Easing.OutElasticHalf); - this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration).Expire(); + this + .FadeTo(0.8f, judgement_fade_in_duration, Easing.OutQuint) + .ResizeWidthTo(1, judgement_fade_in_duration, Easing.OutQuint) + .Then() + .FadeOut(judgement_fade_out_duration, Easing.In) + .ResizeWidthTo(0, judgement_fade_out_duration, Easing.In) + .Expire(); } } From e91b3ae5f19fa70fa4062be6aef4e726f12ba10c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Mar 2022 19:18:47 +0900 Subject: [PATCH 3/4] Move constants closer to usages --- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 2f9206e0fb..521d8c01b1 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -18,19 +18,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class BarHitErrorMeter : HitErrorMeter { - private const int arrow_move_duration = 400; - private const int judgement_line_width = 10; private const int judgement_line_height = 3; - private const int centre_marker_size = 6; - - private const int bar_height = 200; - - private const int bar_width = 2; - - private const float chevron_size = 8; - private SpriteIcon arrow; private SpriteIcon iconEarly; private SpriteIcon iconLate; @@ -50,6 +40,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters [BackgroundDependencyLoader] private void load() { + const int centre_marker_size = 6; + const int bar_height = 200; + const int bar_width = 2; + const float chevron_size = 8; + const float icon_size = 14; + var hitWindows = HitWindows.GetAllAvailableWindows().ToArray(); InternalChild = new Container @@ -72,7 +68,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters iconEarly = new SpriteIcon { Y = -10, - Size = new Vector2(10), + Size = new Vector2(icon_size), Icon = FontAwesome.Solid.ShippingFast, Anchor = Anchor.TopCentre, Origin = Anchor.Centre, @@ -80,7 +76,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters iconLate = new SpriteIcon { Y = 10, - Size = new Vector2(10), + Size = new Vector2(icon_size), Icon = FontAwesome.Solid.Bicycle, Anchor = Anchor.BottomCentre, Origin = Anchor.Centre, @@ -235,6 +231,8 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters protected override void OnNewJudgement(JudgementResult judgement) { + const int arrow_move_duration = 400; + if (!judgement.IsHit || judgement.HitObject.HitWindows?.WindowFor(HitResult.Miss) == 0) return; From 163cd48bf63ec43c3b9677340976544b109eca2f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Mar 2022 19:27:53 +0900 Subject: [PATCH 4/4] Further metrics tweaking --- .../HUD/HitErrorMeters/BarHitErrorMeter.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 521d8c01b1..542731cf93 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -18,8 +18,8 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters { public class BarHitErrorMeter : HitErrorMeter { - private const int judgement_line_width = 10; - private const int judgement_line_height = 3; + private const int judgement_line_width = 14; + private const int judgement_line_height = 4; private SpriteIcon arrow; private SpriteIcon iconEarly; @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters [BackgroundDependencyLoader] private void load() { - const int centre_marker_size = 6; + const int centre_marker_size = 8; const int bar_height = 200; const int bar_width = 2; const float chevron_size = 8; @@ -98,6 +98,14 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters RelativeSizeAxes = Axes.Y, Height = 0.5f, }, + new Circle + { + Name = "middle marker behind", + Colour = GetColourForHitResult(hitWindows.Last().result), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(centre_marker_size), + }, judgementsContainer = new Container { Name = "judgements", @@ -107,17 +115,9 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Width = judgement_line_width, }, new Circle - { - Name = "middle marker behind", - Colour = GetColourForHitResult(hitWindows.Last().result), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(centre_marker_size), - }, - new Circle { Name = "middle marker in front", - Colour = GetColourForHitResult(hitWindows.Last().result).Darken(0.5f), + Colour = GetColourForHitResult(hitWindows.Last().result).Darken(0.3f), Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(centre_marker_size), @@ -231,7 +231,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters protected override void OnNewJudgement(JudgementResult judgement) { - const int arrow_move_duration = 400; + const int arrow_move_duration = 800; if (!judgement.IsHit || judgement.HitObject.HitWindows?.WindowFor(HitResult.Miss) == 0) return; @@ -261,7 +261,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters arrow.MoveToY( getRelativeJudgementPosition(floatingAverage = floatingAverage * 0.9 + judgement.TimeOffset * 0.1) - , arrow_move_duration, Easing.Out); + , arrow_move_duration, Easing.OutQuint); } private float getRelativeJudgementPosition(double value) => Math.Clamp((float)((value / maxHitWindow) + 1) / 2, 0, 1); @@ -296,11 +296,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Width = 0; this - .FadeTo(0.8f, judgement_fade_in_duration, Easing.OutQuint) + .FadeTo(0.6f, judgement_fade_in_duration, Easing.OutQuint) .ResizeWidthTo(1, judgement_fade_in_duration, Easing.OutQuint) .Then() - .FadeOut(judgement_fade_out_duration, Easing.In) - .ResizeWidthTo(0, judgement_fade_out_duration, Easing.In) + .FadeOut(judgement_fade_out_duration) + .ResizeWidthTo(0, judgement_fade_out_duration, Easing.InQuint) .Expire(); } }