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

163 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
2018-11-20 07:51:59 +00:00
using osuTK;
2018-04-13 09:19:50 +00:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2020-01-09 04:43:44 +00:00
using osu.Framework.Utils;
2018-04-13 09:19:50 +00:00
using System;
using System.Linq;
using osu.Framework.Graphics.Sprites;
2018-04-13 09:19:50 +00:00
namespace osu.Game.Graphics.UserInterface
{
public class StarCounter : Container
{
private readonly FillFlowContainer<Star> stars;
2018-04-13 09:19:50 +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; }
/// <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
private const float star_spacing = 4;
private float current;
2018-04-13 09:19:50 +00:00
/// <summary>
/// Amount of stars represented.
/// </summary>
public float Current
2018-04-13 09:19:50 +00:00
{
get => current;
2018-04-13 09:19:50 +00:00
set
{
if (current == value) return;
2018-04-13 09:19:50 +00:00
if (IsLoaded)
animate(value);
current = value;
2018-04-13 09:19:50 +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);
AutoSizeAxes = Axes.Both;
Children = new Drawable[]
{
stars = new FillFlowContainer<Star>
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(star_spacing),
ChildrenEnumerable = Enumerable.Range(0, StarCount).Select(i => CreateStar())
2018-04-13 09:19:50 +00:00
}
};
}
public virtual Star CreateStar() => new DefaultStar();
2018-04-13 09:19:50 +00:00
protected override void LoadComplete()
{
base.LoadComplete();
// Animate initial state from zero.
ReplayAnimation();
}
public void ResetCount()
{
current = 0;
2018-04-13 09:19:50 +00:00
StopAnimation();
}
public void ReplayAnimation()
{
var t = current;
2018-04-13 09:19:50 +00:00
ResetCount();
Current = t;
2018-04-13 09:19:50 +00:00
}
public void StopAnimation()
{
animate(current);
2018-04-13 09:19:50 +00:00
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)
2018-04-13 09:19:50 +00:00
{
for (var i = 0; i < stars.Children.Count; i++)
2018-04-13 09:19:50 +00:00
{
var star = stars.Children[i];
2018-04-13 09:19:50 +00:00
star.ClearTransforms(true);
double delay = (current <= newValue ? Math.Max(i - current, 0) : Math.Max(current - 1 - i, 0)) * AnimationDelay;
2018-04-13 09:19:50 +00:00
using (star.BeginDelayedSequence(delay, true))
star.DisplayAt(getStarScale(i, newValue));
2018-04-13 09:19:50 +00:00
}
}
public class DefaultStar : Star
2018-04-13 09:19:50 +00:00
{
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;
2018-04-13 09:19:50 +00:00
public readonly SpriteIcon Icon;
2019-02-28 04:31:40 +00:00
public DefaultStar()
2018-04-13 09:19:50 +00:00
{
Size = new Vector2(star_size);
InternalChild = Icon = new SpriteIcon
2018-04-13 09:19:50 +00:00
{
Size = new Vector2(star_size),
2019-04-02 10:55:24 +00:00
Icon = FontAwesome.Solid.Star,
2018-04-13 09:19:50 +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 class Star : CompositeDrawable
{
public abstract void DisplayAt(float scale);
2018-04-13 09:19:50 +00:00
}
}
}