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

193 lines
5.9 KiB
C#
Raw Normal View History

//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transformations;
using osu.Framework.MathUtils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
2016-11-08 23:13:20 +00:00
using osu.Framework.Allocation;
namespace osu.Game.Graphics.UserInterface
{
2016-10-22 08:50:42 +00:00
public class StarCounter : Container
{
2016-10-16 23:30:25 +00:00
private readonly Container starContainer;
private readonly List<TextAwesome> stars = new List<TextAwesome>();
2016-10-13 22:13:20 +00:00
private double transformStartTime = 0;
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>
2016-10-13 01:51:50 +00:00
public int MaxStars
{
get;
protected set;
}
2016-10-14 23:23:27 +00:00
private double animationDelay => 150;
2016-10-13 22:13:20 +00:00
2016-10-14 23:23:27 +00:00
private double scalingDuration => 500;
private EasingTypes scalingEasing => EasingTypes.OutElasticHalf;
private float minStarScale => 0.3f;
2016-10-13 22:13:20 +00:00
2016-10-14 23:23:27 +00:00
private double fadingDuration => 100;
private float minStarAlpha => 0.5f;
2016-10-13 22:13:20 +00:00
public float StarSize = 20;
public float StarSpacing = 4;
public float VisibleValue
{
get
{
double elapsedTime = Time.Current - transformStartTime;
2016-10-14 23:23:27 +00:00
double expectedElapsedTime = Math.Abs(prevCount - count) * animationDelay;
2016-10-13 22:13:20 +00:00
if (elapsedTime >= expectedElapsedTime)
return count;
return Interpolation.ValueAt(elapsedTime, prevCount, count, 0, expectedElapsedTime);
}
}
private float prevCount;
private float count;
/// <summary>
/// Amount of stars represented.
/// </summary>
public float Count
{
get
{
return count;
}
2016-10-13 22:13:20 +00:00
set
{
if (IsLoaded)
{
prevCount = VisibleValue;
transformCount(prevCount, value);
2016-10-13 22:13:20 +00:00
}
count = value;
2016-10-13 22:13:20 +00:00
}
}
2016-10-16 23:30:25 +00:00
/// <summary>
/// Shows a float count as stars (up to 10). Used as star difficulty display.
/// </summary>
2016-10-22 08:50:42 +00:00
public StarCounter() : this(10)
{
AutoSizeAxes = Axes.Both;
2016-10-16 23:30:25 +00:00
}
2016-10-13 02:36:52 +00:00
/// <summary>
/// Shows a float count as stars. Used as star difficulty display.
/// </summary>
2016-10-16 00:07:07 +00:00
/// <param name="maxstars">Maximum amount of stars to display.</param>
2016-10-16 23:30:25 +00:00
public StarCounter(int maxstars)
{
2016-10-16 00:07:07 +00:00
MaxStars = Math.Max(maxstars, 0);
2016-10-13 01:51:50 +00:00
Children = new Drawable[]
{
starContainer = new Container
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
}
};
2016-10-13 01:51:50 +00:00
starContainer.Width = MaxStars * StarSize + Math.Max(MaxStars - 1, 0) * StarSpacing;
starContainer.Height = StarSize;
for (int i = 0; i < MaxStars; i++)
{
TextAwesome star = new TextAwesome
{
2016-11-07 08:58:32 +00:00
Icon = FontAwesome.fa_star,
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
TextSize = StarSize,
2016-10-16 23:30:25 +00:00
Scale = new Vector2(minStarScale),
Alpha = minStarAlpha,
Position = new Vector2((StarSize + StarSpacing) * i + (StarSize + StarSpacing) / 2, 0),
};
//todo: user Container<T> once we have it.
stars.Add(star);
starContainer.Add(star);
}
2016-11-01 14:24:14 +00:00
}
2016-11-01 14:24:14 +00:00
protected override void LoadComplete()
{
base.LoadComplete();
2016-10-16 23:30:25 +00:00
// Animate initial state from zero.
transformCount(0, Count);
}
2016-10-13 22:13:20 +00:00
public void ResetCount()
{
2016-10-13 22:13:20 +00:00
Count = 0;
StopAnimation();
}
2016-10-13 22:13:20 +00:00
public void StopAnimation()
{
2016-10-13 22:13:20 +00:00
prevCount = count;
transformStartTime = Time.Current;
2016-10-13 22:13:20 +00:00
for (int i = 0; i < MaxStars; i++)
transformStarQuick(i, count);
}
2016-10-13 22:13:20 +00:00
private float getStarScale(int i, float value)
{
2016-10-13 22:13:20 +00:00
if (value <= i)
2016-10-14 23:23:27 +00:00
return minStarScale;
2016-10-13 22:13:20 +00:00
if (i + 1 <= value)
return 1.0f;
2016-10-14 23:23:27 +00:00
return Interpolation.ValueAt(value, minStarScale, 1.0f, i, i + 1);
}
2016-10-13 22:13:20 +00:00
private void transformStar(int i, float value)
{
2016-10-14 23:23:27 +00:00
stars[i].FadeTo(i < value ? 1.0f : minStarAlpha, fadingDuration);
stars[i].ScaleTo(getStarScale(i, value), scalingDuration, scalingEasing);
}
2016-10-13 22:13:20 +00:00
private void transformStarQuick(int i, float value)
{
2016-10-14 23:23:27 +00:00
stars[i].FadeTo(i < value ? 1.0f : minStarAlpha);
2016-10-13 22:13:20 +00:00
stars[i].ScaleTo(getStarScale(i, value));
}
2016-10-13 22:13:20 +00:00
private void transformCount(float currentValue, float newValue)
{
2016-10-14 00:50:06 +00:00
for (int i = 0; i < MaxStars; i++)
{
2016-10-14 00:50:06 +00:00
stars[i].ClearTransformations();
if (currentValue <= newValue)
2016-10-14 23:23:27 +00:00
stars[i].Delay(Math.Max(i - currentValue, 0) * animationDelay);
2016-10-14 00:50:06 +00:00
else
2016-10-14 23:23:27 +00:00
stars[i].Delay(Math.Max(currentValue - 1 - i, 0) * animationDelay);
2016-10-14 00:50:06 +00:00
transformStar(i, newValue);
2016-10-15 23:04:00 +00:00
stars[i].DelayReset();
}
transformStartTime = Time.Current;
}
}
}