mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 15:44:04 +09:00
Merge remote-tracking branch 'refs/remotes/ppy/master' into friends-layout-split
This commit is contained in:
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.314.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.317.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -417,7 +417,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task TestImportWithDuplicateHashes()
|
public async Task TestImportWithDuplicateHashes()
|
||||||
{
|
{
|
||||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportNestedStructure)))
|
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestImportWithDuplicateHashes)))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,7 @@ using osu.Game.Screens;
|
|||||||
using osu.Game.Screens.Backgrounds;
|
using osu.Game.Screens.Backgrounds;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.PlayerSettings;
|
using osu.Game.Screens.Play.PlayerSettings;
|
||||||
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Tests.Resources;
|
using osu.Game.Tests.Resources;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -203,7 +204,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if the visual settings container removes user dim when suspending <see cref="Player"/> for <see cref="SoloResults"/>
|
/// Check if the visual settings container removes user dim when suspending <see cref="Player"/> for <see cref="ResultsScreen"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TransitionTest()
|
public void TransitionTest()
|
||||||
@ -335,7 +336,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
public bool IsBackgroundCurrent() => ((FadeAccessibleBackground)Background).IsCurrentScreen();
|
public bool IsBackgroundCurrent() => ((FadeAccessibleBackground)Background).IsCurrentScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FadeAccessibleResults : SoloResults
|
private class FadeAccessibleResults : ResultsScreen
|
||||||
{
|
{
|
||||||
public FadeAccessibleResults(ScoreInfo score)
|
public FadeAccessibleResults(ScoreInfo score)
|
||||||
: base(score)
|
: base(score)
|
||||||
|
@ -11,7 +11,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Ranking.Pages;
|
using osu.Game.Screens.Ranking;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
// 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 System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Multi.Match.Components;
|
|
||||||
using osu.Game.Screens.Multi.Ranking;
|
|
||||||
using osu.Game.Screens.Multi.Ranking.Pages;
|
|
||||||
using osu.Game.Screens.Multi.Ranking.Types;
|
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
using osu.Game.Users;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Multiplayer
|
|
||||||
{
|
|
||||||
public class TestSceneMatchResults : MultiplayerTestScene
|
|
||||||
{
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
|
||||||
{
|
|
||||||
typeof(MatchResults),
|
|
||||||
typeof(RoomLeaderboardPageInfo),
|
|
||||||
typeof(RoomLeaderboardPage)
|
|
||||||
};
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private BeatmapManager beatmaps { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0);
|
|
||||||
if (beatmapInfo != null)
|
|
||||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
|
|
||||||
|
|
||||||
Room.RoomID.Value = 1;
|
|
||||||
Room.Name.Value = "an awesome room";
|
|
||||||
|
|
||||||
LoadScreen(new TestMatchResults(new ScoreInfo
|
|
||||||
{
|
|
||||||
User = new User { Id = 10 },
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestMatchResults : MatchResults
|
|
||||||
{
|
|
||||||
public TestMatchResults(ScoreInfo score)
|
|
||||||
: base(score)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap.Value) };
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo
|
|
||||||
{
|
|
||||||
private readonly ScoreInfo score;
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
|
||||||
|
|
||||||
public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
: base(score, beatmap)
|
|
||||||
{
|
|
||||||
this.score = score;
|
|
||||||
this.beatmap = beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestRoomLeaderboardPage : RoomLeaderboardPage
|
|
||||||
{
|
|
||||||
public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
: base(score, beatmap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override MatchLeaderboard CreateLeaderboard() => new TestMatchLeaderboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard
|
|
||||||
{
|
|
||||||
protected override APIRequest FetchScores(Action<IEnumerable<APIUserScoreAggregate>> scoresCallback)
|
|
||||||
{
|
|
||||||
var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray();
|
|
||||||
|
|
||||||
scoresCallback?.Invoke(scores);
|
|
||||||
ScoresLoaded?.Invoke(scores);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private APIUserScoreAggregate createRoomScore(int id) => new APIUserScoreAggregate
|
|
||||||
{
|
|
||||||
User = new User { Id = id, Username = $"User {id}" },
|
|
||||||
Accuracy = 0.98,
|
|
||||||
TotalScore = 987654,
|
|
||||||
TotalAttempts = 13,
|
|
||||||
CompletedBeatmaps = 5
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
155
osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
Normal file
155
osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
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.Expanded.Accuracy;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
|
{
|
||||||
|
public class TestSceneAccuracyCircle : OsuTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(AccuracyCircle),
|
||||||
|
typeof(RankBadge),
|
||||||
|
typeof(RankNotch),
|
||||||
|
typeof(RankText),
|
||||||
|
typeof(SmoothCircularProgress)
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.5;
|
||||||
|
score.Rank = ScoreRank.D;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.75;
|
||||||
|
score.Rank = ScoreRank.C;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.85;
|
||||||
|
score.Rank = ScoreRank.B;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestARank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.925;
|
||||||
|
score.Rank = ScoreRank.A;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.975;
|
||||||
|
score.Rank = ScoreRank.S;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAlmostSSRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 0.9999;
|
||||||
|
score.Rank = ScoreRank.S;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSSRank()
|
||||||
|
{
|
||||||
|
var score = createScore();
|
||||||
|
score.Accuracy = 1;
|
||||||
|
score.Rank = ScoreRank.X;
|
||||||
|
|
||||||
|
addCircleStep(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCircleStep(ScoreInfo score) => AddStep("add panel", () =>
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(500, 700),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#555"), Color4Extensions.FromHex("#333"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AccuracyCircle(score)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(230)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
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 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
// 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 osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
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.Expanded;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Statistics;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
|
{
|
||||||
|
public class TestSceneExpandedPanelMiddleContent : OsuTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(ExpandedPanelMiddleContent),
|
||||||
|
typeof(AccuracyCircle),
|
||||||
|
typeof(AccuracyStatistic),
|
||||||
|
typeof(ComboStatistic),
|
||||||
|
typeof(CounterStatistic),
|
||||||
|
typeof(StarRatingDisplay),
|
||||||
|
typeof(StatisticDisplay),
|
||||||
|
typeof(TotalScoreCounter)
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestSceneExpandedPanelMiddleContent()
|
||||||
|
{
|
||||||
|
Child = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(500, 700),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#444"),
|
||||||
|
},
|
||||||
|
new ExpandedPanelMiddleContent(createTestScore())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -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" }),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,29 +10,27 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Game.Screens.Ranking.Pages;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneResults : ScreenTestScene
|
public class TestSceneResultsScreen : ScreenTestScene
|
||||||
{
|
{
|
||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(Results),
|
typeof(ResultsScreen),
|
||||||
typeof(ResultsPage),
|
|
||||||
typeof(ScoreResultsPage),
|
|
||||||
typeof(RetryButton),
|
typeof(RetryButton),
|
||||||
typeof(ReplayDownloadButton),
|
typeof(ReplayDownloadButton),
|
||||||
typeof(LocalLeaderboardPage),
|
|
||||||
typeof(TestPlayer)
|
typeof(TestPlayer)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,6 +63,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{ HitResult.Meh, 50 },
|
{ HitResult.Meh, 50 },
|
||||||
{ HitResult.Miss, 1 }
|
{ HitResult.Miss, 1 }
|
||||||
},
|
},
|
||||||
|
Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo,
|
||||||
User = new User
|
User = new User
|
||||||
{
|
{
|
||||||
Username = "peppy",
|
Username = "peppy",
|
||||||
@ -119,7 +118,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestSoloResults : SoloResults
|
private class TestSoloResults : ResultsScreen
|
||||||
{
|
{
|
||||||
public HotkeyRetryOverlay RetryOverlay;
|
public HotkeyRetryOverlay RetryOverlay;
|
||||||
|
|
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 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
32
osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs
Normal file
32
osu.Game.Tests/Visual/Ranking/TestSceneStarRatingDisplay.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
|
{
|
||||||
|
public class TestSceneStarRatingDisplay : OsuTestScene
|
||||||
|
{
|
||||||
|
public TestSceneStarRatingDisplay()
|
||||||
|
{
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 1.23 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 2.34 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 3.45 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 4.56 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 5.67 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 6.78 }),
|
||||||
|
new StarRatingDisplay(new BeatmapInfo { StarDifficulty = 10.11 }),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
// 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 osu.Framework.Graphics;
|
||||||
|
using osu.Game.Tournament.Components;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.Components
|
||||||
|
{
|
||||||
|
public class TestSceneRoundDisplay : TournamentTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(DrawableTournamentHeaderText),
|
||||||
|
typeof(DrawableTournamentHeaderLogo),
|
||||||
|
};
|
||||||
|
|
||||||
|
public TestSceneRoundDisplay()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new RoundDisplay(new TournamentMatch
|
||||||
|
{
|
||||||
|
Round =
|
||||||
|
{
|
||||||
|
Value = new TournamentRound
|
||||||
|
{
|
||||||
|
Name = { Value = "Test Round" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding(20)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,9 +11,13 @@ namespace osu.Game.Tournament.Components
|
|||||||
{
|
{
|
||||||
public class DrawableTournamentHeaderText : CompositeDrawable
|
public class DrawableTournamentHeaderText : CompositeDrawable
|
||||||
{
|
{
|
||||||
public DrawableTournamentHeaderText()
|
public DrawableTournamentHeaderText(bool center = true)
|
||||||
{
|
{
|
||||||
InternalChild = new TextSprite();
|
InternalChild = new TextSprite
|
||||||
|
{
|
||||||
|
Anchor = center ? Anchor.Centre : Anchor.TopLeft,
|
||||||
|
Origin = center ? Anchor.Centre : Anchor.TopLeft,
|
||||||
|
};
|
||||||
|
|
||||||
Height = 22;
|
Height = 22;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
@ -27,9 +31,6 @@ namespace osu.Game.Tournament.Components
|
|||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
FillMode = FillMode.Fit;
|
FillMode = FillMode.Fit;
|
||||||
|
|
||||||
Anchor = Anchor.Centre;
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
|
|
||||||
Texture = textures.Get("header-text");
|
Texture = textures.Get("header-text");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,19 +12,27 @@ namespace osu.Game.Tournament.Components
|
|||||||
{
|
{
|
||||||
public RoundDisplay(TournamentMatch match)
|
public RoundDisplay(TournamentMatch match)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Y;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DrawableTournamentHeaderText(),
|
new DrawableTournamentHeaderText(false)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
|
},
|
||||||
new TournamentSpriteText
|
new TournamentSpriteText
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.TopLeft,
|
||||||
|
Origin = Anchor.TopLeft,
|
||||||
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
|
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
|
||||||
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.SemiBold)
|
Font = OsuFont.Torus.With(size: 26, weight: FontWeight.SemiBold)
|
||||||
},
|
},
|
||||||
|
@ -35,7 +35,9 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
|||||||
private void load(LadderInfo ladder)
|
private void load(LadderInfo ladder)
|
||||||
{
|
{
|
||||||
currentMatch.BindTo(ladder.CurrentMatch);
|
currentMatch.BindTo(ladder.CurrentMatch);
|
||||||
currentMatch.BindValueChanged(matchChanged, true);
|
currentMatch.BindValueChanged(matchChanged);
|
||||||
|
|
||||||
|
updateMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||||
@ -43,10 +45,19 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
|||||||
currentTeamScore.UnbindBindings();
|
currentTeamScore.UnbindBindings();
|
||||||
currentTeam.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);
|
match.StartMatch();
|
||||||
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2);
|
|
||||||
|
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.
|
// team may change to same team, which means score is not in a good state.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
@ -60,8 +61,9 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
|
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
|
||||||
/// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param>
|
/// <param name="mods">The <see cref="Mod"/>s to apply to the <see cref="IBeatmap"/>.</param>
|
||||||
|
/// <param name="timeout">The maximum length in milliseconds to wait for load to complete. Defaults to 10,000ms.</param>
|
||||||
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
||||||
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
||||||
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null);
|
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,55 +83,81 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
|
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
|
||||||
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
|
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
|
||||||
|
|
||||||
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null)
|
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
mods ??= Array.Empty<Mod>();
|
using (var cancellationSource = new CancellationTokenSource(timeout ?? TimeSpan.FromSeconds(10)))
|
||||||
|
|
||||||
var rulesetInstance = ruleset.CreateInstance();
|
|
||||||
|
|
||||||
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
|
||||||
|
|
||||||
// Check if the beatmap can be converted
|
|
||||||
if (Beatmap.HitObjects.Count > 0 && !converter.CanConvert())
|
|
||||||
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");
|
|
||||||
|
|
||||||
// Apply conversion mods
|
|
||||||
foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>())
|
|
||||||
mod.ApplyToBeatmapConverter(converter);
|
|
||||||
|
|
||||||
// Convert
|
|
||||||
IBeatmap converted = converter.Convert();
|
|
||||||
|
|
||||||
// Apply difficulty mods
|
|
||||||
if (mods.Any(m => m is IApplicableToDifficulty))
|
|
||||||
{
|
{
|
||||||
converted.BeatmapInfo = converted.BeatmapInfo.Clone();
|
mods ??= Array.Empty<Mod>();
|
||||||
converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone();
|
|
||||||
|
|
||||||
foreach (var mod in mods.OfType<IApplicableToDifficulty>())
|
var rulesetInstance = ruleset.CreateInstance();
|
||||||
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
|
|
||||||
}
|
|
||||||
|
|
||||||
IBeatmapProcessor processor = rulesetInstance.CreateBeatmapProcessor(converted);
|
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
||||||
|
|
||||||
processor?.PreProcess();
|
// Check if the beatmap can be converted
|
||||||
|
if (Beatmap.HitObjects.Count > 0 && !converter.CanConvert())
|
||||||
|
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");
|
||||||
|
|
||||||
// Compute default values for hitobjects, including creating nested hitobjects in-case they're needed
|
// Apply conversion mods
|
||||||
foreach (var obj in converted.HitObjects)
|
foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>())
|
||||||
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
{
|
||||||
|
if (cancellationSource.IsCancellationRequested)
|
||||||
|
throw new BeatmapLoadTimeoutException(BeatmapInfo);
|
||||||
|
|
||||||
foreach (var mod in mods.OfType<IApplicableToHitObject>())
|
mod.ApplyToBeatmapConverter(converter);
|
||||||
{
|
}
|
||||||
|
|
||||||
|
// Convert
|
||||||
|
IBeatmap converted = converter.Convert();
|
||||||
|
|
||||||
|
// Apply difficulty mods
|
||||||
|
if (mods.Any(m => m is IApplicableToDifficulty))
|
||||||
|
{
|
||||||
|
converted.BeatmapInfo = converted.BeatmapInfo.Clone();
|
||||||
|
converted.BeatmapInfo.BaseDifficulty = converted.BeatmapInfo.BaseDifficulty.Clone();
|
||||||
|
|
||||||
|
foreach (var mod in mods.OfType<IApplicableToDifficulty>())
|
||||||
|
{
|
||||||
|
if (cancellationSource.IsCancellationRequested)
|
||||||
|
throw new BeatmapLoadTimeoutException(BeatmapInfo);
|
||||||
|
|
||||||
|
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IBeatmapProcessor processor = rulesetInstance.CreateBeatmapProcessor(converted);
|
||||||
|
|
||||||
|
processor?.PreProcess();
|
||||||
|
|
||||||
|
// Compute default values for hitobjects, including creating nested hitobjects in-case they're needed
|
||||||
foreach (var obj in converted.HitObjects)
|
foreach (var obj in converted.HitObjects)
|
||||||
mod.ApplyToHitObject(obj);
|
{
|
||||||
|
if (cancellationSource.IsCancellationRequested)
|
||||||
|
throw new BeatmapLoadTimeoutException(BeatmapInfo);
|
||||||
|
|
||||||
|
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var mod in mods.OfType<IApplicableToHitObject>())
|
||||||
|
{
|
||||||
|
foreach (var obj in converted.HitObjects)
|
||||||
|
{
|
||||||
|
if (cancellationSource.IsCancellationRequested)
|
||||||
|
throw new BeatmapLoadTimeoutException(BeatmapInfo);
|
||||||
|
|
||||||
|
mod.ApplyToHitObject(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processor?.PostProcess();
|
||||||
|
|
||||||
|
foreach (var mod in mods.OfType<IApplicableToBeatmap>())
|
||||||
|
{
|
||||||
|
cancellationSource.Token.ThrowIfCancellationRequested();
|
||||||
|
mod.ApplyToBeatmap(converted);
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
processor?.PostProcess();
|
|
||||||
|
|
||||||
foreach (var mod in mods.OfType<IApplicableToBeatmap>())
|
|
||||||
mod.ApplyToBeatmap(converted);
|
|
||||||
|
|
||||||
return converted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CancellationTokenSource loadCancellation = new CancellationTokenSource();
|
private CancellationTokenSource loadCancellation = new CancellationTokenSource();
|
||||||
@ -297,5 +323,13 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
|
private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class BeatmapLoadTimeoutException : TimeoutException
|
||||||
|
{
|
||||||
|
public BeatmapLoadTimeoutException(BeatmapInfo beatmapInfo)
|
||||||
|
: base($"Timed out while loading beatmap ({beatmapInfo}).")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Scoring;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Graphics
|
namespace osu.Game.Graphics
|
||||||
@ -37,6 +38,35 @@ namespace osu.Game.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the colour for a <see cref="ScoreRank"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static Color4 ForRank(ScoreRank rank)
|
||||||
|
{
|
||||||
|
switch (rank)
|
||||||
|
{
|
||||||
|
case ScoreRank.XH:
|
||||||
|
case ScoreRank.X:
|
||||||
|
return Color4Extensions.FromHex(@"ce1c9d");
|
||||||
|
|
||||||
|
case ScoreRank.SH:
|
||||||
|
case ScoreRank.S:
|
||||||
|
return Color4Extensions.FromHex(@"00a8b5");
|
||||||
|
|
||||||
|
case ScoreRank.A:
|
||||||
|
return Color4Extensions.FromHex(@"7cce14");
|
||||||
|
|
||||||
|
case ScoreRank.B:
|
||||||
|
return Color4Extensions.FromHex(@"e3b130");
|
||||||
|
|
||||||
|
case ScoreRank.C:
|
||||||
|
return Color4Extensions.FromHex(@"f18252");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return Color4Extensions.FromHex(@"e95353");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less
|
// See https://github.com/ppy/osu-web/blob/master/resources/assets/less/colors.less
|
||||||
public readonly Color4 PurpleLighter = Color4Extensions.FromHex(@"eeeeff");
|
public readonly Color4 PurpleLighter = Color4Extensions.FromHex(@"eeeeff");
|
||||||
public readonly Color4 PurpleLight = Color4Extensions.FromHex(@"aa88ff");
|
public readonly Color4 PurpleLight = Color4Extensions.FromHex(@"aa88ff");
|
||||||
|
@ -43,6 +43,18 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
set => blurredText.Colour = value;
|
set => blurredText.Colour = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector2 Spacing
|
||||||
|
{
|
||||||
|
get => spriteText.Spacing;
|
||||||
|
set => spriteText.Spacing = blurredText.Spacing = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseFullGlyphHeight
|
||||||
|
{
|
||||||
|
get => spriteText.UseFullGlyphHeight;
|
||||||
|
set => spriteText.UseFullGlyphHeight = blurredText.UseFullGlyphHeight = value;
|
||||||
|
}
|
||||||
|
|
||||||
public GlowingSpriteText()
|
public GlowingSpriteText()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
FillMode = FillMode.Fit;
|
FillMode = FillMode.Fit;
|
||||||
FillAspectRatio = 2;
|
FillAspectRatio = 2;
|
||||||
|
|
||||||
var rankColour = getRankColour();
|
var rankColour = OsuColour.ForRank(rank);
|
||||||
InternalChild = new DrawSizePreservingFillContainer
|
InternalChild = new DrawSizePreservingFillContainer
|
||||||
{
|
{
|
||||||
TargetDrawSize = new Vector2(64, 32),
|
TargetDrawSize = new Vector2(64, 32),
|
||||||
@ -59,7 +59,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
Padding = new MarginPadding { Top = 5 },
|
Padding = new MarginPadding { Top = 5 },
|
||||||
Colour = getRankNameColour(),
|
Colour = getRankNameColour(),
|
||||||
Font = OsuFont.Numeric.With(size: 25),
|
Font = OsuFont.Numeric.With(size: 25),
|
||||||
Text = getRankName(),
|
Text = GetRankName(rank),
|
||||||
ShadowColour = Color4.Black.Opacity(0.3f),
|
ShadowColour = Color4.Black.Opacity(0.3f),
|
||||||
ShadowOffset = new Vector2(0, 0.08f),
|
ShadowOffset = new Vector2(0, 0.08f),
|
||||||
Shadow = true,
|
Shadow = true,
|
||||||
@ -69,36 +69,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getRankName() => rank.GetDescription().TrimEnd('+');
|
public static string GetRankName(ScoreRank rank) => rank.GetDescription().TrimEnd('+');
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the grade background colour.
|
|
||||||
/// </summary>
|
|
||||||
private Color4 getRankColour()
|
|
||||||
{
|
|
||||||
switch (rank)
|
|
||||||
{
|
|
||||||
case ScoreRank.XH:
|
|
||||||
case ScoreRank.X:
|
|
||||||
return Color4Extensions.FromHex(@"ce1c9d");
|
|
||||||
|
|
||||||
case ScoreRank.SH:
|
|
||||||
case ScoreRank.S:
|
|
||||||
return Color4Extensions.FromHex(@"00a8b5");
|
|
||||||
|
|
||||||
case ScoreRank.A:
|
|
||||||
return Color4Extensions.FromHex(@"7cce14");
|
|
||||||
|
|
||||||
case ScoreRank.B:
|
|
||||||
return Color4Extensions.FromHex(@"e3b130");
|
|
||||||
|
|
||||||
case ScoreRank.C:
|
|
||||||
return Color4Extensions.FromHex(@"f18252");
|
|
||||||
|
|
||||||
default:
|
|
||||||
return Color4Extensions.FromHex(@"e95353");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the grade text colour.
|
/// Retrieves the grade text colour.
|
||||||
|
@ -148,7 +148,7 @@ namespace osu.Game.Overlays.News
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Font = OsuFont.GetFont(Typeface.Torus, 12, FontWeight.Black, false, false),
|
Font = OsuFont.GetFont(Typeface.Torus, 12, FontWeight.Bold, false, false),
|
||||||
Text = date.ToString("d MMM yyy").ToUpper(),
|
Text = date.ToString("d MMM yyy").ToUpper(),
|
||||||
Margin = new MarginPadding
|
Margin = new MarginPadding
|
||||||
{
|
{
|
||||||
|
@ -84,13 +84,13 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = titleText.ToUpperInvariant(),
|
Text = titleText.ToUpperInvariant(),
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Black)
|
Font = OsuFont.GetFont(weight: FontWeight.Bold)
|
||||||
},
|
},
|
||||||
countDrawable = new OsuSpriteText
|
countDrawable = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = "3",
|
Text = "3",
|
||||||
Colour = colours.Yellow,
|
Colour = colours.Yellow,
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Black)
|
Font = OsuFont.GetFont(weight: FontWeight.Bold)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Overlays.OSD
|
|||||||
{
|
{
|
||||||
Padding = new MarginPadding(10),
|
Padding = new MarginPadding(10),
|
||||||
Name = "Description",
|
Name = "Description",
|
||||||
Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black),
|
Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold),
|
||||||
Spacing = new Vector2(1, 0),
|
Spacing = new Vector2(1, 0),
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Overlays
|
|||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = MainText,
|
Text = MainText,
|
||||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black),
|
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
|
||||||
},
|
},
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
{
|
{
|
||||||
Text = "ACCOUNT",
|
Text = "ACCOUNT",
|
||||||
Margin = new MarginPadding { Bottom = 5 },
|
Margin = new MarginPadding { Bottom = 5 },
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Black),
|
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
||||||
},
|
},
|
||||||
form = new LoginForm
|
form = new LoginForm
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
{
|
{
|
||||||
Text = Header.ToUpperInvariant(),
|
Text = Header.ToUpperInvariant(),
|
||||||
Margin = new MarginPadding { Bottom = 10, Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS },
|
Margin = new MarginPadding { Bottom = 10, Left = SettingsPanel.CONTENT_MARGINS, Right = SettingsPanel.CONTENT_MARGINS },
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Black),
|
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
||||||
},
|
},
|
||||||
FlowContent
|
FlowContent
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,7 @@ using osuTK.Input;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework;
|
using osu.Framework;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
@ -86,7 +87,18 @@ namespace osu.Game.Screens.Edit
|
|||||||
// todo: remove caching of this and consume via editorBeatmap?
|
// todo: remove caching of this and consume via editorBeatmap?
|
||||||
dependencies.Cache(beatDivisor);
|
dependencies.Cache(beatDivisor);
|
||||||
|
|
||||||
playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset);
|
try
|
||||||
|
{
|
||||||
|
playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Beatmap.Value.BeatmapInfo.Ruleset);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, "Could not load beatmap successfully!");
|
||||||
|
// couldn't load, hard abort!
|
||||||
|
this.Exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap));
|
AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap));
|
||||||
|
|
||||||
dependencies.CacheAs(editorBeatmap);
|
dependencies.CacheAs(editorBeatmap);
|
||||||
|
@ -152,7 +152,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
public HeaderText(string text)
|
public HeaderText(string text)
|
||||||
{
|
{
|
||||||
Text = text.ToUpper();
|
Text = text.ToUpper();
|
||||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black);
|
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,7 @@ using osu.Game.Online.API.Requests;
|
|||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Multi.Ranking;
|
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Multi.Play
|
namespace osu.Game.Screens.Multi.Play
|
||||||
{
|
{
|
||||||
@ -115,7 +113,5 @@ namespace osu.Game.Screens.Multi.Play
|
|||||||
|
|
||||||
Exited = null;
|
Exited = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Results CreateResults(ScoreInfo score) => new MatchResults(score);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// 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.Collections.Generic;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Multi.Ranking.Types;
|
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
using osu.Game.Screens.Ranking.Types;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Multi.Ranking
|
|
||||||
{
|
|
||||||
public class MatchResults : Results
|
|
||||||
{
|
|
||||||
public MatchResults(ScoreInfo score)
|
|
||||||
: base(score)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
|
|
||||||
{
|
|
||||||
new ScoreOverviewPageInfo(Score, Beatmap.Value),
|
|
||||||
new LocalLeaderboardPageInfo(Score, Beatmap.Value),
|
|
||||||
new RoomLeaderboardPageInfo(Score, Beatmap.Value),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
// 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.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Internal;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Lists;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Online.Leaderboards;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Multi.Match.Components;
|
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Multi.Ranking.Pages
|
|
||||||
{
|
|
||||||
public class RoomLeaderboardPage : ResultsPage
|
|
||||||
{
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
private TextFlowContainer rankText;
|
|
||||||
|
|
||||||
[Resolved(typeof(Room), nameof(Room.Name))]
|
|
||||||
private Bindable<string> name { get; set; }
|
|
||||||
|
|
||||||
public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
: base(score, beatmap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
MatchLeaderboard leaderboard;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Colour = colours.Gray6,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
new BufferedContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
BackgroundColour = colours.Gray6,
|
|
||||||
Child = leaderboard = CreateLeaderboard()
|
|
||||||
},
|
|
||||||
rankText = new TextFlowContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Width = 0.5f,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Y = 50,
|
|
||||||
TextAnchor = Anchor.TopCentre
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
leaderboard.Origin = Anchor.Centre;
|
|
||||||
leaderboard.Anchor = Anchor.Centre;
|
|
||||||
leaderboard.RelativeSizeAxes = Axes.Both;
|
|
||||||
leaderboard.Height = 0.8f;
|
|
||||||
leaderboard.Y = 55;
|
|
||||||
leaderboard.ScoresLoaded = scoresLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scoresLoaded(IEnumerable<APIUserScoreAggregate> scores)
|
|
||||||
{
|
|
||||||
void gray(SpriteText s) => s.Colour = colours.GrayC;
|
|
||||||
|
|
||||||
void white(SpriteText s)
|
|
||||||
{
|
|
||||||
s.Font = s.Font.With(size: s.Font.Size * 1.4f);
|
|
||||||
s.Colour = colours.GrayF;
|
|
||||||
}
|
|
||||||
|
|
||||||
rankText.AddText(name + "\n", white);
|
|
||||||
rankText.AddText("You are placed ", gray);
|
|
||||||
|
|
||||||
int index = scores.IndexOf(new APIUserScoreAggregate { User = Score.User }, new FuncEqualityComparer<APIUserScoreAggregate>((s1, s2) => s1.User.Id.Equals(s2.User.Id)));
|
|
||||||
|
|
||||||
rankText.AddText($"#{index + 1} ", s =>
|
|
||||||
{
|
|
||||||
s.Font = s.Font.With(Typeface.Torus, weight: FontWeight.Bold);
|
|
||||||
s.Colour = colours.YellowDark;
|
|
||||||
});
|
|
||||||
|
|
||||||
rankText.AddText("in the room!", gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual MatchLeaderboard CreateLeaderboard() => new ResultsMatchLeaderboard();
|
|
||||||
|
|
||||||
public class ResultsMatchLeaderboard : MatchLeaderboard
|
|
||||||
{
|
|
||||||
protected override bool FadeTop => true;
|
|
||||||
|
|
||||||
protected override LeaderboardScore CreateDrawableScore(APIUserScoreAggregate model, int index)
|
|
||||||
=> new ResultsMatchLeaderboardScore(model, index);
|
|
||||||
|
|
||||||
protected override FillFlowContainer<LeaderboardScore> CreateScoreFlow()
|
|
||||||
{
|
|
||||||
var flow = base.CreateScoreFlow();
|
|
||||||
flow.Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Top = LeaderboardScore.HEIGHT * 2,
|
|
||||||
Bottom = LeaderboardScore.HEIGHT * 3,
|
|
||||||
};
|
|
||||||
return flow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ResultsMatchLeaderboardScore : MatchLeaderboardScore
|
|
||||||
{
|
|
||||||
public ResultsMatchLeaderboardScore(APIUserScoreAggregate score, int rank)
|
|
||||||
: base(score, rank)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
// 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.Sprites;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Multi.Ranking.Pages;
|
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Multi.Ranking.Types
|
|
||||||
{
|
|
||||||
public class RoomLeaderboardPageInfo : IResultPageInfo
|
|
||||||
{
|
|
||||||
private readonly ScoreInfo score;
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
|
||||||
|
|
||||||
public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
{
|
|
||||||
this.score = score;
|
|
||||||
this.beatmap = beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IconUsage Icon => FontAwesome.Solid.Users;
|
|
||||||
|
|
||||||
public string Name => "Room Leaderboard";
|
|
||||||
|
|
||||||
public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap);
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,7 +30,7 @@ namespace osu.Game.Screens.Play.Break
|
|||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Text = "current progress".ToUpperInvariant(),
|
Text = "current progress".ToUpperInvariant(),
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Black, size: 15),
|
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15),
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
|
@ -401,14 +401,18 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected virtual ScoreInfo CreateScore()
|
protected virtual ScoreInfo CreateScore()
|
||||||
{
|
{
|
||||||
var score = DrawableRuleset.ReplayScore?.ScoreInfo ?? new ScoreInfo
|
var score = new ScoreInfo
|
||||||
{
|
{
|
||||||
Beatmap = Beatmap.Value.BeatmapInfo,
|
Beatmap = Beatmap.Value.BeatmapInfo,
|
||||||
Ruleset = rulesetInfo,
|
Ruleset = rulesetInfo,
|
||||||
Mods = Mods.Value.ToArray(),
|
Mods = Mods.Value.ToArray(),
|
||||||
User = api.LocalUser.Value,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (DrawableRuleset.ReplayScore != null)
|
||||||
|
score.User = DrawableRuleset.ReplayScore.ScoreInfo?.User ?? new GuestUser();
|
||||||
|
else
|
||||||
|
score.User = api.LocalUser.Value;
|
||||||
|
|
||||||
ScoreProcessor.PopulateScore(score);
|
ScoreProcessor.PopulateScore(score);
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
@ -416,7 +420,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !GameplayClockContainer.IsPaused.Value;
|
protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !GameplayClockContainer.IsPaused.Value;
|
||||||
|
|
||||||
protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score);
|
protected virtual ResultsScreen CreateResults(ScoreInfo score) => new ResultsScreen(score);
|
||||||
|
|
||||||
#region Fail Logic
|
#region Fail Logic
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// 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.Collections.Generic;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Ranking;
|
|
||||||
using osu.Game.Screens.Ranking.Types;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
|
||||||
{
|
|
||||||
public class SoloResults : Results
|
|
||||||
{
|
|
||||||
public SoloResults(ScoreInfo score)
|
|
||||||
: base(score)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<IResultPageInfo> CreateResultPages() => new IResultPageInfo[]
|
|
||||||
{
|
|
||||||
new ScoreOverviewPageInfo(Score, Beatmap.Value),
|
|
||||||
new LocalLeaderboardPageInfo(Score, Beatmap.Value)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
253
osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
Normal file
253
osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The component that displays the player's accuracy on the results screen.
|
||||||
|
/// </summary>
|
||||||
|
public class AccuracyCircle : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Duration for the transforms causing this component to appear.
|
||||||
|
/// </summary>
|
||||||
|
public const double APPEAR_DURATION = 200;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay before the accuracy circle starts filling.
|
||||||
|
/// </summary>
|
||||||
|
public const double ACCURACY_TRANSFORM_DELAY = 450;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration for the accuracy circle fill.
|
||||||
|
/// </summary>
|
||||||
|
public const double ACCURACY_TRANSFORM_DURATION = 3000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay after <see cref="ACCURACY_TRANSFORM_DURATION"/> for the rank text (A/B/C/D/S/SS) to appear.
|
||||||
|
/// </summary>
|
||||||
|
public const double TEXT_APPEAR_DELAY = ACCURACY_TRANSFORM_DURATION / 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delay before the rank circles start filling.
|
||||||
|
/// </summary>
|
||||||
|
public const double RANK_CIRCLE_TRANSFORM_DELAY = 150;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration for the rank circle fills.
|
||||||
|
/// </summary>
|
||||||
|
public const double RANK_CIRCLE_TRANSFORM_DURATION = 800;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Relative width of the rank circles.
|
||||||
|
/// </summary>
|
||||||
|
public const float RANK_CIRCLE_RADIUS = 0.06f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Relative width of the circle showing the accuracy.
|
||||||
|
/// </summary>
|
||||||
|
private const float accuracy_circle_radius = 0.2f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// SS is displayed as a 1% region, otherwise it would be invisible.
|
||||||
|
/// </summary>
|
||||||
|
private const double virtual_ss_percentage = 0.01;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The easing for the circle filling transforms.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly Easing ACCURACY_TRANSFORM_EASING = Easing.OutPow10;
|
||||||
|
|
||||||
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
|
private SmoothCircularProgress accuracyCircle;
|
||||||
|
private SmoothCircularProgress innerMask;
|
||||||
|
private Container<RankBadge> badges;
|
||||||
|
private RankText rankText;
|
||||||
|
|
||||||
|
public AccuracyCircle(ScoreInfo score)
|
||||||
|
{
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
Name = "Background circle",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.Gray(47),
|
||||||
|
Alpha = 0.5f,
|
||||||
|
InnerRadius = accuracy_circle_radius + 0.01f, // Extends a little bit into the circle
|
||||||
|
Current = { Value = 1 },
|
||||||
|
},
|
||||||
|
accuracyCircle = new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
Name = "Accuracy circle",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#7CF6FF"), Color4Extensions.FromHex("#BAFFA9")),
|
||||||
|
InnerRadius = accuracy_circle_radius,
|
||||||
|
},
|
||||||
|
new BufferedContainer
|
||||||
|
{
|
||||||
|
Name = "Graded circles",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(0.8f),
|
||||||
|
Padding = new MarginPadding(2),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#BE0089"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 1 }
|
||||||
|
},
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#0096A2"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 1 - virtual_ss_percentage }
|
||||||
|
},
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#72C904"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 0.95f }
|
||||||
|
},
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#D99D03"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 0.9f }
|
||||||
|
},
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#EA7948"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 0.8f }
|
||||||
|
},
|
||||||
|
new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#FF5858"),
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS,
|
||||||
|
Current = { Value = 0.7f }
|
||||||
|
},
|
||||||
|
new RankNotch(0),
|
||||||
|
new RankNotch((float)(1 - virtual_ss_percentage)),
|
||||||
|
new RankNotch(0.95f),
|
||||||
|
new RankNotch(0.9f),
|
||||||
|
new RankNotch(0.8f),
|
||||||
|
new RankNotch(0.7f),
|
||||||
|
new BufferedContainer
|
||||||
|
{
|
||||||
|
Name = "Graded circle mask",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding(1),
|
||||||
|
Blending = new BlendingParameters
|
||||||
|
{
|
||||||
|
Source = BlendingType.DstColor,
|
||||||
|
Destination = BlendingType.OneMinusSrcAlpha,
|
||||||
|
SourceAlpha = BlendingType.One,
|
||||||
|
DestinationAlpha = BlendingType.SrcAlpha
|
||||||
|
},
|
||||||
|
Child = innerMask = new SmoothCircularProgress
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
InnerRadius = RANK_CIRCLE_RADIUS - 0.01f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
badges = new Container<RankBadge>
|
||||||
|
{
|
||||||
|
Name = "Rank badges",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Vertical = -15, Horizontal = -20 },
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new RankBadge(1f, ScoreRank.X),
|
||||||
|
new RankBadge(0.95f, ScoreRank.S),
|
||||||
|
new RankBadge(0.9f, ScoreRank.A),
|
||||||
|
new RankBadge(0.8f, ScoreRank.B),
|
||||||
|
new RankBadge(0.7f, ScoreRank.C),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rankText = new RankText(score.Rank)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
this.ScaleTo(0).Then().ScaleTo(1, APPEAR_DURATION, Easing.OutQuint);
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(RANK_CIRCLE_TRANSFORM_DELAY, true))
|
||||||
|
innerMask.FillTo(1f, RANK_CIRCLE_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY, true))
|
||||||
|
{
|
||||||
|
double targetAccuracy = score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH ? 1 : Math.Min(1 - virtual_ss_percentage, score.Accuracy);
|
||||||
|
|
||||||
|
accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
|
||||||
|
|
||||||
|
foreach (var badge in badges)
|
||||||
|
{
|
||||||
|
if (badge.Accuracy > score.Accuracy)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(1 - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION, true))
|
||||||
|
badge.Appear();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(TEXT_APPEAR_DELAY, true))
|
||||||
|
rankText.Appear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double inverseEasing(Easing easing, double targetValue)
|
||||||
|
{
|
||||||
|
double test = 0;
|
||||||
|
double result = 0;
|
||||||
|
int count = 2;
|
||||||
|
|
||||||
|
while (Math.Abs(result - targetValue) > 0.005)
|
||||||
|
{
|
||||||
|
int dir = Math.Sign(targetValue - result);
|
||||||
|
|
||||||
|
test += dir * 1.0 / count;
|
||||||
|
result = Interpolation.ApplyEasing(easing, test);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs
Normal file
99
osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Online.Leaderboards;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains a <see cref="DrawableRank"/> that is positioned around the <see cref="AccuracyCircle"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class RankBadge : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The accuracy value corresponding to the <see cref="ScoreRank"/> displayed by this badge.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float Accuracy;
|
||||||
|
|
||||||
|
private readonly ScoreRank rank;
|
||||||
|
|
||||||
|
private Drawable rankContainer;
|
||||||
|
private Drawable overlay;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="RankBadge"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="accuracy">The accuracy value corresponding to <paramref name="rank"/>.</param>
|
||||||
|
/// <param name="rank">The <see cref="ScoreRank"/> to be displayed in this <see cref="RankBadge"/>.</param>
|
||||||
|
public RankBadge(float accuracy, ScoreRank rank)
|
||||||
|
{
|
||||||
|
Accuracy = accuracy;
|
||||||
|
this.rank = rank;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Alpha = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = rankContainer = new Container
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(28, 14),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new DrawableRank(rank),
|
||||||
|
overlay = new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Colour = OsuColour.ForRank(rank).Opacity(0.2f),
|
||||||
|
Radius = 10,
|
||||||
|
},
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows this <see cref="RankBadge"/>.
|
||||||
|
/// </summary>
|
||||||
|
public void Appear()
|
||||||
|
{
|
||||||
|
this.FadeIn(50);
|
||||||
|
overlay.FadeIn().FadeOut(500, Easing.In);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
// Starts at -90deg (top) and moves counter-clockwise by the accuracy
|
||||||
|
rankContainer.Position = circlePosition(-MathF.PI / 2 - (1 - Accuracy) * MathF.PI * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 circlePosition(float t)
|
||||||
|
=> DrawSize / 2 + new Vector2(MathF.Cos(t), MathF.Sin(t)) * DrawSize / 2;
|
||||||
|
}
|
||||||
|
}
|
49
osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs
Normal file
49
osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// 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.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A solid "notch" of the <see cref="AccuracyCircle"/> that appears at the ends of the rank circles to add separation.
|
||||||
|
/// </summary>
|
||||||
|
public class RankNotch : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly float position;
|
||||||
|
|
||||||
|
public RankNotch(float position)
|
||||||
|
{
|
||||||
|
this.position = position;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Rotation = position * 360f,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Height = AccuracyCircle.RANK_CIRCLE_RADIUS,
|
||||||
|
Width = 1f,
|
||||||
|
Colour = OsuColour.Gray(0.3f),
|
||||||
|
EdgeSmoothness = new Vector2(1f)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs
Normal file
137
osu.Game/Screens/Ranking/Expanded/Accuracy/RankText.cs
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// 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.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Online.Leaderboards;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The text that appears in the middle of the <see cref="AccuracyCircle"/> displaying the user's rank.
|
||||||
|
/// </summary>
|
||||||
|
public class RankText : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly ScoreRank rank;
|
||||||
|
|
||||||
|
private BufferedContainer flash;
|
||||||
|
private BufferedContainer superFlash;
|
||||||
|
private GlowingSpriteText rankText;
|
||||||
|
|
||||||
|
public RankText(ScoreRank rank)
|
||||||
|
{
|
||||||
|
this.rank = rank;
|
||||||
|
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Alpha = 0;
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
rankText = new GlowingSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
GlowColour = OsuColour.ForRank(rank),
|
||||||
|
Spacing = new Vector2(-15, 0),
|
||||||
|
Text = DrawableRank.GetRankName(rank),
|
||||||
|
Font = OsuFont.Numeric.With(size: 76),
|
||||||
|
UseFullGlyphHeight = false
|
||||||
|
},
|
||||||
|
superFlash = new BufferedContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
BlurSigma = new Vector2(85),
|
||||||
|
Size = new Vector2(600),
|
||||||
|
CacheDrawnFrameBuffer = true,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Alpha = 0,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.White,
|
||||||
|
Size = new Vector2(150),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flash = new BufferedContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
BlurSigma = new Vector2(35),
|
||||||
|
BypassAutoSizeAxes = Axes.Both,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
CacheDrawnFrameBuffer = true,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
Alpha = 0,
|
||||||
|
Size = new Vector2(2f), // increase buffer size to allow for scale
|
||||||
|
Scale = new Vector2(1.8f),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Spacing = new Vector2(-15, 0),
|
||||||
|
Text = DrawableRank.GetRankName(rank),
|
||||||
|
Font = OsuFont.Numeric.With(size: 76),
|
||||||
|
UseFullGlyphHeight = false,
|
||||||
|
Shadow = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Appear()
|
||||||
|
{
|
||||||
|
this.FadeIn();
|
||||||
|
|
||||||
|
if (rank < ScoreRank.A)
|
||||||
|
{
|
||||||
|
this
|
||||||
|
.MoveToOffset(new Vector2(0, -20))
|
||||||
|
.MoveToOffset(new Vector2(0, 20), 200, Easing.OutBounce);
|
||||||
|
|
||||||
|
if (rank <= ScoreRank.D)
|
||||||
|
{
|
||||||
|
this.Delay(700)
|
||||||
|
.RotateTo(5, 150, Easing.In)
|
||||||
|
.MoveToOffset(new Vector2(0, 3), 150, Easing.In);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.FadeInFromZero(200, Easing.OutQuint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash.Colour = OsuColour.ForRank(rank);
|
||||||
|
flash.FadeIn().Then().FadeOut(1200, Easing.OutQuint);
|
||||||
|
|
||||||
|
if (rank >= ScoreRank.S)
|
||||||
|
rankText.ScaleTo(1.05f).ScaleTo(1, 3000, Easing.OutQuint);
|
||||||
|
|
||||||
|
if (rank >= ScoreRank.X)
|
||||||
|
{
|
||||||
|
flash.FadeIn().Then().FadeOut(3000);
|
||||||
|
superFlash.FadeIn().Then().FadeOut(800, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
// 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.Bindables;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Accuracy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains a <see cref="CircularProgress"/> with smoothened edges.
|
||||||
|
/// </summary>
|
||||||
|
public class SmoothCircularProgress : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Bindable<double> Current
|
||||||
|
{
|
||||||
|
get => progress.Current;
|
||||||
|
set => progress.Current = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float InnerRadius
|
||||||
|
{
|
||||||
|
get => progress.InnerRadius;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
progress.InnerRadius = value;
|
||||||
|
innerSmoothingContainer.Size = new Vector2(1 - value);
|
||||||
|
smoothingWedge.Height = value / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly CircularProgress progress;
|
||||||
|
private readonly Container innerSmoothingContainer;
|
||||||
|
private readonly Drawable smoothingWedge;
|
||||||
|
|
||||||
|
public SmoothCircularProgress()
|
||||||
|
{
|
||||||
|
Container smoothingWedgeContainer;
|
||||||
|
|
||||||
|
InternalChild = new BufferedContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
progress = new CircularProgress { RelativeSizeAxes = Axes.Both },
|
||||||
|
smoothingWedgeContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Child = smoothingWedge = new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 1f,
|
||||||
|
EdgeSmoothness = new Vector2(2, 0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding(-1),
|
||||||
|
Child = new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BorderThickness = 2,
|
||||||
|
Masking = true,
|
||||||
|
BorderColour = OsuColour.Gray(0.5f).Opacity(0.75f),
|
||||||
|
Blending = new BlendingParameters
|
||||||
|
{
|
||||||
|
AlphaEquation = BlendingEquation.ReverseSubtract,
|
||||||
|
},
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
innerSmoothingContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = Vector2.Zero,
|
||||||
|
Padding = new MarginPadding(-1),
|
||||||
|
Child = new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BorderThickness = 2,
|
||||||
|
BorderColour = OsuColour.Gray(0.5f).Opacity(0.75f),
|
||||||
|
Masking = true,
|
||||||
|
Blending = new BlendingParameters
|
||||||
|
{
|
||||||
|
AlphaEquation = BlendingEquation.ReverseSubtract,
|
||||||
|
},
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Current.BindValueChanged(c =>
|
||||||
|
{
|
||||||
|
smoothingWedgeContainer.Alpha = c.NewValue > 0 ? 1 : 0;
|
||||||
|
smoothingWedgeContainer.Rotation = (float)(360 * c.NewValue);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransformSequence<CircularProgress> FillTo(double newValue, double duration = 0, Easing easing = Easing.None)
|
||||||
|
=> progress.FillTo(newValue, duration, easing);
|
||||||
|
}
|
||||||
|
}
|
231
osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
Normal file
231
osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Statistics;
|
||||||
|
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 ExpandedPanelMiddleContent : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
|
private readonly List<StatisticDisplay> statisticDisplays = new List<StatisticDisplay>();
|
||||||
|
private RollingCounter<long> scoreCounter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="ExpandedPanelMiddleContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="score">The score to display.</param>
|
||||||
|
public ExpandedPanelMiddleContent(ScoreInfo score)
|
||||||
|
{
|
||||||
|
this.score = score;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
Padding = new MarginPadding { Vertical = 10, Horizontal = 10 };
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(Bindable<WorkingBeatmap> working)
|
||||||
|
{
|
||||||
|
var beatmap = working.Value.BeatmapInfo;
|
||||||
|
var metadata = beatmap.Metadata;
|
||||||
|
|
||||||
|
var topStatistics = new List<StatisticDisplay>
|
||||||
|
{
|
||||||
|
new AccuracyStatistic(score.Accuracy),
|
||||||
|
new ComboStatistic(score.MaxCombo, true),
|
||||||
|
new CounterStatistic("pp", (int)(score.PP ?? 0)),
|
||||||
|
};
|
||||||
|
|
||||||
|
var bottomStatistics = new List<StatisticDisplay>();
|
||||||
|
foreach (var stat in score.SortedStatistics)
|
||||||
|
bottomStatistics.Add(new CounterStatistic(stat.Key.GetDescription(), stat.Value));
|
||||||
|
|
||||||
|
statisticDisplays.AddRange(topStatistics);
|
||||||
|
statisticDisplays.AddRange(bottomStatistics);
|
||||||
|
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(20),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = new LocalisedString((metadata.Title, metadata.TitleUnicode)),
|
||||||
|
Font = OsuFont.Torus.With(size: 20, weight: FontWeight.SemiBold),
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = new LocalisedString((metadata.Artist, metadata.ArtistUnicode)),
|
||||||
|
Font = OsuFont.Torus.With(size: 14, weight: FontWeight.SemiBold)
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Margin = new MarginPadding { Top = 40 },
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 230,
|
||||||
|
Child = new AccuracyCircle(score)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scoreCounter = new TotalScoreCounter
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding { Top = 0, Bottom = 5 },
|
||||||
|
Current = { Value = 0 },
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new StarRatingDisplay(beatmap)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft
|
||||||
|
},
|
||||||
|
new ModDisplay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
DisplayUnrankedText = false,
|
||||||
|
ExpansionMode = ExpansionMode.AlwaysExpanded,
|
||||||
|
Scale = new Vector2(0.5f),
|
||||||
|
Current = { Value = score.Mods }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = beatmap.Version,
|
||||||
|
Font = OsuFont.Torus.With(size: 16, weight: FontWeight.SemiBold),
|
||||||
|
},
|
||||||
|
new OsuTextFlowContainer(s => s.Font = OsuFont.Torus.With(size: 12))
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
}.With(t =>
|
||||||
|
{
|
||||||
|
t.AddText("mapped by ");
|
||||||
|
t.AddText(score.UserString, s => s.Font = s.Font.With(weight: FontWeight.SemiBold));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Content = new[] { topStatistics.Cast<Drawable>().ToArray() },
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new GridContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Content = new[] { bottomStatistics.Cast<Drawable>().ToArray() },
|
||||||
|
RowDimensions = new[]
|
||||||
|
{
|
||||||
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
// Score counter value setting must be scheduled so it isn't transferred instantaneously
|
||||||
|
ScheduleAfterChildren(() =>
|
||||||
|
{
|
||||||
|
using (BeginDelayedSequence(AccuracyCircle.ACCURACY_TRANSFORM_DELAY, true))
|
||||||
|
{
|
||||||
|
scoreCounter.FadeIn();
|
||||||
|
scoreCounter.Current.Value = score.TotalScore;
|
||||||
|
|
||||||
|
double delay = 0;
|
||||||
|
|
||||||
|
foreach (var stat in statisticDisplays)
|
||||||
|
{
|
||||||
|
using (BeginDelayedSequence(delay, true))
|
||||||
|
stat.Appear();
|
||||||
|
|
||||||
|
delay += 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs
Normal file
108
osu.Game/Screens/Ranking/Expanded/StarRatingDisplay.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// 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.Globalization;
|
||||||
|
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.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A pill that displays the star rating of a <see cref="BeatmapInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class StarRatingDisplay : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly BeatmapInfo beatmap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="StarRatingDisplay"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beatmap">The <see cref="BeatmapInfo"/> to display the star difficulty of.</param>
|
||||||
|
public StarRatingDisplay(BeatmapInfo beatmap)
|
||||||
|
{
|
||||||
|
this.beatmap = beatmap;
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
var starRatingParts = beatmap.StarDifficulty.ToString("0.00", CultureInfo.InvariantCulture).Split('.');
|
||||||
|
string wholePart = starRatingParts[0];
|
||||||
|
string fractionPart = starRatingParts[1];
|
||||||
|
string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||||
|
|
||||||
|
ColourInfo backgroundColour = beatmap.DifficultyRating == DifficultyRating.ExpertPlus
|
||||||
|
? ColourInfo.GradientVertical(Color4Extensions.FromHex("#C1C1C1"), Color4Extensions.FromHex("#595959"))
|
||||||
|
: (ColourInfo)colours.ForDifficultyRating(beatmap.DifficultyRating);
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = backgroundColour
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Horizontal = 8, Vertical = 4 },
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(2, 0),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Size = new Vector2(7),
|
||||||
|
Icon = FontAwesome.Solid.Star,
|
||||||
|
Colour = Color4.Black
|
||||||
|
},
|
||||||
|
new OsuTextFlowContainer(s => s.Font = OsuFont.Numeric.With(weight: FontWeight.Black))
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
TextAnchor = Anchor.BottomLeft,
|
||||||
|
}.With(t =>
|
||||||
|
{
|
||||||
|
t.AddText($"{wholePart}", s =>
|
||||||
|
{
|
||||||
|
s.Colour = Color4.Black;
|
||||||
|
s.Font = s.Font.With(size: 14);
|
||||||
|
s.UseFullGlyphHeight = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
t.AddText($"{separator}{fractionPart}", s =>
|
||||||
|
{
|
||||||
|
s.Colour = Color4.Black;
|
||||||
|
s.Font = s.Font.With(size: 7);
|
||||||
|
s.UseFullGlyphHeight = false;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="StatisticDisplay"/> to display the player's accuracy.
|
||||||
|
/// </summary>
|
||||||
|
public class AccuracyStatistic : StatisticDisplay
|
||||||
|
{
|
||||||
|
private readonly double accuracy;
|
||||||
|
|
||||||
|
private RollingCounter<double> counter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="AccuracyStatistic"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="accuracy">The accuracy to display.</param>
|
||||||
|
public AccuracyStatistic(double accuracy)
|
||||||
|
: base("accuracy")
|
||||||
|
{
|
||||||
|
this.accuracy = accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Appear()
|
||||||
|
{
|
||||||
|
base.Appear();
|
||||||
|
counter.Current.Value = accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateContent() => counter = new Counter();
|
||||||
|
|
||||||
|
private class Counter : RollingCounter<double>
|
||||||
|
{
|
||||||
|
protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION;
|
||||||
|
|
||||||
|
protected override Easing RollingEasing => AccuracyCircle.ACCURACY_TRANSFORM_EASING;
|
||||||
|
|
||||||
|
public Counter()
|
||||||
|
{
|
||||||
|
DisplayedCountSpriteText.Font = OsuFont.Torus.With(size: 20, fixedWidth: true);
|
||||||
|
DisplayedCountSpriteText.Spacing = new Vector2(-2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string FormatCount(double count) => count.FormatAccuracy();
|
||||||
|
|
||||||
|
public override void Increment(double amount)
|
||||||
|
=> Current.Value += amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
// 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.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="StatisticDisplay"/> to display the player's combo.
|
||||||
|
/// </summary>
|
||||||
|
public class ComboStatistic : CounterStatistic
|
||||||
|
{
|
||||||
|
private readonly bool isPerfect;
|
||||||
|
|
||||||
|
private Drawable perfectText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="ComboStatistic"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="combo">The combo to be displayed.</param>
|
||||||
|
/// <param name="isPerfect">Whether this is a perfect combo.</param>
|
||||||
|
public ComboStatistic(int combo, bool isPerfect)
|
||||||
|
: base("combo", combo)
|
||||||
|
{
|
||||||
|
this.isPerfect = isPerfect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Appear()
|
||||||
|
{
|
||||||
|
base.Appear();
|
||||||
|
|
||||||
|
if (isPerfect)
|
||||||
|
{
|
||||||
|
using (BeginDelayedSequence(AccuracyCircle.ACCURACY_TRANSFORM_DURATION / 2, true))
|
||||||
|
perfectText.FadeIn(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateContent() => new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(10, 0),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
base.CreateContent().With(d =>
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft;
|
||||||
|
Origin = Anchor.CentreLeft;
|
||||||
|
}),
|
||||||
|
perfectText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Text = "PERFECT",
|
||||||
|
Font = OsuFont.Torus.With(size: 11, weight: FontWeight.SemiBold),
|
||||||
|
Colour = ColourInfo.GradientVertical(Color4Extensions.FromHex("#66FFCC"), Color4Extensions.FromHex("#FF9AD7")),
|
||||||
|
Alpha = 0,
|
||||||
|
UseFullGlyphHeight = false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="StatisticDisplay"/> to display general numeric values.
|
||||||
|
/// </summary>
|
||||||
|
public class CounterStatistic : StatisticDisplay
|
||||||
|
{
|
||||||
|
private readonly int count;
|
||||||
|
|
||||||
|
private RollingCounter<int> counter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="CounterStatistic"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="header">The name of the statistic.</param>
|
||||||
|
/// <param name="count">The value to display.</param>
|
||||||
|
public CounterStatistic(string header, int count)
|
||||||
|
: base(header)
|
||||||
|
{
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Appear()
|
||||||
|
{
|
||||||
|
base.Appear();
|
||||||
|
counter.Current.Value = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateContent() => counter = new Counter();
|
||||||
|
|
||||||
|
private class Counter : RollingCounter<int>
|
||||||
|
{
|
||||||
|
protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION;
|
||||||
|
|
||||||
|
protected override Easing RollingEasing => AccuracyCircle.ACCURACY_TRANSFORM_EASING;
|
||||||
|
|
||||||
|
public Counter()
|
||||||
|
{
|
||||||
|
DisplayedCountSpriteText.Font = OsuFont.Torus.With(size: 20, fixedWidth: true);
|
||||||
|
DisplayedCountSpriteText.Spacing = new Vector2(-2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Increment(int amount)
|
||||||
|
=> Current.Value += amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A statistic from the score to be displayed in the <see cref="ExpandedPanelMiddleContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class StatisticDisplay : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly string header;
|
||||||
|
|
||||||
|
private Drawable content;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="StatisticDisplay"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="header">The name of the statistic.</param>
|
||||||
|
protected StatisticDisplay(string header)
|
||||||
|
{
|
||||||
|
this.header = header;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 12,
|
||||||
|
Masking = true,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#222")
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Font = OsuFont.Torus.With(size: 12, weight: FontWeight.SemiBold),
|
||||||
|
Text = header.ToUpperInvariant(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
content = CreateContent().With(d =>
|
||||||
|
{
|
||||||
|
d.Anchor = Anchor.TopCentre;
|
||||||
|
d.Origin = Anchor.TopCentre;
|
||||||
|
d.Alpha = 0;
|
||||||
|
d.AlwaysPresent = true;
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the statistic value.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Appear() => content.FadeIn(100);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the content for this <see cref="StatisticDisplay"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected abstract Drawable CreateContent();
|
||||||
|
}
|
||||||
|
}
|
38
osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs
Normal file
38
osu.Game/Screens/Ranking/Expanded/TotalScoreCounter.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Screens.Ranking.Expanded.Accuracy;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking.Expanded
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A counter for the player's total score to be displayed in the <see cref="ExpandedPanelMiddleContent"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class TotalScoreCounter : RollingCounter<long>
|
||||||
|
{
|
||||||
|
protected override double RollingDuration => AccuracyCircle.ACCURACY_TRANSFORM_DURATION;
|
||||||
|
|
||||||
|
protected override Easing RollingEasing => AccuracyCircle.ACCURACY_TRANSFORM_EASING;
|
||||||
|
|
||||||
|
public TotalScoreCounter()
|
||||||
|
{
|
||||||
|
// Todo: AutoSize X removed here due to https://github.com/ppy/osu-framework/issues/3369
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
DisplayedCountSpriteText.Anchor = Anchor.TopCentre;
|
||||||
|
DisplayedCountSpriteText.Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
|
DisplayedCountSpriteText.Font = OsuFont.Torus.With(size: 60, weight: FontWeight.Light, fixedWidth: true);
|
||||||
|
DisplayedCountSpriteText.Spacing = new Vector2(-5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string FormatCount(long count) => count.ToString("N0");
|
||||||
|
|
||||||
|
public override void Increment(long amount)
|
||||||
|
=> Current.Value += amount;
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
// 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.Shapes;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Select.Leaderboards;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Pages
|
|
||||||
{
|
|
||||||
public class LocalLeaderboardPage : ResultsPage
|
|
||||||
{
|
|
||||||
public LocalLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap = null)
|
|
||||||
: base(score, beatmap)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Colour = colours.Gray6,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
new BeatmapLeaderboard
|
|
||||||
{
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Beatmap = Beatmap.BeatmapInfo ?? Score.Beatmap,
|
|
||||||
Scale = new Vector2(0.7f)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,428 +0,0 @@
|
|||||||
// 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 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.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Textures;
|
|
||||||
using osu.Framework.Localisation;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online.Leaderboards;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Users;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Pages
|
|
||||||
{
|
|
||||||
public class ScoreResultsPage : ResultsPage
|
|
||||||
{
|
|
||||||
private Container scoreContainer;
|
|
||||||
private ScoreCounter scoreCounter;
|
|
||||||
|
|
||||||
private readonly ScoreInfo score;
|
|
||||||
|
|
||||||
public ScoreResultsPage(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
: base(score, beatmap)
|
|
||||||
{
|
|
||||||
this.score = score;
|
|
||||||
}
|
|
||||||
|
|
||||||
private FillFlowContainer<DrawableScoreStatistic> statisticsContainer;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
const float user_header_height = 120;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding { Top = user_header_height },
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new DelayedLoadWrapper(new UserHeader(Score.User)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = user_header_height,
|
|
||||||
},
|
|
||||||
new UpdateableRank(Score.Rank)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Size = new Vector2(150, 60),
|
|
||||||
Margin = new MarginPadding(20),
|
|
||||||
},
|
|
||||||
scoreContainer = new Container
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 60,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new SongProgressGraph
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.5f,
|
|
||||||
Objects = Beatmap.Beatmap.HitObjects,
|
|
||||||
},
|
|
||||||
scoreCounter = new SlowScoreCounter(6)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Colour = colours.PinkDarker,
|
|
||||||
Y = 10,
|
|
||||||
TextSize = 56,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Colour = colours.PinkDarker,
|
|
||||||
Shadow = false,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
|
||||||
Text = "total score",
|
|
||||||
Margin = new MarginPadding { Bottom = 15 },
|
|
||||||
},
|
|
||||||
new BeatmapDetails(Beatmap.BeatmapInfo)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Margin = new MarginPadding { Bottom = 10 },
|
|
||||||
},
|
|
||||||
new DateTimeDisplay(Score.Date.LocalDateTime)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Size = new Vector2(0.75f, 1),
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Margin = new MarginPadding { Top = 10, Bottom = 10 },
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Colour = ColourInfo.GradientHorizontal(
|
|
||||||
colours.GrayC.Opacity(0),
|
|
||||||
colours.GrayC.Opacity(0.9f)),
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = new Vector2(0.5f, 1),
|
|
||||||
},
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Colour = ColourInfo.GradientHorizontal(
|
|
||||||
colours.GrayC.Opacity(0.9f),
|
|
||||||
colours.GrayC.Opacity(0)),
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = new Vector2(0.5f, 1),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
statisticsContainer = new FillFlowContainer<DrawableScoreStatistic>
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
LayoutDuration = 200,
|
|
||||||
LayoutEasing = Easing.OutQuint
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
Margin = new MarginPadding { Bottom = 10 },
|
|
||||||
Spacing = new Vector2(5),
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new ReplayDownloadButton(score),
|
|
||||||
new RetryButton()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
statisticsContainer.ChildrenEnumerable = Score.SortedStatistics.Select(s => new DrawableScoreStatistic(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Schedule(() =>
|
|
||||||
{
|
|
||||||
scoreCounter.Increment(Score.TotalScore);
|
|
||||||
|
|
||||||
int delay = 0;
|
|
||||||
|
|
||||||
foreach (var s in statisticsContainer.Children)
|
|
||||||
{
|
|
||||||
s.FadeOut()
|
|
||||||
.Then(delay += 200)
|
|
||||||
.FadeIn(300 + delay, Easing.Out);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateAfterChildren()
|
|
||||||
{
|
|
||||||
base.UpdateAfterChildren();
|
|
||||||
|
|
||||||
scoreCounter.Scale = new Vector2(Math.Min(1f, (scoreContainer.DrawWidth - 20) / scoreCounter.DrawWidth));
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DrawableScoreStatistic : Container
|
|
||||||
{
|
|
||||||
private readonly KeyValuePair<HitResult, int> statistic;
|
|
||||||
|
|
||||||
public DrawableScoreStatistic(KeyValuePair<HitResult, int> statistic)
|
|
||||||
{
|
|
||||||
this.statistic = statistic;
|
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
Margin = new MarginPadding { Left = 5, Right = 5 };
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = statistic.Value.ToString().PadLeft(4, '0'),
|
|
||||||
Colour = colours.Gray7,
|
|
||||||
Font = OsuFont.GetFont(size: 30),
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = statistic.Key.GetDescription(),
|
|
||||||
Colour = colours.Gray7,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
|
||||||
Y = 26,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DateTimeDisplay : Container
|
|
||||||
{
|
|
||||||
private readonly DateTime date;
|
|
||||||
|
|
||||||
public DateTimeDisplay(DateTime date)
|
|
||||||
{
|
|
||||||
this.date = date;
|
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
Masking = true;
|
|
||||||
CornerRadius = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = colours.Gray6,
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Padding = new MarginPadding { Horizontal = 10, Vertical = 5 },
|
|
||||||
Spacing = new Vector2(10),
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = date.ToShortDateString(),
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = date.ToShortTimeString(),
|
|
||||||
Colour = Color4.White,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BeatmapDetails : Container
|
|
||||||
{
|
|
||||||
private readonly BeatmapInfo beatmap;
|
|
||||||
|
|
||||||
private readonly OsuSpriteText title;
|
|
||||||
private readonly OsuSpriteText artist;
|
|
||||||
private readonly OsuSpriteText versionMapper;
|
|
||||||
|
|
||||||
public BeatmapDetails(BeatmapInfo beatmap)
|
|
||||||
{
|
|
||||||
this.beatmap = beatmap;
|
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
title = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Shadow = false,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24, italics: true),
|
|
||||||
},
|
|
||||||
artist = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Shadow = false,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 20, italics: true),
|
|
||||||
},
|
|
||||||
versionMapper = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Shadow = false,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
title.Colour = artist.Colour = colours.BlueDarker;
|
|
||||||
versionMapper.Colour = colours.Gray8;
|
|
||||||
|
|
||||||
var creator = beatmap.Metadata.Author?.Username;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(creator))
|
|
||||||
{
|
|
||||||
versionMapper.Text = $"mapped by {creator}";
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(beatmap.Version))
|
|
||||||
versionMapper.Text = $"{beatmap.Version} - " + versionMapper.Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
title.Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title));
|
|
||||||
artist.Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LongRunningLoad]
|
|
||||||
private class UserHeader : Container
|
|
||||||
{
|
|
||||||
private readonly User user;
|
|
||||||
private readonly Sprite cover;
|
|
||||||
|
|
||||||
public UserHeader(User user)
|
|
||||||
{
|
|
||||||
this.user = user;
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
cover = new Sprite
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
FillMode = FillMode.Fill,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
Text = user.Username,
|
|
||||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, italics: true),
|
|
||||||
Padding = new MarginPadding { Bottom = 10 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(LargeTextureStore textures)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(user.CoverUrl))
|
|
||||||
cover.Texture = textures.Get(user.CoverUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SlowScoreCounter : ScoreCounter
|
|
||||||
{
|
|
||||||
protected override double RollingDuration => 3000;
|
|
||||||
|
|
||||||
protected override Easing RollingEasing => Easing.OutPow10;
|
|
||||||
|
|
||||||
public SlowScoreCounter(uint leading = 0)
|
|
||||||
: base(leading)
|
|
||||||
{
|
|
||||||
DisplayedCountSpriteText.Shadow = false;
|
|
||||||
DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(Typeface.Venera, weight: FontWeight.Light);
|
|
||||||
UseCommaSeparator = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,11 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking
|
namespace osu.Game.Screens.Ranking
|
||||||
{
|
{
|
||||||
public interface IResultPageInfo
|
public enum PanelState
|
||||||
{
|
{
|
||||||
IconUsage Icon { get; }
|
Expanded,
|
||||||
|
Contracted
|
||||||
string Name { get; }
|
|
||||||
|
|
||||||
ResultsPage CreatePage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ using osu.Game.Online;
|
|||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Pages
|
namespace osu.Game.Screens.Ranking
|
||||||
{
|
{
|
||||||
public class ReplayDownloadButton : DownloadTrackingComposite<ScoreInfo, ScoreManager>
|
public class ReplayDownloadButton : DownloadTrackingComposite<ScoreInfo, ScoreManager>
|
||||||
{
|
{
|
@ -1,97 +0,0 @@
|
|||||||
// 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.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.UserInterface;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking
|
|
||||||
{
|
|
||||||
public class ResultModeButton : TabItem<IResultPageInfo>, IHasTooltip
|
|
||||||
{
|
|
||||||
private readonly IconUsage icon;
|
|
||||||
private Color4 activeColour;
|
|
||||||
private Color4 inactiveColour;
|
|
||||||
private CircularContainer colouredPart;
|
|
||||||
|
|
||||||
public ResultModeButton(IResultPageInfo mode)
|
|
||||||
: base(mode)
|
|
||||||
{
|
|
||||||
icon = mode.Icon;
|
|
||||||
TooltipText = mode.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
Size = new Vector2(50);
|
|
||||||
|
|
||||||
Masking = true;
|
|
||||||
|
|
||||||
CornerRadius = 25;
|
|
||||||
CornerExponent = 2;
|
|
||||||
|
|
||||||
activeColour = colours.PinkDarker;
|
|
||||||
inactiveColour = OsuColour.Gray(0.8f);
|
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = Color4.Black.Opacity(0.4f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
colouredPart = new CircularContainer
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Size = new Vector2(0.8f),
|
|
||||||
BorderThickness = 4,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
Colour = inactiveColour,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
AlwaysPresent = true, //for border rendering
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Transparent,
|
|
||||||
},
|
|
||||||
new SpriteIcon
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Shadow = false,
|
|
||||||
Colour = OsuColour.Gray(0.95f),
|
|
||||||
Icon = icon,
|
|
||||||
Size = new Vector2(20),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnActivated() => colouredPart.FadeColour(activeColour, 200, Easing.OutQuint);
|
|
||||||
|
|
||||||
protected override void OnDeactivated() => colouredPart.FadeColour(inactiveColour, 200, Easing.OutQuint);
|
|
||||||
|
|
||||||
public string TooltipText { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// 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;
|
|
||||||
using osu.Framework.Graphics.UserInterface;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking
|
|
||||||
{
|
|
||||||
public class ResultModeTabControl : TabControl<IResultPageInfo>
|
|
||||||
{
|
|
||||||
public ResultModeTabControl()
|
|
||||||
{
|
|
||||||
TabContainer.Anchor = Anchor.BottomCentre;
|
|
||||||
TabContainer.Origin = Anchor.BottomCentre;
|
|
||||||
TabContainer.Spacing = new Vector2(15);
|
|
||||||
|
|
||||||
TabContainer.Masking = false;
|
|
||||||
TabContainer.Padding = new MarginPadding(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Dropdown<IResultPageInfo> CreateDropdown() => null;
|
|
||||||
|
|
||||||
protected override TabItem<IResultPageInfo> CreateTabItem(IResultPageInfo value) => new ResultModeButton(value)
|
|
||||||
{
|
|
||||||
Anchor = TabContainer.Anchor,
|
|
||||||
Origin = TabContainer.Origin
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,291 +0,0 @@
|
|||||||
// 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.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
using osu.Game.Screens.Backgrounds;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking
|
|
||||||
{
|
|
||||||
public abstract class Results : OsuScreen
|
|
||||||
{
|
|
||||||
protected const float BACKGROUND_BLUR = 20;
|
|
||||||
|
|
||||||
private Container circleOuterBackground;
|
|
||||||
private Container circleOuter;
|
|
||||||
private Container circleInner;
|
|
||||||
|
|
||||||
private ParallaxContainer backgroundParallax;
|
|
||||||
|
|
||||||
private ResultModeTabControl modeChangeButtons;
|
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
|
||||||
private Player player { get; set; }
|
|
||||||
|
|
||||||
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
|
||||||
|
|
||||||
protected readonly ScoreInfo Score;
|
|
||||||
|
|
||||||
private Container currentPage;
|
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
|
|
||||||
|
|
||||||
private const float overscan = 1.3f;
|
|
||||||
|
|
||||||
private const float circle_outer_scale = 0.96f;
|
|
||||||
|
|
||||||
protected Results(ScoreInfo score)
|
|
||||||
{
|
|
||||||
Score = score;
|
|
||||||
}
|
|
||||||
|
|
||||||
private const float transition_time = 800;
|
|
||||||
|
|
||||||
private IEnumerable<Drawable> allCircles => new Drawable[] { circleOuterBackground, circleInner, circleOuter };
|
|
||||||
|
|
||||||
public override void OnEntering(IScreen last)
|
|
||||||
{
|
|
||||||
base.OnEntering(last);
|
|
||||||
((BackgroundScreenBeatmap)Background).BlurAmount.Value = BACKGROUND_BLUR;
|
|
||||||
Background.ScaleTo(1.1f, transition_time, Easing.OutQuint);
|
|
||||||
|
|
||||||
allCircles.ForEach(c =>
|
|
||||||
{
|
|
||||||
c.FadeOut();
|
|
||||||
c.ScaleTo(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
backgroundParallax.FadeOut();
|
|
||||||
modeChangeButtons.FadeOut();
|
|
||||||
currentPage?.FadeOut();
|
|
||||||
|
|
||||||
circleOuterBackground
|
|
||||||
.FadeIn(transition_time, Easing.OutQuint)
|
|
||||||
.ScaleTo(1, transition_time, Easing.OutQuint);
|
|
||||||
|
|
||||||
using (BeginDelayedSequence(transition_time * 0.25f, true))
|
|
||||||
{
|
|
||||||
circleOuter
|
|
||||||
.FadeIn(transition_time, Easing.OutQuint)
|
|
||||||
.ScaleTo(1, transition_time, Easing.OutQuint);
|
|
||||||
|
|
||||||
using (BeginDelayedSequence(transition_time * 0.3f, true))
|
|
||||||
{
|
|
||||||
backgroundParallax.FadeIn(transition_time, Easing.OutQuint);
|
|
||||||
|
|
||||||
circleInner
|
|
||||||
.FadeIn(transition_time, Easing.OutQuint)
|
|
||||||
.ScaleTo(1, transition_time, Easing.OutQuint);
|
|
||||||
|
|
||||||
using (BeginDelayedSequence(transition_time * 0.4f, true))
|
|
||||||
{
|
|
||||||
modeChangeButtons.FadeIn(transition_time, Easing.OutQuint);
|
|
||||||
currentPage?.FadeIn(transition_time, Easing.OutQuint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool OnExiting(IScreen next)
|
|
||||||
{
|
|
||||||
allCircles.ForEach(c => c.ScaleTo(0, transition_time, Easing.OutSine));
|
|
||||||
|
|
||||||
Background.ScaleTo(1f, transition_time / 4, Easing.OutQuint);
|
|
||||||
|
|
||||||
this.FadeOut(transition_time / 4);
|
|
||||||
|
|
||||||
return base.OnExiting(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
InternalChild = new AspectContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Height = overscan,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
circleOuterBackground = new CircularContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
Alpha = 0.2f,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
circleOuter = new CircularContainer
|
|
||||||
{
|
|
||||||
Size = new Vector2(circle_outer_scale),
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = Color4.Black.Opacity(0.4f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 15,
|
|
||||||
},
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
backgroundParallax = new ParallaxContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
ParallaxAmount = 0.01f,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Sprite
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.2f,
|
|
||||||
Texture = Beatmap.Value.Background,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
FillMode = FillMode.Fill
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modeChangeButtons = new ResultModeTabControl
|
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 50,
|
|
||||||
Margin = new MarginPadding { Bottom = 110 },
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
Text = $"{Score.MaxCombo}x",
|
|
||||||
RelativePositionAxes = Axes.X,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40),
|
|
||||||
X = 0.1f,
|
|
||||||
Colour = colours.BlueDarker,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Text = "max combo",
|
|
||||||
Font = OsuFont.GetFont(size: 20),
|
|
||||||
RelativePositionAxes = Axes.X,
|
|
||||||
X = 0.1f,
|
|
||||||
Colour = colours.Gray6,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
Text = Score.DisplayAccuracy,
|
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40),
|
|
||||||
RelativePositionAxes = Axes.X,
|
|
||||||
X = 0.9f,
|
|
||||||
Colour = colours.BlueDarker,
|
|
||||||
},
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Text = "accuracy",
|
|
||||||
Font = OsuFont.GetFont(size: 20),
|
|
||||||
RelativePositionAxes = Axes.X,
|
|
||||||
X = 0.9f,
|
|
||||||
Colour = colours.Gray6,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
circleInner = new CircularContainer
|
|
||||||
{
|
|
||||||
Size = new Vector2(0.6f),
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = Color4.Black.Opacity(0.4f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 15,
|
|
||||||
},
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.White,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (player != null)
|
|
||||||
{
|
|
||||||
AddInternal(new HotkeyRetryOverlay
|
|
||||||
{
|
|
||||||
Action = () =>
|
|
||||||
{
|
|
||||||
if (!this.IsCurrentScreen()) return;
|
|
||||||
|
|
||||||
player?.Restart();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var pages = CreateResultPages();
|
|
||||||
|
|
||||||
foreach (var p in pages)
|
|
||||||
modeChangeButtons.AddItem(p);
|
|
||||||
|
|
||||||
modeChangeButtons.Current.Value = pages.FirstOrDefault();
|
|
||||||
|
|
||||||
modeChangeButtons.Current.BindValueChanged(page =>
|
|
||||||
{
|
|
||||||
currentPage?.FadeOut();
|
|
||||||
currentPage?.Expire();
|
|
||||||
|
|
||||||
currentPage = page.NewValue?.CreatePage();
|
|
||||||
|
|
||||||
if (currentPage != null)
|
|
||||||
LoadComponentAsync(currentPage, circleInner.Add);
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract IEnumerable<IResultPageInfo> CreateResultPages();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
// 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.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking
|
|
||||||
{
|
|
||||||
public abstract class ResultsPage : Container
|
|
||||||
{
|
|
||||||
protected readonly ScoreInfo Score;
|
|
||||||
protected readonly WorkingBeatmap Beatmap;
|
|
||||||
private CircularContainer content;
|
|
||||||
private Box fill;
|
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
|
||||||
|
|
||||||
protected ResultsPage(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
{
|
|
||||||
Score = score;
|
|
||||||
Beatmap = beatmap;
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
fill.Delay(400).FadeInFromZero(600);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
AddRangeInternal(new Drawable[]
|
|
||||||
{
|
|
||||||
fill = new Box
|
|
||||||
{
|
|
||||||
Alpha = 0,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = colours.Gray6
|
|
||||||
},
|
|
||||||
new CircularContainer
|
|
||||||
{
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = colours.GrayF.Opacity(0.8f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 1,
|
|
||||||
},
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = 20,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content = new CircularContainer
|
|
||||||
{
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Radius = 15,
|
|
||||||
},
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
Size = new Vector2(0.88f),
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
142
osu.Game/Screens/Ranking/ResultsScreen.cs
Normal file
142
osu.Game/Screens/Ranking/ResultsScreen.cs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.Backgrounds;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Ranking
|
||||||
|
{
|
||||||
|
public class ResultsScreen : OsuScreen
|
||||||
|
{
|
||||||
|
protected const float BACKGROUND_BLUR = 20;
|
||||||
|
|
||||||
|
public override bool DisallowExternalBeatmapRulesetChanges => true;
|
||||||
|
|
||||||
|
// Temporary for now to stop dual transitions. Should respect the current toolbar mode, but there's no way to do so currently.
|
||||||
|
public override bool HideOverlaysOnEnter => true;
|
||||||
|
|
||||||
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
|
||||||
|
|
||||||
|
[Resolved(CanBeNull = true)]
|
||||||
|
private Player player { get; set; }
|
||||||
|
|
||||||
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
|
private Drawable bottomPanel;
|
||||||
|
|
||||||
|
public ResultsScreen(ScoreInfo score)
|
||||||
|
{
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
InternalChildren = new[]
|
||||||
|
{
|
||||||
|
new ResultsScrollContainer
|
||||||
|
{
|
||||||
|
Child = new ScorePanel(score)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
State = PanelState.Expanded
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bottomPanel = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = TwoLayerButton.SIZE_EXTENDED.Y,
|
||||||
|
Alpha = 0,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4Extensions.FromHex("#333")
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(5),
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new ReplayDownloadButton(score) { Width = 300 },
|
||||||
|
new RetryButton { Width = 300 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
AddInternal(new HotkeyRetryOverlay
|
||||||
|
{
|
||||||
|
Action = () =>
|
||||||
|
{
|
||||||
|
if (!this.IsCurrentScreen()) return;
|
||||||
|
|
||||||
|
player?.Restart();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnEntering(IScreen last)
|
||||||
|
{
|
||||||
|
base.OnEntering(last);
|
||||||
|
|
||||||
|
((BackgroundScreenBeatmap)Background).BlurAmount.Value = BACKGROUND_BLUR;
|
||||||
|
|
||||||
|
Background.FadeTo(0.5f, 250);
|
||||||
|
bottomPanel.FadeTo(1, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool OnExiting(IScreen next)
|
||||||
|
{
|
||||||
|
Background.FadeTo(1, 250);
|
||||||
|
|
||||||
|
return base.OnExiting(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ResultsScrollContainer : OsuScrollContainer
|
||||||
|
{
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
|
protected override Container<Drawable> Content => content;
|
||||||
|
|
||||||
|
public ResultsScrollContainer()
|
||||||
|
{
|
||||||
|
base.Content.Add(content = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X
|
||||||
|
});
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
ScrollbarVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
content.Height = DrawHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ using osu.Game.Graphics.UserInterface;
|
|||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Pages
|
namespace osu.Game.Screens.Ranking
|
||||||
{
|
{
|
||||||
public class RetryButton : OsuAnimatedButton
|
public class RetryButton : OsuAnimatedButton
|
||||||
{
|
{
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
// 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.Sprites;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Ranking.Pages;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Types
|
|
||||||
{
|
|
||||||
public class LocalLeaderboardPageInfo : IResultPageInfo
|
|
||||||
{
|
|
||||||
private readonly ScoreInfo score;
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
|
||||||
|
|
||||||
public LocalLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
{
|
|
||||||
this.score = score;
|
|
||||||
this.beatmap = beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IconUsage Icon => FontAwesome.Solid.User;
|
|
||||||
|
|
||||||
public string Name => @"Local Leaderboard";
|
|
||||||
|
|
||||||
public ResultsPage CreatePage() => new LocalLeaderboardPage(score, beatmap);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// 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.Sprites;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osu.Game.Screens.Ranking.Pages;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Ranking.Types
|
|
||||||
{
|
|
||||||
public class ScoreOverviewPageInfo : IResultPageInfo
|
|
||||||
{
|
|
||||||
public IconUsage Icon => FontAwesome.Solid.Asterisk;
|
|
||||||
|
|
||||||
public string Name => "Overview";
|
|
||||||
private readonly ScoreInfo score;
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
|
||||||
|
|
||||||
public ScoreOverviewPageInfo(ScoreInfo score, WorkingBeatmap beatmap)
|
|
||||||
{
|
|
||||||
this.score = score;
|
|
||||||
this.beatmap = beatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResultsPage CreatePage()
|
|
||||||
{
|
|
||||||
return new ScoreResultsPage(score, beatmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,6 +23,7 @@ using osu.Framework.Graphics.Cursor;
|
|||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -311,20 +312,27 @@ namespace osu.Game.Screens.Select
|
|||||||
Content = getBPMRange(b),
|
Content = getBPMRange(b),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
IBeatmap playableBeatmap;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Try to get the beatmap with the user's ruleset
|
IBeatmap playableBeatmap;
|
||||||
playableBeatmap = beatmap.GetPlayableBeatmap(ruleset, Array.Empty<Mod>());
|
|
||||||
}
|
|
||||||
catch (BeatmapInvalidForRulesetException)
|
|
||||||
{
|
|
||||||
// Can't be converted to the user's ruleset, so use the beatmap's own ruleset
|
|
||||||
playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset, Array.Empty<Mod>());
|
|
||||||
}
|
|
||||||
|
|
||||||
labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s)));
|
try
|
||||||
|
{
|
||||||
|
// Try to get the beatmap with the user's ruleset
|
||||||
|
playableBeatmap = beatmap.GetPlayableBeatmap(ruleset, Array.Empty<Mod>());
|
||||||
|
}
|
||||||
|
catch (BeatmapInvalidForRulesetException)
|
||||||
|
{
|
||||||
|
// Can't be converted to the user's ruleset, so use the beatmap's own ruleset
|
||||||
|
playableBeatmap = beatmap.GetPlayableBeatmap(beatmap.BeatmapInfo.Ruleset, Array.Empty<Mod>());
|
||||||
|
}
|
||||||
|
|
||||||
|
labels.AddRange(playableBeatmap.GetStatistics().Select(s => new InfoLabel(s)));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, "Could not load beatmap successfully!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return labels.ToArray();
|
return labels.ToArray();
|
||||||
|
@ -8,6 +8,7 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ namespace osu.Game.Screens.Select
|
|||||||
Edit();
|
Edit();
|
||||||
}, Key.Number4);
|
}, Key.Number4);
|
||||||
|
|
||||||
((PlayBeatmapDetailArea)BeatmapDetails).Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score));
|
((PlayBeatmapDetailArea)BeatmapDetails).Leaderboard.ScoreSelected += score => this.Push(new ResultsScreen(score));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();
|
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.314.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.317.0" />
|
||||||
<PackageReference Include="Sentry" Version="2.1.0" />
|
<PackageReference Include="Sentry" Version="2.1.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.314.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.317.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.314.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.317.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
<PackageReference Include="SharpCompress" Version="0.24.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
Reference in New Issue
Block a user