osu/osu.Game/Graphics/UserInterface/StarCounter.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

165 lines
4.6 KiB
C#
Raw Normal View History

// 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.
2018-04-13 09:19:50 +00:00
2022-06-17 07:37:17 +00:00
#nullable disable
2018-11-20 07:51:59 +00:00
using osuTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2020-01-09 04:43:44 +00:00
using osu.Framework.Utils;
using System;
2017-12-15 09:40:03 +00:00
using System.Linq;
using osu.Framework.Graphics.Sprites;
2018-04-13 09:19:50 +00:00
namespace osu.Game.Graphics.UserInterface
{
2016-10-22 08:50:42 +00:00
public partial class StarCounter : Container
{
private readonly FillFlowContainer<Star> stars;
2018-04-13 09:19:50 +00:00
2016-10-13 02:36:52 +00:00
/// <summary>
/// Maximum amount of stars displayed.
/// </summary>
/// <remarks>
/// This does not limit the counter value, but the amount of stars displayed.
/// </remarks>
public int StarCount { get; }
2018-04-13 09:19:50 +00:00
/// <summary>
/// The added delay for each subsequent star to be animated.
/// </summary>
protected virtual double AnimationDelay => 80;
2018-04-13 09:19:50 +00:00
2017-03-06 09:49:23 +00:00
private const float star_spacing = 4;
2018-04-13 09:19:50 +00:00
private float current;
2018-04-13 09:19:50 +00:00
2016-10-13 22:13:20 +00:00
/// <summary>
/// Amount of stars represented.
/// </summary>
public float Current
2016-10-13 22:13:20 +00:00
{
get => current;
2018-04-13 09:19:50 +00:00
2016-10-13 22:13:20 +00:00
set
{
if (current == value) return;
2018-04-13 09:19:50 +00:00
if (IsLoaded)
animate(value);
current = value;
2016-10-13 22:13:20 +00:00
}
}
2018-04-13 09:19:50 +00:00
2016-10-13 02:36:52 +00:00
/// <summary>
/// Shows a float count as stars. Used as star difficulty display.
/// </summary>
/// <param name="starCount">Maximum amount of stars to display.</param>
public StarCounter(int starCount = 10)
{
StarCount = Math.Max(starCount, 0);
2018-04-13 09:19:50 +00:00
AutoSizeAxes = Axes.Both;
2018-04-13 09:19:50 +00:00
2016-10-13 01:51:50 +00:00
Children = new Drawable[]
{
2017-03-01 18:33:01 +00:00
stars = new FillFlowContainer<Star>
2016-10-13 01:51:50 +00:00
{
AutoSizeAxes = Axes.Both,
2017-03-04 10:00:17 +00:00
Direction = FillDirection.Horizontal,
2017-03-01 18:33:01 +00:00
Spacing = new Vector2(star_spacing),
2022-06-24 12:25:23 +00:00
ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(_ => CreateStar())
2016-10-13 01:51:50 +00:00
}
};
2016-11-01 14:24:14 +00:00
}
2018-04-13 09:19:50 +00:00
public virtual Star CreateStar() => new DefaultStar();
2016-11-01 14:24:14 +00:00
protected override void LoadComplete()
{
base.LoadComplete();
2018-04-13 09:19:50 +00:00
2016-10-16 23:30:25 +00:00
// Animate initial state from zero.
ReplayAnimation();
}
2018-04-13 09:19:50 +00:00
2016-10-13 22:13:20 +00:00
public void ResetCount()
{
current = 0;
2016-10-13 22:13:20 +00:00
StopAnimation();
}
2018-04-13 09:19:50 +00:00
public void ReplayAnimation()
{
float t = current;
ResetCount();
Current = t;
}
2018-04-13 09:19:50 +00:00
public void StopAnimation()
{
animate(current);
foreach (var star in stars.Children)
star.FinishTransforms(true);
}
2018-04-13 09:19:50 +00:00
private float getStarScale(int i, float value) => i + 1 <= value ? 1.0f : Interpolation.ValueAt(value, 0, 1.0f, i, i + 1);
2018-04-13 09:19:50 +00:00
private void animate(float newValue)
{
for (int i = 0; i < stars.Children.Count; i++)
{
var star = stars.Children[i];
2017-02-25 12:12:39 +00:00
star.ClearTransforms(true);
2018-04-13 09:19:50 +00:00
double delay = (current <= newValue ? Math.Max(i - current, 0) : Math.Max(current - 1 - i, 0)) * AnimationDelay;
2018-04-13 09:19:50 +00:00
2021-07-05 15:52:39 +00:00
using (star.BeginDelayedSequence(delay))
star.DisplayAt(getStarScale(i, newValue));
}
}
2018-04-13 09:19:50 +00:00
public partial class DefaultStar : Star
{
private const double scaling_duration = 1000;
private const double fading_duration = 100;
private const Easing scaling_easing = Easing.OutElasticHalf;
private const float min_star_scale = 0.4f;
private const float star_size = 20;
public readonly SpriteIcon Icon;
2019-02-28 04:31:40 +00:00
public DefaultStar()
{
Size = new Vector2(star_size);
2018-04-13 09:19:50 +00:00
InternalChild = Icon = new SpriteIcon
{
2017-12-15 09:40:03 +00:00
Size = new Vector2(star_size),
2019-04-02 10:55:24 +00:00
Icon = FontAwesome.Solid.Star,
2017-12-15 09:40:03 +00:00
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
};
}
public override void DisplayAt(float scale)
{
2020-11-28 19:35:03 +00:00
scale = (float)Interpolation.Lerp(min_star_scale, 1, Math.Clamp(scale, 0, 1));
this.FadeTo(scale, fading_duration);
Icon.ScaleTo(scale, scaling_duration, scaling_easing);
}
}
public abstract partial class Star : CompositeDrawable
{
public abstract void DisplayAt(float scale);
}
}
}