diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs
index 3bc4556a27..02e8a8329a 100644
--- a/osu.Game/Graphics/UserInterface/LineGraph.cs
+++ b/osu.Game/Graphics/UserInterface/LineGraph.cs
@@ -23,6 +23,9 @@ namespace osu.Game.Graphics.UserInterface
///
public float? MinValue { get; set; }
+ public float? ActualMaxValue { get; private set; }
+ public float? ActualMinValue { get; private set; }
+
private const double transform_duration = 500;
///
@@ -40,6 +43,7 @@ namespace osu.Game.Graphics.UserInterface
///
public IEnumerable Values
{
+ get { return values; }
set
{
values = value.ToArray();
@@ -77,6 +81,9 @@ namespace osu.Game.Graphics.UserInterface
if (MaxValue > max) max = MaxValue.Value;
if (MinValue < min) min = MinValue.Value;
+ ActualMaxValue = max;
+ ActualMinValue = min;
+
for (int i = 0; i < values.Length; i++)
{
float x = (i + count - values.Length) / (float)(count - 1) * DrawWidth - 1;
diff --git a/osu.Game/Users/Profile/RankChart.cs b/osu.Game/Users/Profile/RankChart.cs
index 9cb11623da..49f67efbdc 100644
--- a/osu.Game/Users/Profile/RankChart.cs
+++ b/osu.Game/Users/Profile/RankChart.cs
@@ -2,12 +2,15 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using OpenTK;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
+using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
@@ -16,24 +19,28 @@ namespace osu.Game.Users.Profile
{
public class RankChart : Container
{
- private readonly SpriteText rank, performance, relative;
- private readonly LineGraph graph;
+ private readonly SpriteText rankText, performanceText, relativeText;
+ private readonly RankChartLineGraph graph;
- private readonly int[] ranks, performances;
+ private int[] ranks, performances;
+ private int rank, performance, countryRank;
+
+ private readonly User user;
public RankChart(User user)
{
+ this.user = user;
Padding = new MarginPadding { Vertical = 10 };
Children = new Drawable[]
{
- rank = new OsuSpriteText
+ rankText = new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Font = @"Exo2.0-RegularItalic",
TextSize = 25
},
- relative = new OsuSpriteText
+ relativeText = new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
@@ -41,29 +48,35 @@ namespace osu.Game.Users.Profile
Y = 25,
TextSize = 13
},
- performance = new OsuSpriteText
+ performanceText = new OsuSpriteText
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
Font = @"Exo2.0-RegularItalic",
TextSize = 13
},
- graph = new LineGraph
+ graph = new RankChartLineGraph
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.X,
Y = -13,
- DefaultValueCount = 90
+ DefaultValueCount = 90,
+ BallRelease = () =>
+ {
+ rankText.Text = $"#{rank:#,#}";
+ performanceText.Text = $"{performance:#,#}pp";
+ relativeText.Text = $"{this.user.Country?.FullName} #{countryRank:#,#}";
+ },
+ BallMove = index =>
+ {
+ rankText.Text = $"#{ranks[index]:#,#}";
+ performanceText.Text = $"{performances[index]:#,#}pp";
+ relativeText.Text = index == ranks.Length ? "Now" : $"{ranks.Length - index} days ago";
+ //plural should be handled in a general way
+ }
}
};
-
- //placeholder text
- rank.Text = "#12,345";
- relative.Text = $"{user.Country?.FullName} #678";
- performance.Text = "4,567pp";
- ranks = Enumerable.Range(1234, 80).ToArray();
- performances = ranks.Select(x => 6000 - x).ToArray();
}
[BackgroundDependencyLoader]
@@ -73,10 +86,16 @@ namespace osu.Game.Users.Profile
Task.Factory.StartNew(() =>
{
System.Threading.Thread.Sleep(1000);
- // put placeholder data here to show the transform
+ // put placeholder data here to show the transform
+ rank = 12345;
+ countryRank = 678;
+ performance = 4567;
+ ranks = Enumerable.Range(1234, 80).ToArray();
+ performances = ranks.Select(x => 6000 - x).ToArray();
// use logarithmic coordinates
graph.Values = ranks.Select(x => -(float)Math.Log(x));
+ graph.ResetBall();
});
}
@@ -89,5 +108,70 @@ namespace osu.Game.Users.Profile
return base.Invalidate(invalidation, source, shallPropagate);
}
+
+ private class RankChartLineGraph : LineGraph
+ {
+ private readonly CircularContainer ball;
+ private bool ballShown;
+
+ private const double transform_duration = 100;
+
+ public Action BallMove;
+ public Action BallRelease;
+
+ public RankChartLineGraph()
+ {
+ Add(ball = new CircularContainer
+ {
+ Size = new Vector2(8),
+ Masking = true,
+ Origin = Anchor.Centre,
+ Alpha = 0,
+ RelativePositionAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ new Box { RelativeSizeAxes = Axes.Both }
+ }
+ });
+ }
+
+ public void ResetBall()
+ {
+ ball.MoveTo(new Vector2(1, ((ActualMaxValue - Values.Last()) / (ActualMaxValue - ActualMinValue)).Value), ballShown ? transform_duration : 0, EasingTypes.OutQuint);
+ ball.Show();
+ BallRelease();
+ ballShown = true;
+ }
+
+ protected override bool OnMouseMove(InputState state)
+ {
+ if (ballShown)
+ {
+ var values = Values as IList;
+ var position = ToLocalSpace(state.Mouse.NativeState.Position);
+ int count = Math.Max(values.Count, DefaultValueCount);
+ int index = (int)Math.Round(position.X / DrawWidth * (count - 1));
+ if (index >= count - values.Count)
+ {
+ int i = index + values.Count - count;
+ float value = values[i];
+ float y = ((ActualMaxValue - value) / (ActualMaxValue - ActualMinValue)).Value;
+ if (Math.Abs(y * DrawHeight - position.Y) <= 8f)
+ {
+ ball.MoveTo(new Vector2(index / (float)(count - 1), y), transform_duration, EasingTypes.OutQuint);
+ BallMove(i);
+ }
+ }
+ }
+ return base.OnMouseMove(state);
+ }
+
+ protected override void OnHoverLost(InputState state)
+ {
+ if (ballShown)
+ ResetBall();
+ base.OnHoverLost(state);
+ }
+ }
}
}