diff --git a/osu.Desktop.VisualTests/Tests/TestCaseUserRanks.cs b/osu.Desktop.VisualTests/Tests/TestCaseUserRanks.cs new file mode 100644 index 0000000000..651c39ede4 --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseUserRanks.cs @@ -0,0 +1,100 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Overlays.Profile.Sections; +using osu.Game.Overlays.Profile.Sections.Ranks; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Desktop.VisualTests.Tests +{ + public class TestCaseUserRanks : TestCase + { + public override string Description => "showing your latest achievements"; + + public TestCaseUserRanks() + { + RanksSection ranks; + + Add(new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f) + }, + ranks = new RanksSection(), + } + }); + + AddStep("Add First Place", () => ranks.FirstPlacePlays = new[] + { + new Play + { + Rank = ScoreRank.A, + PerformancePoints = 666, + Accuracy = 0.735, + Date = DateTimeOffset.UtcNow, + Mods = new Mod[] { new ModAutoplay(), new ModDoubleTime() }, + Beatmap = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "FREEDOM DiVE", + Artist = "xi" + }, + Version = "FOUR DIMENSIONS", + OnlineBeatmapID = 129891, + } + } + }); + + AddStep("Add Best Performances", () => + { + List plays = new List(); + Mod[] availableMods = { new OsuModHidden(), new OsuModFlashlight(), new OsuModHardRock(), new OsuModDoubleTime(), new OsuModPerfect() }; + List selectedMods = new List(availableMods); + for (int i = 0; i <= availableMods.Length; i++) + { + plays.Add(new Play + { + Rank = (ScoreRank) Enum.GetValues(typeof(ScoreRank)).GetValue(Enum.GetValues(typeof(ScoreRank)).Length - 1 - i), + PerformancePoints = (int)(Math.Pow(0.50, i) * 800), + Accuracy = Math.Pow(0.99, i), + Date = DateTimeOffset.UtcNow.AddDays(-Math.Pow(i, 2)), + Mods = selectedMods.ToList(), + Beatmap = new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "Highscore", + Artist = "Panda Eyes & Teminite" + }, + Version = "Game Over", + OnlineBeatmapID = 736215, + } + }); + if(i < availableMods.Length) + selectedMods.Remove(availableMods[i]); + } + ranks.BestPlays = plays; + }); + } + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 4974f0c0d1..00bcaca1e8 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -217,6 +217,7 @@ + diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePlay.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePlay.cs new file mode 100644 index 0000000000..66588462f3 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePlay.cs @@ -0,0 +1,211 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Select.Leaderboards; +using System.Linq; +using OpenTK.Graphics; +using System.Diagnostics; +using osu.Framework.Input; +using osu.Framework.Localisation; + +namespace osu.Game.Overlays.Profile.Sections.Ranks +{ + public class DrawablePlay : Container + { + private readonly FillFlowContainer stats; + private readonly FillFlowContainer metadata; + private readonly ModContainer modContainer; + private readonly Play play; + private readonly double weight; + + public DrawablePlay(Play play, double weight = -1) + { + this.play = play; + this.weight = weight; + + Children = new Drawable[] + { + new DrawableRank(play.Rank) + { + RelativeSizeAxes = Axes.Y, + Width = 60, + FillMode = FillMode.Fit, + }, + stats = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Direction = FillDirection.Vertical, + }, + metadata = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 70 }, + Direction = FillDirection.Vertical, + Child = new OsuSpriteText + { + Text = play.Date.LocalDateTime.ToShortDateString(), + TextSize = 11, + Colour = OsuColour.Gray(0xAA), + Depth = -1, + }, + }, + modContainer = new ModContainer + { + AutoSizeAxes = Axes.Y, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Width = 60, + Margin = new MarginPadding{ Right = 140 } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour, LocalisationEngine locale) + { + stats.Add(new OsuSpriteText { + Text = play.PerformancePoints + "pp", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + TextSize = 18, + Font = "Exo2.0-BoldItalic", + }); + if(weight != -1) + { + stats.Add(new OsuSpriteText + { + Text = $"weighted: {(int)(play.PerformancePoints * weight)}pp ({weight.ToString("0%")})", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = colour.GrayA, + TextSize = 11, + Font = "Exo2.0-RegularItalic", + }); + } + stats.Add(new OsuSpriteText { + Text = "accuracy: " + play.Accuracy.ToString("0.00%"), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Colour = colour.GrayA, + TextSize = 11, + Font = "Exo2.0-RegularItalic", + }); + + metadata.Add(new LinkContainer + { + AutoSizeAxes = Axes.Both, + Url = $"https://osu.ppy.sh/beatmaps/{play.Beatmap.OnlineBeatmapID}", + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Current = locale.GetUnicodePreference($"{play.Beatmap.Metadata.TitleUnicode ?? play.Beatmap.Metadata.Title} [{play.Beatmap.Version}] ", $"{play.Beatmap.Metadata.Title ?? play.Beatmap.Metadata.TitleUnicode} [{play.Beatmap.Version}] "), + TextSize = 15, + Font = "Exo2.0-SemiBoldItalic", + }, + new OsuSpriteText + { + Current = locale.GetUnicodePreference(play.Beatmap.Metadata.ArtistUnicode, play.Beatmap.Metadata.Artist), + TextSize = 12, + Padding = new MarginPadding { Top = 3 }, + Font = "Exo2.0-RegularItalic", + }, + }, + }, + }); + + foreach (Mod mod in play.Mods) + modContainer.Add(new ModIcon(mod.Icon, colour.Yellow)); + } + + private class ModContainer : FlowContainer + { + protected override IEnumerable ComputeLayoutPositions() + { + int count = FlowingChildren.Count(); + for (int i = 0; i < count; i++) + yield return new Vector2(DrawWidth * i * (count == 1 ? 0 : 1f / (count - 1)), 0); + } + } + + private class ModIcon : Container + { + public ModIcon(FontAwesome icon, Color4 colour) + { + AutoSizeAxes = Axes.Both; + + Children = new[] + { + new TextAwesome + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Icon = FontAwesome.fa_osu_mod_bg, + Colour = colour, + Shadow = true, + TextSize = 30, + UseFullGlyphHeight = false, + }, + new TextAwesome + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Icon = icon, + Colour = OsuColour.Gray(84), + TextSize = 18, + Position = new Vector2(0f, 2f), + UseFullGlyphHeight = false, + }, + }; + } + } + + private class LinkContainer : OsuClickableContainer + { + public string Url; + + private Color4 hoverColour; + + public LinkContainer() + { + Action = () => Process.Start(Url); + } + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(Color4.White, 500, Easing.OutQuint); + base.OnHoverLost(state); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.Yellow; + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/Play.cs b/osu.Game/Overlays/Profile/Sections/Ranks/Play.cs new file mode 100644 index 0000000000..a9cbbcbef4 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Ranks/Play.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Database; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using System; +using System.Collections.Generic; + +namespace osu.Game.Overlays.Profile.Sections.Ranks +{ + public class Play + { + public ScoreRank Rank; + public BeatmapInfo Beatmap; + public DateTimeOffset Date; + public IEnumerable Mods; + public int PerformancePoints; + public double Accuracy; + } +} diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index 5ea135fcac..f19de5356c 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -1,6 +1,13 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Profile.Sections.Ranks; +using System; +using System.Collections.Generic; + namespace osu.Game.Overlays.Profile.Sections { public class RanksSection : ProfileSection @@ -8,5 +15,66 @@ namespace osu.Game.Overlays.Profile.Sections public override string Title => "Ranks"; public override string Identifier => "top_ranks"; + + private readonly FillFlowContainer best, firstPlace; + + public RanksSection() + { + Children = new Drawable[] + { + new OsuSpriteText { + TextSize = 15, + Text = "Best Performance", + Font = "Exo2.0-RegularItalic", + }, + best = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + }, + new OsuSpriteText { + TextSize = 15, + Text = "First Place Ranks", + Font = "Exo2.0-RegularItalic", + }, + firstPlace = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + }, + }; + } + + public IEnumerable BestPlays + { + set + { + int i = 0; + foreach (Play play in value) + { + best.Add(new DrawablePlay(play, Math.Pow(0.95, i)) + { + RelativeSizeAxes = Axes.X, + Height = 60, + }); + i++; + } + } + } + + public IEnumerable FirstPlacePlays + { + set + { + foreach (Play play in value) + firstPlace.Add(new DrawablePlay(play) + { + RelativeSizeAxes = Axes.X, + Height = 60, + }); + } + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6031304b26..b63ad6a271 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -98,6 +98,8 @@ + +