Initial implementation of contracted score panel

This commit is contained in:
smoogipoo 2020-05-16 18:17:32 +09:00
parent 35623e8513
commit 2bde4fc3ee
4 changed files with 381 additions and 5 deletions

View File

@ -8,7 +8,7 @@ using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Scoring
{
internal class OsuScoreProcessor : ScoreProcessor
public class OsuScoreProcessor : ScoreProcessor
{
protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new OsuJudgementResult(hitObject, judgement);

View File

@ -0,0 +1,118 @@
// 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.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Contracted;
using osu.Game.Tests.Beatmaps;
using osu.Game.Users;
using osuTK;
namespace osu.Game.Tests.Visual.Ranking
{
public class TestSceneContractedPanelMiddleContent : OsuTestScene
{
[Resolved]
private RulesetStore rulesetStore { get; set; }
[Test]
public void TestMapWithKnownMapper()
{
var author = new User { Username = "mapper_name" };
AddStep("show example score", () => showPanel(createTestBeatmap(author), createTestScore()));
AddAssert("mapper name present", () => this.ChildrenOfType<OsuSpriteText>().Any(spriteText => spriteText.Text == "mapper_name"));
}
[Test]
public void TestMapWithUnknownMapper()
{
AddStep("show example score", () => showPanel(createTestBeatmap(null), createTestScore()));
AddAssert("mapped by text not present", () =>
this.ChildrenOfType<OsuSpriteText>().All(spriteText => !containsAny(spriteText.Text, "mapped", "by")));
}
private void showPanel(WorkingBeatmap workingBeatmap, ScoreInfo score)
{
Child = new ContractedPanelMiddleContentContainer(workingBeatmap, score);
}
private WorkingBeatmap createTestBeatmap(User author)
{
var beatmap = new TestBeatmap(rulesetStore.GetRuleset(0));
beatmap.Metadata.Author = author;
beatmap.Metadata.Title = "Verrrrrrrrrrrrrrrrrrry looooooooooooooooooooooooong beatmap title";
beatmap.Metadata.Artist = "Verrrrrrrrrrrrrrrrrrry looooooooooooooooooooooooong beatmap artist";
return new TestWorkingBeatmap(beatmap);
}
private ScoreInfo createTestScore() => new ScoreInfo
{
User = new User
{
Id = 2,
Username = "peppy",
},
Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo,
Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() },
TotalScore = 999999,
Accuracy = 0.95,
MaxCombo = 999,
Rank = ScoreRank.S,
Date = DateTimeOffset.Now,
Statistics =
{
{ HitResult.Miss, 1 },
{ HitResult.Meh, 50 },
{ HitResult.Good, 100 },
{ HitResult.Great, 300 },
}
};
private bool containsAny(string text, params string[] stringsToMatch) => stringsToMatch.Any(text.Contains);
private class ContractedPanelMiddleContentContainer : Container
{
[Cached]
private Bindable<WorkingBeatmap> workingBeatmap { get; set; }
public ContractedPanelMiddleContentContainer(WorkingBeatmap beatmap, ScoreInfo score)
{
workingBeatmap = new Bindable<WorkingBeatmap>(beatmap);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Size = new Vector2(ScorePanel.CONTRACTED_WIDTH, 700);
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4Extensions.FromHex("#353535"),
},
new ContractedPanelMiddleContent(score),
};
}
}
}
}

View File

