mirror of
https://github.com/ppy/osu.git
synced 2024-12-05 10:33:22 +08:00
Compare commits
10 Commits
7213b987b8
...
cb3069461c
Author | SHA1 | Date | |
---|---|---|---|
|
cb3069461c | ||
|
75695938e2 | ||
|
18a98c8e73 | ||
|
3b9c64b76f | ||
|
af092966e4 | ||
|
c6e4bf35de | ||
|
6f801e1695 | ||
|
7cc1a6040f | ||
|
05789e6fe4 | ||
|
99f28efc96 |
@ -0,0 +1,35 @@
|
||||
// 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 osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Screens.Ranking.Expanded;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
public class TestSceneExpandedPanelTopContent : OsuTestScene
|
||||
{
|
||||
public TestSceneExpandedPanelTopContent()
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(500, 200),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4Extensions.FromHex("#444"),
|
||||
},
|
||||
new ExpandedPanelTopContent(new User { Id = 2, Username = "peppy" }),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
143
osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs
Normal file
143
osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs
Normal file
@ -0,0 +1,143 @@
|
||||
// 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.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
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.Expanded;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
public class TestSceneScorePanel : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ScorePanel),
|
||||
typeof(PanelState),
|
||||
typeof(ExpandedPanelMiddleContent),
|
||||
typeof(ExpandedPanelTopContent),
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestDRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.5;
|
||||
score.Rank = ScoreRank.D;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.75;
|
||||
score.Rank = ScoreRank.C;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.85;
|
||||
score.Rank = ScoreRank.B;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestARank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.925;
|
||||
score.Rank = ScoreRank.A;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.975;
|
||||
score.Rank = ScoreRank.S;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAlmostSSRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 0.9999;
|
||||
score.Rank = ScoreRank.S;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSSRank()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Accuracy = 1;
|
||||
score.Rank = ScoreRank.X;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAllHitResults()
|
||||
{
|
||||
var score = createScore();
|
||||
score.Statistics[HitResult.Perfect] = 350;
|
||||
score.Statistics[HitResult.Ok] = 200;
|
||||
|
||||
addPanelStep(score);
|
||||
}
|
||||
|
||||
private void addPanelStep(ScoreInfo score) => AddStep("add panel", () =>
|
||||
{
|
||||
Child = new ScorePanel(score)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
State = PanelState.Expanded
|
||||
};
|
||||
});
|
||||
|
||||
private ScoreInfo createScore() => new ScoreInfo
|
||||
{
|
||||
User = new User
|
||||
{
|
||||
Id = 2,
|
||||
Username = "peppy",
|
||||
},
|
||||
Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo,
|
||||
Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() },
|
||||
TotalScore = 2845370,
|
||||
Accuracy = 0.95,
|
||||
MaxCombo = 999,
|
||||
Rank = ScoreRank.S,
|
||||
Date = DateTimeOffset.Now,
|
||||
Statistics =
|
||||
{
|
||||
{ HitResult.Miss, 1 },
|
||||
{ HitResult.Meh, 50 },
|
||||
{ HitResult.Good, 100 },
|
||||
{ HitResult.Great, 300 },
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -35,7 +35,9 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
private void load(LadderInfo ladder)
|
||||
{
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
currentMatch.BindValueChanged(matchChanged, true);
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
|
||||
updateMatch();
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
@ -43,10 +45,19 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
currentTeamScore.UnbindBindings();
|
||||
currentTeam.UnbindBindings();
|
||||
|
||||
if (match.NewValue != null)
|
||||
Scheduler.AddOnce(updateMatch);
|
||||
}
|
||||
|
||||
private void updateMatch()
|
||||
{
|
||||
var match = currentMatch.Value;
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score);
|
||||
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2);
|
||||
match.StartMatch();
|
||||
|
||||
currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.Team1Score : match.Team2Score);
|
||||
currentTeam.BindTo(teamColour == TeamColour.Red ? match.Team1 : match.Team2);
|
||||
}
|
||||
|
||||
// team may change to same team, which means score is not in a good state.
|
||||
|
@ -0,0 +1,15 @@
|
||||
// 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 osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Expanded
|
||||
{
|
||||
public class ExpandedPanelMiddleContent : CompositeDrawable
|
||||
{
|
||||
public ExpandedPanelMiddleContent(ScoreInfo score)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
64
osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs
Normal file
64
osu.Game/Screens/Ranking/Expanded/ExpandedPanelTopContent.cs
Normal file
@ -0,0 +1,64 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Users.Drawables;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Expanded
|
||||
{
|
||||
/// <summary>
|
||||
/// The content that appears in the middle section of the <see cref="ScorePanel"/>.
|
||||
/// </summary>
|
||||
public class ExpandedPanelTopContent : CompositeDrawable
|
||||
{
|
||||
private readonly User user;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ExpandedPanelTopContent"/>.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="User"/> to display.</param>
|
||||
public ExpandedPanelTopContent(User user)
|
||||
{
|
||||
this.user = user;
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new UpdateableAvatar(user)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(80),
|
||||
CornerRadius = 20,
|
||||
CornerExponent = 2.5f,
|
||||
Masking = true,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = user.Username,
|
||||
Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
11
osu.Game/Screens/Ranking/PanelState.cs
Normal file
11
osu.Game/Screens/Ranking/PanelState.cs
Normal file
@ -0,0 +1,11 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Screens.Ranking
|
||||
{
|
||||
public enum PanelState
|
||||
{
|
||||
Expanded,
|
||||
Contracted
|
||||
}
|
||||
}
|
223
osu.Game/Screens/Ranking/ScorePanel.cs
Normal file
223
osu.Game/Screens/Ranking/ScorePanel.cs
Normal file
@ -0,0 +1,223 @@
|
||||
// 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 osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Ranking.Expanded;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Ranking
|
||||
{
|
||||
public class ScorePanel : CompositeDrawable, IStateful<PanelState>
|
||||
{
|
||||
/// <summary>
|
||||
/// Width of the panel when contracted.
|
||||
/// </summary>
|
||||
private const float contracted_width = 160;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the panel when contracted.
|
||||
/// </summary>
|
||||
private const float contracted_height = 320;
|
||||
|
||||
/// <summary>
|
||||
/// Width of the panel when expanded.
|
||||
/// </summary>
|
||||
private const float expanded_width = 360;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the panel when expanded.
|
||||
/// </summary>
|
||||
private const float expanded_height = 560;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the top layer when the panel is expanded.
|
||||
/// </summary>
|
||||
private const float expanded_top_layer_height = 53;
|
||||
|
||||
/// <summary>
|
||||
/// Height of the top layer when the panel is contracted.
|
||||
/// </summary>
|
||||
private const float contracted_top_layer_height = 40;
|
||||
|
||||
/// <summary>
|
||||
/// Duration for the panel to resize into its expanded/contracted size.
|
||||
/// </summary>
|
||||
private const double resize_duration = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Delay after <see cref="resize_duration"/> before the top layer is expanded.
|
||||
/// </summary>
|
||||
private const double top_layer_expand_delay = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Duration for the top layer expansion.
|
||||
/// </summary>
|
||||
private const double top_layer_expand_duration = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Duration for the panel contents to fade in.
|
||||
/// </summary>
|
||||
private const double content_fade_duration = 50;
|
||||
|
||||
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");
|
||||
|
||||
public event Action<PanelState> StateChanged;
|
||||
|
||||
private readonly ScoreInfo score;
|
||||
|
||||
private Container topLayerContainer;
|
||||
private Drawable topLayerBackground;
|
||||
private Container topLayerContentContainer;
|
||||
private Drawable topLayerContent;
|
||||
|
||||
private Container middleLayerContainer;
|
||||
private Drawable middleLayerBackground;
|
||||
private Container middleLayerContentContainer;
|
||||
private Drawable middleLayerContent;
|
||||
|
||||
public ScorePanel(ScoreInfo score)
|
||||
{
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
topLayerContainer = new Container
|
||||
{
|
||||
Name = "Top layer",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 120,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 20,
|
||||
CornerExponent = 2.5f,
|
||||
Masking = true,
|
||||
Child = topLayerBackground = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
topLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
},
|
||||
middleLayerContainer = new Container
|
||||
{
|
||||
Name = "Middle layer",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 20,
|
||||
CornerExponent = 2.5f,
|
||||
Masking = true,
|
||||
Child = middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (state == PanelState.Expanded)
|
||||
{
|
||||
topLayerBackground.FadeColour(expanded_top_layer_colour);
|
||||
middleLayerBackground.FadeColour(expanded_middle_layer_colour);
|
||||
}
|
||||
else
|
||||
{
|
||||
topLayerBackground.FadeColour(contracted_top_layer_colour);
|
||||
middleLayerBackground.FadeColour(contracted_middle_layer_colour);
|
||||
}
|
||||
|
||||
updateState();
|
||||
}
|
||||
|
||||
private PanelState state = PanelState.Contracted;
|
||||
|
||||
public PanelState State
|
||||
{
|
||||
get => state;
|
||||
set
|
||||
{
|
||||
if (state == value)
|
||||
return;
|
||||
|
||||
state = value;
|
||||
|
||||
if (LoadState >= LoadState.Ready)
|
||||
updateState();
|
||||
|
||||
StateChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
topLayerContainer.MoveToY(0, resize_duration, Easing.OutQuint);
|
||||
middleLayerContainer.MoveToY(0, resize_duration, Easing.OutQuint);
|
||||
|
||||
topLayerContent?.FadeOut(content_fade_duration).Expire();
|
||||
middleLayerContent?.FadeOut(content_fade_duration).Expire();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case PanelState.Expanded:
|
||||
this.ResizeTo(new Vector2(expanded_width, expanded_height), resize_duration, Easing.OutQuint);
|
||||
|
||||
topLayerBackground.FadeColour(expanded_top_layer_colour, resize_duration, Easing.OutQuint);
|
||||
middleLayerBackground.FadeColour(expanded_middle_layer_colour, resize_duration, Easing.OutQuint);
|
||||
|
||||
topLayerContentContainer.Add(middleLayerContent = new ExpandedPanelTopContent(score.User).With(d => d.Alpha = 0));
|
||||
middleLayerContentContainer.Add(topLayerContent = new ExpandedPanelMiddleContent(score).With(d => d.Alpha = 0));
|
||||
break;
|
||||
|
||||
case PanelState.Contracted:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
using (BeginDelayedSequence(resize_duration + top_layer_expand_delay, true))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PanelState.Expanded:
|
||||
topLayerContainer.MoveToY(-expanded_top_layer_height / 2, top_layer_expand_duration, Easing.OutQuint);
|
||||
middleLayerContainer.MoveToY(expanded_top_layer_height / 2, top_layer_expand_duration, Easing.OutQuint);
|
||||
break;
|
||||
|
||||
case PanelState.Contracted:
|
||||
topLayerContainer.MoveToY(-contracted_top_layer_height / 2, top_layer_expand_duration, Easing.OutQuint);
|
||||
middleLayerContainer.MoveToY(contracted_top_layer_height / 2, top_layer_expand_duration, Easing.OutQuint);
|
||||
break;
|
||||
}
|
||||
|
||||
topLayerContent?.FadeIn(content_fade_duration);
|
||||
middleLayerContent?.FadeIn(content_fade_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user