mirror of
https://github.com/ppy/osu.git
synced 2025-03-10 03:57:20 +08:00
Merge pull request #26769 from EVAST9919/results-clean
Rework `AccuracyCircle` to not use `BufferedContainer`s
This commit is contained in:
commit
82b2edd4b7
42
osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs
Normal file
42
osu.Game.Tests/Visual/Ranking/TestSceneGradedCircles.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
|
{
|
||||||
|
public partial class TestSceneGradedCircles : OsuTestScene
|
||||||
|
{
|
||||||
|
private readonly GradedCircles ring;
|
||||||
|
|
||||||
|
public TestSceneGradedCircles()
|
||||||
|
{
|
||||||
|
ScoreProcessor scoreProcessor = new OsuRuleset().CreateScoreProcessor();
|
||||||
|
double accuracyX = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.X);
|
||||||
|
double accuracyS = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.S);
|
||||||
|
|
||||||
|
double accuracyA = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.A);
|
||||||
|
double accuracyB = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.B);
|
||||||
|
double accuracyC = scoreProcessor.AccuracyCutoffFromRank(ScoreRank.C);
|
||||||
|
|
||||||
|
Add(ring = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(400)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
AddSliderStep("Progress", 0.0, 1.0, 1.0, p => ring.Progress = p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -64,7 +64,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Relative width of the rank circles.
|
/// Relative width of the rank circles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float RANK_CIRCLE_RADIUS = 0.06f;
|
public const float RANK_CIRCLE_RADIUS = 0.05f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Relative width of the circle showing the accuracy.
|
/// Relative width of the circle showing the accuracy.
|
||||||
@ -74,12 +74,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// SS is displayed as a 1% region, otherwise it would be invisible.
|
/// SS is displayed as a 1% region, otherwise it would be invisible.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const double virtual_ss_percentage = 0.01;
|
public const double VIRTUAL_SS_PERCENTAGE = 0.01;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The width of a <see cref="RankNotch"/> in terms of accuracy.
|
/// The width of spacing in terms of accuracy between the grade circles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const double NOTCH_WIDTH_PERCENTAGE = 1.0 / 360;
|
public const double GRADE_SPACING_PERCENTAGE = 2.0 / 360;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The easing for the circle filling transforms.
|
/// The easing for the circle filling transforms.
|
||||||
@ -89,7 +89,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
private readonly ScoreInfo score;
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
private CircularProgress accuracyCircle;
|
private CircularProgress accuracyCircle;
|
||||||
private CircularProgress innerMask;
|
private GradedCircles gradedCircles;
|
||||||
private Container<RankBadge> badges;
|
private Container<RankBadge> badges;
|
||||||
private RankText rankText;
|
private RankText rankText;
|
||||||
|
|
||||||
@ -158,82 +158,16 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#7CF6FF"), Color4Extensions.FromHex("#BAFFA9")),
|
Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#7CF6FF"), Color4Extensions.FromHex("#BAFFA9")),
|
||||||
InnerRadius = accuracy_circle_radius,
|
InnerRadius = accuracy_circle_radius,
|
||||||
},
|
},
|
||||||
new BufferedContainer
|
new Container
|
||||||
{
|
{
|
||||||
Name = "Graded circles",
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Size = new Vector2(0.8f),
|
Size = new Vector2(0.8f),
|
||||||
Padding = new MarginPadding(2),
|
Padding = new MarginPadding(2.5f),
|
||||||
Children = new Drawable[]
|
Child = gradedCircles = new GradedCircles(accuracyC, accuracyB, accuracyA, accuracyS, accuracyX)
|
||||||
{
|
{
|
||||||
new CircularProgress
|
RelativeSizeAxes = Axes.Both
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.X),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyX }
|
|
||||||
},
|
|
||||||
new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.S),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyX - virtual_ss_percentage }
|
|
||||||
},
|
|
||||||
new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.A),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyS }
|
|
||||||
},
|
|
||||||
new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.B),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyA }
|
|
||||||
},
|
|
||||||
new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.C),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyB }
|
|
||||||
},
|
|
||||||
new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = OsuColour.ForRank(ScoreRank.D),
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS,
|
|
||||||
Current = { Value = accuracyC }
|
|
||||||
},
|
|
||||||
new RankNotch((float)accuracyX),
|
|
||||||
new RankNotch((float)(accuracyX - virtual_ss_percentage)),
|
|
||||||
new RankNotch((float)accuracyS),
|
|
||||||
new RankNotch((float)accuracyA),
|
|
||||||
new RankNotch((float)accuracyB),
|
|
||||||
new RankNotch((float)accuracyC),
|
|
||||||
new BufferedContainer
|
|
||||||
{
|
|
||||||
Name = "Graded circle mask",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding(1),
|
|
||||||
Blending = new BlendingParameters
|
|
||||||
{
|
|
||||||
Source = BlendingType.DstColor,
|
|
||||||
Destination = BlendingType.OneMinusSrcColor,
|
|
||||||
SourceAlpha = BlendingType.One,
|
|
||||||
DestinationAlpha = BlendingType.SrcAlpha
|
|
||||||
},
|
|
||||||
Child = innerMask = new CircularProgress
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
InnerRadius = RANK_CIRCLE_RADIUS - 0.02f,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
badges = new Container<RankBadge>
|
badges = new Container<RankBadge>
|
||||||
@ -248,7 +182,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
new RankBadge(accuracyB, Interpolation.Lerp(accuracyB, accuracyA, 0.5), getRank(ScoreRank.B)),
|
new RankBadge(accuracyB, Interpolation.Lerp(accuracyB, accuracyA, 0.5), getRank(ScoreRank.B)),
|
||||||
// The S and A badges are moved down slightly to prevent collision with the SS badge.
|
// The S and A badges are moved down slightly to prevent collision with the SS badge.
|
||||||
new RankBadge(accuracyA, Interpolation.Lerp(accuracyA, accuracyS, 0.25), getRank(ScoreRank.A)),
|
new RankBadge(accuracyA, Interpolation.Lerp(accuracyA, accuracyS, 0.25), getRank(ScoreRank.A)),
|
||||||
new RankBadge(accuracyS, Interpolation.Lerp(accuracyS, (accuracyX - virtual_ss_percentage), 0.25), getRank(ScoreRank.S)),
|
new RankBadge(accuracyS, Interpolation.Lerp(accuracyS, (accuracyX - VIRTUAL_SS_PERCENTAGE), 0.25), getRank(ScoreRank.S)),
|
||||||
new RankBadge(accuracyX, accuracyX, getRank(ScoreRank.X)),
|
new RankBadge(accuracyX, accuracyX, getRank(ScoreRank.X)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -296,7 +230,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
}
|
}
|
||||||
|
|
||||||
using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY))
|
using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY))
|
||||||
innerMask.FillTo(1f, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
|
gradedCircles.TransformTo(nameof(GradedCircles.Progress), 1.0, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
|
||||||
|
|
||||||
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
|
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
|
||||||
{
|
{
|
||||||
@ -313,10 +247,10 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
// to prevent ambiguity on what grade it's pointing at.
|
// to prevent ambiguity on what grade it's pointing at.
|
||||||
foreach (double p in notchPercentages)
|
foreach (double p in notchPercentages)
|
||||||
{
|
{
|
||||||
if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2))
|
if (Precision.AlmostEquals(p, targetAccuracy, GRADE_SPACING_PERCENTAGE / 2))
|
||||||
{
|
{
|
||||||
int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria
|
int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria
|
||||||
targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2);
|
targetAccuracy = p + tippingDirection * (GRADE_SPACING_PERCENTAGE / 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +259,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH)
|
if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH)
|
||||||
targetAccuracy = 1;
|
targetAccuracy = 1;
|
||||||
else
|
else
|
||||||
targetAccuracy = Math.Min(accuracyX - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy);
|
targetAccuracy = Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE - GRADE_SPACING_PERCENTAGE / 2, targetAccuracy);
|
||||||
|
|
||||||
// The accuracy circle gauge visually fills up a bit too much.
|
// The accuracy circle gauge visually fills up a bit too much.
|
||||||
// This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases.
|
// This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases.
|
||||||
@ -365,7 +299,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
using (BeginDelayedSequence(
|
using (BeginDelayedSequence(
|
||||||
inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION))
|
inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracyX - VIRTUAL_SS_PERCENTAGE, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION))
|
||||||
{
|
{
|
||||||
badge.Appear();
|
badge.Appear();
|
||||||
|
|
||||||
@ -425,7 +359,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|||||||
.FadeOut(800, Easing.Out);
|
.FadeOut(800, Easing.Out);
|
||||||
|
|
||||||
accuracyCircle
|
accuracyCircle
|
||||||
.FillTo(accuracyS - NOTCH_WIDTH_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint);
|
.FillTo(accuracyS - GRADE_SPACING_PERCENTAGE / 2 - visual_alignment_offset, 70, Easing.OutQuint);
|
||||||
|
|
||||||
badges.Single(b => b.Rank == getRank(ScoreRank.S))
|
badges.Single(b => b.Rank == getRank(ScoreRank.S))
|
||||||
.FadeOut(70, Easing.OutQuint);
|
.FadeOut(70, Easing.OutQuint);
|
||||||
|
89
osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs
Normal file
89
osu.Game/Screens/Ranking/Expanded/Accuracy/GradedCircles.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
public partial class GradedCircles : CompositeDrawable
|
||||||
|
{
|
||||||
|
private double progress;
|
||||||
|
|
||||||
|
public double Progress
|
||||||
|
{
|
||||||
|
get => progress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
progress = value;
|
||||||
|
|
||||||
|
foreach (var circle in circles)
|
||||||
|
circle.RevealProgress = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Container<GradedCircle> circles;
|
||||||
|
|
||||||
|
public GradedCircles(double accuracyC, double accuracyB, double accuracyA, double accuracyS, double accuracyX)
|
||||||
|
{
|
||||||
|
InternalChild = circles = new Container<GradedCircle>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new GradedCircle(0.0, accuracyC)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.D),
|
||||||
|
},
|
||||||
|
new GradedCircle(accuracyC, accuracyB)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.C),
|
||||||
|
},
|
||||||
|
new GradedCircle(accuracyB, accuracyA)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.B),
|
||||||
|
},
|
||||||
|
new GradedCircle(accuracyA, accuracyS)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.A),
|
||||||
|
},
|
||||||
|
new GradedCircle(accuracyS, accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.S),
|
||||||
|
},
|
||||||
|
new GradedCircle(accuracyX - AccuracyCircle.VIRTUAL_SS_PERCENTAGE, 1.0)
|
||||||
|
{
|
||||||
|
Colour = OsuColour.ForRank(ScoreRank.X)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class GradedCircle : CircularProgress
|
||||||
|
{
|
||||||
|
public double RevealProgress
|
||||||
|
{
|
||||||
|
set => Current.Value = Math.Clamp(value, startProgress, endProgress) - startProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly double startProgress;
|
||||||
|
private readonly double endProgress;
|
||||||
|
|
||||||
|
public GradedCircle(double startProgress, double endProgress)
|
||||||
|
{
|
||||||
|
this.startProgress = startProgress + AccuracyCircle.GRADE_SPACING_PERCENTAGE * 0.5;
|
||||||
|
this.endProgress = endProgress - AccuracyCircle.GRADE_SPACING_PERCENTAGE * 0.5;
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
InnerRadius = AccuracyCircle.RANK_CIRCLE_RADIUS;
|
||||||
|
Rotation = (float)this.startProgress * 360;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A solid "notch" of the <see cref="AccuracyCircle"/> that appears at the ends of the rank circles to add separation.
|
|
||||||
/// </summary>
|
|
||||||
public partial class RankNotch : CompositeDrawable
|
|
||||||
{
|
|
||||||
private readonly float position;
|
|
||||||
|
|
||||||
public RankNotch(float position)
|
|
||||||
{
|
|
||||||
this.position = position;
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
InternalChild = new Container
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Rotation = position * 360f,
|
|
||||||
Child = new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Height = AccuracyCircle.RANK_CIRCLE_RADIUS,
|
|
||||||
Width = (float)AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 360f,
|
|
||||||
Colour = OsuColour.Gray(0.3f),
|
|
||||||
EdgeSmoothness = new Vector2(1f)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user