// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using System; namespace osu.Game.Graphics.UserInterface { public class StarCounter : Container { private readonly Container stars; /// /// Maximum amount of stars displayed. /// /// /// This does not limit the counter value, but the amount of stars displayed. /// public int StarCount { get; } private double animationDelay => 80; private double scalingDuration => 1000; private EasingTypes scalingEasing => EasingTypes.OutElasticHalf; private float minStarScale => 0.4f; private double fadingDuration => 100; private float minStarAlpha => 0.5f; private const float star_size = 20; private const float star_spacing = 4; private float countStars; /// /// Amount of stars represented. /// public float CountStars { get { return countStars; } set { if (countStars == value) return; if (IsLoaded) transformCount(value); countStars = value; } } /// /// Shows a float count as stars. Used as star difficulty display. /// /// Maximum amount of stars to display. public StarCounter(int starCount = 10) { StarCount = Math.Max(starCount, 0); AutoSizeAxes = Axes.Both; Children = new Drawable[] { stars = new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, Spacing = new Vector2(star_spacing), } }; for (int i = 0; i < StarCount; i++) { stars.Add(new Star { Alpha = minStarAlpha, }); } } protected override void LoadComplete() { base.LoadComplete(); // Animate initial state from zero. ReplayAnimation(); } public void ResetCount() { countStars = 0; StopAnimation(); } public void ReplayAnimation() { var t = countStars; ResetCount(); CountStars = t; } public void StopAnimation() { int i = 0; foreach (var star in stars.Children) { star.ClearTransforms(true); star.FadeTo(i < countStars ? 1.0f : minStarAlpha); star.Icon.ScaleTo(getStarScale(i, countStars)); i++; } } private float getStarScale(int i, float value) { if (value <= i) return minStarScale; return i + 1 <= value ? 1.0f : (float)Interpolation.ValueAt(value, minStarScale, 1.0f, i, i + 1); } private void transformCount(float newValue) { int i = 0; foreach (var star in stars.Children) { star.ClearTransforms(true); var delay = (countStars <= newValue ? Math.Max(i - countStars, 0) : Math.Max(countStars - 1 - i, 0)) * animationDelay; star.Delay(delay).FadeTo(i < newValue ? 1.0f : minStarAlpha, fadingDuration); star.Icon.Delay(delay).ScaleTo(getStarScale(i, newValue), scalingDuration, scalingEasing); i++; } } private class Star : Container { public readonly TextAwesome Icon; public Star() { Size = new Vector2(star_size); Children = new[] { Icon = new TextAwesome { TextSize = star_size, Icon = FontAwesome.fa_star, Anchor = Anchor.Centre, Origin = Anchor.Centre, } }; } } } }