@ -0,0 +1,255 @@
// 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.
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Leaderboards;
using osu.Game.Scoring;
using osu.Game.Screens.Play.HUD;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osu.Game.Utils;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.Ranking.Contracted
{
/// <summary>
/// The content that appears in the middle of a contracted <see cref="ScorePanel"/>.
/// </summary>
public class ContractedPanelMiddleContent : CompositeDrawable
{
private readonly ScoreInfo score;
/// <summary>
/// Creates a new <see cref="ContractedPanelMiddleContent"/>.
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to display.</param>
public ContractedPanelMiddleContent(ScoreInfo score)
{
this.score = score;
RelativeSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
InternalChild = new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Container
{
Name = "Background",
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerExponent = 2.5f,
CornerRadius = 20,
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.25f),
Type = EdgeEffectType.Shadow,
Radius = 1,
Offset = new Vector2(0, 4)
},
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4Extensions.FromHex("444")
},
new UserCoverBackground
{
RelativeSizeAxes = Axes.Both,
User = score.User,
},
}
},
new Container
{
Name = "Background overlay",
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Bottom = -1 },
Child = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerExponent = 2.5f,
CornerRadius = 20,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4Extensions.FromHex("#444"))
}
}
},
new Container
{
Name = "Foreground",
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding(10),
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new UpdateableAvatar(score.User)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Size = new Vector2(140),
Masking = true,
CornerExponent = 2.5f,
CornerRadius = 20,
EdgeEffect = new EdgeEffectParameters
{
Colour = Color4.Black.Opacity(0.25f),
Type = EdgeEffectType.Shadow,
Radius = 8,
Offset = new Vector2(0, 4),
}
},
new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = score.UserString,
Font = OsuFont.GetFont(size: 16, weight: FontWeight.SemiBold)
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
ChildrenEnumerable = score.SortedStatistics.Select(s => createStatistic(s.Key.GetDescription(), s.Value.ToString()))
},
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 10 },
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new[]
{
createStatistic("Max Combo", $"x{score.MaxCombo}"),
createStatistic("Accuracy", $"{score.Accuracy.FormatAccuracy()}"),
}
},
new ModDisplay
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AutoSizeAxes = Axes.Both,
ExpansionMode = ExpansionMode.AlwaysExpanded,
DisplayUnrankedText = false,
Current = { Value = score.Mods },
Scale = new Vector2(0.5f),
}
}
}
}
}
}
},
},
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Vertical = 5 },
Child = new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
{
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = score.TotalScore.ToString(),
Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, fixedWidth: true),
Spacing = new Vector2(-1, 0)
},
},
new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 2 },
Child = new DrawableRank(score.Rank)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}
}
},
},
RowDimensions = new[]
{
new Dimension(GridSizeMode.AutoSize),
}
}
}
},
},
RowDimensions = new[]
{
new Dimension(),
new Dimension(GridSizeMode.Absolute, 45),
}
};
}
private Drawable createStatistic(string key, string value) => new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Text = key,
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
},
new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Text = value,
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
Colour = Color4Extensions.FromHex("#FFDD55")
}
}
};
}
}

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking.Contracted;
using osu.Game.Screens.Ranking.Expanded;
using osuTK;
using osuTK.Graphics;
@ -21,12 +22,12 @@ namespace osu.Game.Screens.Ranking
/// <summary>
/// Width of the panel when contracted.
/// </summary>
private const float contracted_width = 160;
public const float CONTRACTED_WIDTH = 160;
/// <summary>
/// Height of the panel when contracted.
/// </summary>
private const float contracted_height = 320;
private const float contracted_height = 385;
/// <summary>
/// Width of the panel when expanded.
@ -71,7 +72,7 @@ namespace osu.Game.Screens.Ranking
private static readonly ColourInfo expanded_top_layer_colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#444"), Color4Extensions.FromHex("#333"));
private static readonly ColourInfo expanded_middle_layer_colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#555"), Color4Extensions.FromHex("#333"));
private static readonly Color4 contracted_top_layer_colour = Color4Extensions.FromHex("#353535");
private static readonly Color4 contracted_middle_layer_colour = Color4Extensions.FromHex("#444");
private static readonly Color4 contracted_middle_layer_colour = Color4Extensions.FromHex("#353535");
public event Action<PanelState> StateChanged;
@ -193,10 +194,12 @@ namespace osu.Game.Screens.Ranking
break;
case PanelState.Contracted:
this.ResizeTo(new Vector2(contracted_width, contracted_height), resize_duration, Easing.OutQuint);
this.ResizeTo(new Vector2(CONTRACTED_WIDTH, contracted_height), resize_duration, Easing.OutQuint);
topLayerBackground.FadeColour(contracted_top_layer_colour, resize_duration, Easing.OutQuint);
middleLayerBackground.FadeColour(contracted_middle_layer_colour, resize_duration, Easing.OutQuint);
middleLayerContentContainer.Add(topLayerContent = new ContractedPanelMiddleContent(score).With(d => d.Alpha = 0));
break;
}