1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-15 13:07:24 +08:00
osu-lazer/osu.Game/Screens/OnlinePlay/DailyChallenge/DailyChallengeScoreBreakdown.cs

200 lines
6.6 KiB
C#

// 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 System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Metadata;
using osu.Game.Overlays;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osuTK;
namespace osu.Game.Screens.OnlinePlay.DailyChallenge
{
public partial class DailyChallengeScoreBreakdown : CompositeDrawable
{
private FillFlowContainer<Bar> barsContainer = null!;
private const int bin_count = MultiplayerPlaylistItemStats.TOTAL_SCORE_DISTRIBUTION_BINS;
private long[] bins = new long[bin_count];
[BackgroundDependencyLoader]
private void load()
{
InternalChildren = new Drawable[]
{
new SectionHeader("Score breakdown"),
barsContainer = new FillFlowContainer<Bar>
{
Direction = FillDirection.Horizontal,
RelativeSizeAxes = Axes.Both,
Height = 0.9f,
Padding = new MarginPadding { Top = 35 },
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
}
};
for (int i = 0; i < bin_count; ++i)
{
barsContainer.Add(new Bar(100_000 * i, 100_000 * (i + 1) - 1)
{
Width = 1f / bin_count,
});
}
}
public void AddNewScore(NewScoreEvent newScoreEvent)
{
int targetBin = (int)Math.Clamp(Math.Floor((float)newScoreEvent.TotalScore / 100000), 0, bin_count - 1);
bins[targetBin] += 1;
updateCounts();
var text = new OsuSpriteText
{
Text = newScoreEvent.TotalScore.ToString(@"N0"),
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
Font = OsuFont.Default.With(size: 30),
RelativePositionAxes = Axes.X,
X = (targetBin + 0.5f) / bin_count - 0.5f,
Alpha = 0,
};
AddInternal(text);
Scheduler.AddDelayed(() =>
{
float startY = ToLocalSpace(barsContainer[targetBin].CircularBar.ScreenSpaceDrawQuad.TopLeft).Y;
text.FadeInFromZero()
.ScaleTo(new Vector2(0.8f), 500, Easing.OutElasticHalf)
.MoveToY(startY)
.MoveToOffset(new Vector2(0, -50), 2500, Easing.OutQuint)
.FadeOut(2500, Easing.OutQuint)
.Expire();
}, 150);
}
public void SetInitialCounts(long[] counts)
{
if (counts.Length != bin_count)
throw new ArgumentException(@"Incorrect number of bins.", nameof(counts));
bins = counts;
updateCounts();
}
private void updateCounts()
{
long max = Math.Max(bins.Max(), 1);
for (int i = 0; i < bin_count; ++i)
barsContainer[i].UpdateCounts(bins[i], max);
}
private partial class Bar : CompositeDrawable, IHasTooltip
{
private readonly int binStart;
private readonly int binEnd;
private long count;
private long max;
public Container CircularBar { get; private set; } = null!;
public Bar(int binStart, int binEnd)
{
this.binStart = binStart;
this.binEnd = binEnd;
}
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
RelativeSizeAxes = Axes.Both;
AddInternal(new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding
{
Bottom = 20,
Horizontal = 3,
},
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Masking = true,
Child = CircularBar = new Container
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Height = 0.01f,
Masking = true,
CornerRadius = 10,
Colour = colourProvider.Highlight1,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
}
}
});
string? label = null;
switch (binStart)
{
case 200_000:
case 400_000:
case 600_000:
case 800_000:
label = @$"{binStart / 1000}k";
break;
case 1_000_000:
label = @"1M";
break;
}
if (label != null)
{
AddInternal(new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomCentre,
Text = label,
Colour = colourProvider.Content2,
});
}
}
protected override void Update()
{
base.Update();
CircularBar.CornerRadius = Math.Min(CircularBar.DrawHeight / 2, CircularBar.DrawWidth / 4);
}
public void UpdateCounts(long newCount, long newMax)
{
bool isIncrement = newCount > count;
count = newCount;
max = newMax;
CircularBar.ResizeHeightTo(0.01f + 0.99f * count / max, 300, Easing.OutQuint);
if (isIncrement)
CircularBar.FlashColour(Colour4.White, 600, Easing.OutQuint);
}
public LocalisableString TooltipText => LocalisableString.Format("{0:N0} passes in {1:N0} - {2:N0} range", count, binStart, binEnd);
}
}
}