1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 23:12:56 +08:00

Merge branch 'master' into results-screen-statistics

This commit is contained in:
smoogipoo 2020-06-15 20:13:09 +09:00
commit 41cec2c216
73 changed files with 503 additions and 292 deletions

View File

@ -5,6 +5,22 @@ GEM
addressable (2.7.0) addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0) public_suffix (>= 2.0.2, < 5.0)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.329.0)
aws-sdk-core (3.99.2)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.34.1)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.68.1)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.1.4)
aws-eventstream (~> 1.0, >= 1.0.2)
babosa (1.0.3) babosa (1.0.3)
claide (1.0.3) claide (1.0.3)
colored (1.2) colored (1.2)
@ -13,23 +29,24 @@ GEM
highline (~> 1.7.2) highline (~> 1.7.2)
declarative (0.0.10) declarative (0.0.10)
declarative-option (0.1.0) declarative-option (0.1.0)
digest-crc (0.4.1) digest-crc (0.5.1)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.5) dotenv (2.7.5)
emoji_regex (1.0.1) emoji_regex (1.0.1)
excon (0.71.1) excon (0.74.0)
faraday (0.17.3) faraday (1.0.1)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6) faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4) faraday (>= 0.7.4)
http-cookie (~> 1.0.0) http-cookie (~> 1.0.0)
faraday_middleware (0.13.1) faraday_middleware (1.0.0)
faraday (>= 0.7.4, < 1.0) faraday (~> 1.0)
fastimage (2.1.7) fastimage (2.1.7)
fastlane (2.140.0) fastlane (2.149.1)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0) addressable (>= 2.3, < 3.0.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.2, < 2.0.0) babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0) bundler (>= 1.12.0, < 3.0.0)
colored colored
@ -37,12 +54,12 @@ GEM
dotenv (>= 2.1.1, < 3.0.0) dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 2.0) emoji_regex (>= 0.1, < 2.0)
excon (>= 0.71.0, < 1.0.0) excon (>= 0.71.0, < 1.0.0)
faraday (~> 0.17) faraday (>= 0.17, < 2.0)
faraday-cookie_jar (~> 0.0.6) faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.13.1) faraday_middleware (>= 0.13.1, < 2.0)
fastimage (>= 2.1.0, < 3.0.0) fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0) gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.29.2, < 0.37.0) google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0) google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0) highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0) json (< 3.0.0)
@ -69,7 +86,7 @@ GEM
souyuz (= 0.9.1) souyuz (= 0.9.1)
fastlane-plugin-xamarin (0.6.3) fastlane-plugin-xamarin (0.6.3)
gh_inspector (1.1.3) gh_inspector (1.1.3)
google-api-client (0.36.4) google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1) addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9) googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0) httpclient (>= 2.8.1, < 3.0)
@ -80,27 +97,28 @@ GEM
google-cloud-core (1.5.0) google-cloud-core (1.5.0)
google-cloud-env (~> 1.0) google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-cloud-env (1.3.0) google-cloud-env (1.3.2)
faraday (~> 0.11) faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.0) google-cloud-errors (1.0.1)
google-cloud-storage (1.25.1) google-cloud-storage (1.26.2)
addressable (~> 2.5) addressable (~> 2.5)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-api-client (~> 0.33) google-api-client (~> 0.33)
google-cloud-core (~> 1.2) google-cloud-core (~> 1.2)
googleauth (~> 0.9) googleauth (~> 0.9)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (0.10.0) googleauth (0.12.0)
faraday (~> 0.12) faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16) memoist (~> 0.16)
multi_json (~> 1.11) multi_json (~> 1.11)
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (~> 0.12) signet (~> 0.14)
highline (1.7.10) highline (1.7.10)
http-cookie (1.0.3) http-cookie (1.0.3)
domain_name (~> 0.5) domain_name (~> 0.5)
httpclient (2.8.3) httpclient (2.8.3)
jmespath (1.4.0)
json (2.3.0) json (2.3.0)
jwt (2.1.0) jwt (2.1.0)
memoist (0.16.2) memoist (0.16.2)
@ -114,7 +132,7 @@ GEM
naturally (2.2.0) naturally (2.2.0)
nokogiri (1.10.7) nokogiri (1.10.7)
mini_portile2 (~> 2.4.0) mini_portile2 (~> 2.4.0)
os (1.0.1) os (1.1.0)
plist (3.5.0) plist (3.5.0)
public_suffix (2.0.5) public_suffix (2.0.5)
representable (3.0.4) representable (3.0.4)
@ -125,12 +143,12 @@ GEM
rouge (2.0.7) rouge (2.0.7)
rubyzip (1.3.0) rubyzip (1.3.0)
security (0.1.3) security (0.1.3)
signet (0.12.0) signet (0.14.0)
addressable (~> 2.3) addressable (~> 2.3)
faraday (~> 0.9) faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0) jwt (>= 1.5, < 3.0)
multi_json (~> 1.10) multi_json (~> 1.10)
simctl (1.6.7) simctl (1.6.8)
CFPropertyList CFPropertyList
naturally naturally
slack-notifier (2.3.2) slack-notifier (2.3.2)
@ -141,17 +159,17 @@ GEM
terminal-notifier (2.0.0) terminal-notifier (2.0.0)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.7.0) tty-cursor (0.7.1)
tty-screen (0.7.0) tty-screen (0.8.0)
tty-spinner (0.9.2) tty-spinner (0.9.3)
tty-cursor (~> 0.7) tty-cursor (~> 0.7)
uber (0.1.0) uber (0.1.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.6) unf_ext (0.0.7.7)
unicode-display_width (1.6.1) unicode-display_width (1.7.0)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.14.0) xcodeproj (1.16.0)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)

View File

@ -5,6 +5,6 @@
"version": "3.1.100" "version": "3.1.100"
}, },
"msbuild-sdks": { "msbuild-sdks": {
"Microsoft.Build.Traversal": "2.0.48" "Microsoft.Build.Traversal": "2.0.50"
} }
} }

View File

@ -13,8 +13,10 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods
{ {
public class TestSceneCatchModPerfect : ModPerfectTestScene public class TestSceneCatchModPerfect : ModPerfectTestScene
{ {
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
public TestSceneCatchModPerfect() public TestSceneCatchModPerfect()
: base(new CatchRuleset(), new CatchModPerfect()) : base(new CatchModPerfect())
{ {
} }

View File

@ -12,13 +12,8 @@ using osuTK;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
public class TestSceneAutoJuiceStream : PlayerTestScene public class TestSceneAutoJuiceStream : TestSceneCatchPlayer
{ {
public TestSceneAutoJuiceStream()
: base(new CatchRuleset())
{
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap

View File

@ -4,18 +4,12 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneBananaShower : PlayerTestScene public class TestSceneBananaShower : TestSceneCatchPlayer
{ {
public TestSceneBananaShower()
: base(new CatchRuleset())
{
}
[Test] [Test]
public void TestBananaShower() public void TestBananaShower()
{ {

View File

@ -9,9 +9,6 @@ namespace osu.Game.Rulesets.Catch.Tests
[TestFixture] [TestFixture]
public class TestSceneCatchPlayer : PlayerTestScene public class TestSceneCatchPlayer : PlayerTestScene
{ {
public TestSceneCatchPlayer() protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
: base(new CatchRuleset())
{
}
} }
} }

View File

@ -4,18 +4,12 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneCatchStacker : PlayerTestScene public class TestSceneCatchStacker : TestSceneCatchPlayer
{ {
public TestSceneCatchStacker()
: base(new CatchRuleset())
{
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap

View File

@ -9,19 +9,13 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Tests.Visual;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneHyperDash : PlayerTestScene public class TestSceneHyperDash : TestSceneCatchPlayer
{ {
public TestSceneHyperDash()
: base(new CatchRuleset())
{
}
protected override bool Autoplay => true; protected override bool Autoplay => true;
[Test] [Test]

View File

@ -7,18 +7,12 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Tests.Visual;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
public class TestSceneJuiceStream : PlayerTestScene public class TestSceneJuiceStream : TestSceneCatchPlayer
{ {
public TestSceneJuiceStream()
: base(new CatchRuleset())
{
}
[Test] [Test]
public void TestJuiceStreamEndingCombo() public void TestJuiceStreamEndingCombo()
{ {

View File

@ -10,8 +10,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
{ {
public class TestSceneManiaModPerfect : ModPerfectTestScene public class TestSceneManiaModPerfect : ModPerfectTestScene
{ {
protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
public TestSceneManiaModPerfect() public TestSceneManiaModPerfect()
: base(new ManiaRuleset(), new ManiaModPerfect()) : base(new ManiaModPerfect())
{ {
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,6 +1,12 @@
[General] [General]
Version: 2.4 Version: 2.5
[Mania] [Mania]
Keys: 4 Keys: 4
ColumnLineWidth: 3,1,3,1,1 ColumnLineWidth: 3,1,3,1,1
Hit0: mania/hit0
Hit50: mania/hit50
Hit100: mania/hit100
Hit200: mania/hit200
Hit300: mania/hit300
Hit300g: mania/hit300g

View File

@ -6,6 +6,7 @@ using System.Linq;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -16,14 +17,19 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning
{ {
public TestSceneDrawableJudgement() public TestSceneDrawableJudgement()
{ {
var hitWindows = new ManiaHitWindows();
foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1)) foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1))
{ {
AddStep("Show " + result.GetDescription(), () => SetContents(() => if (hitWindows.IsHitResultAllowed(result))
new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) {
{ AddStep("Show " + result.GetDescription(), () => SetContents(() =>
Anchor = Anchor.Centre, new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null)
Origin = Anchor.Centre, {
})); Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}));
}
} }
} }
} }

View File

@ -15,8 +15,9 @@ namespace osu.Game.Rulesets.Mania.Tests
{ {
private readonly Bindable<ManiaScrollingDirection> direction = new Bindable<ManiaScrollingDirection>(); private readonly Bindable<ManiaScrollingDirection> direction = new Bindable<ManiaScrollingDirection>();
protected override Ruleset CreateEditorRuleset() => new ManiaRuleset();
public TestSceneEditor() public TestSceneEditor()
: base(new ManiaRuleset())
{ {
AddStep("upwards scroll", () => direction.Value = ManiaScrollingDirection.Up); AddStep("upwards scroll", () => direction.Value = ManiaScrollingDirection.Up);
AddStep("downwards scroll", () => direction.Value = ManiaScrollingDirection.Down); AddStep("downwards scroll", () => direction.Value = ManiaScrollingDirection.Down);

View File

@ -5,11 +5,8 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Mania.Tests namespace osu.Game.Rulesets.Mania.Tests
{ {
public class TestScenePlayer : PlayerTestScene public class TestSceneManiaPlayer : PlayerTestScene
{ {
public TestScenePlayer() protected override Ruleset CreatePlayerRuleset() => new ManiaRuleset();
: base(new ManiaRuleset())
{
}
} }
} }

View File

@ -11,6 +11,7 @@ using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Skinning; using osu.Game.Skinning;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Mania.Skinning namespace osu.Game.Rulesets.Mania.Skinning
{ {
@ -19,6 +20,36 @@ namespace osu.Game.Rulesets.Mania.Skinning
private readonly ISkin source; private readonly ISkin source;
private readonly ManiaBeatmap beatmap; private readonly ManiaBeatmap beatmap;
/// <summary>
/// Mapping of <see cref="HitResult"/> to their corresponding
/// <see cref="LegacyManiaSkinConfigurationLookups"/> value.
/// </summary>
private static readonly IReadOnlyDictionary<HitResult, LegacyManiaSkinConfigurationLookups> hitresult_mapping
= new Dictionary<HitResult, LegacyManiaSkinConfigurationLookups>
{
{ HitResult.Perfect, LegacyManiaSkinConfigurationLookups.Hit300g },
{ HitResult.Great, LegacyManiaSkinConfigurationLookups.Hit300 },
{ HitResult.Good, LegacyManiaSkinConfigurationLookups.Hit200 },
{ HitResult.Ok, LegacyManiaSkinConfigurationLookups.Hit100 },
{ HitResult.Meh, LegacyManiaSkinConfigurationLookups.Hit50 },
{ HitResult.Miss, LegacyManiaSkinConfigurationLookups.Hit0 }
};
/// <summary>
/// Mapping of <see cref="HitResult"/> to their corresponding
/// default filenames.
/// </summary>
private static readonly IReadOnlyDictionary<HitResult, string> default_hitresult_skin_filenames
= new Dictionary<HitResult, string>
{
{ HitResult.Perfect, "mania-hit300g" },
{ HitResult.Great, "mania-hit300" },
{ HitResult.Good, "mania-hit200" },
{ HitResult.Ok, "mania-hit100" },
{ HitResult.Meh, "mania-hit50" },
{ HitResult.Miss, "mania-hit0" }
};
private Lazy<bool> isLegacySkin; private Lazy<bool> isLegacySkin;
/// <summary> /// <summary>
@ -50,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.Skinning
switch (component) switch (component)
{ {
case GameplaySkinComponent<HitResult> resultComponent: case GameplaySkinComponent<HitResult> resultComponent:
return getResult(resultComponent); return getResult(resultComponent.Component);
case ManiaSkinComponent maniaComponent: case ManiaSkinComponent maniaComponent:
if (!isLegacySkin.Value || !hasKeyTexture.Value) if (!isLegacySkin.Value || !hasKeyTexture.Value)
@ -95,30 +126,13 @@ namespace osu.Game.Rulesets.Mania.Skinning
return null; return null;
} }
private Drawable getResult(GameplaySkinComponent<HitResult> resultComponent) private Drawable getResult(HitResult result)
{ {
switch (resultComponent.Component) string filename = GetConfig<ManiaSkinConfigurationLookup, string>(
{ new ManiaSkinConfigurationLookup(hitresult_mapping[result])
case HitResult.Miss: )?.Value ?? default_hitresult_skin_filenames[result];
return this.GetAnimation("mania-hit0", true, true);
case HitResult.Meh: return this.GetAnimation(filename, true, true);
return this.GetAnimation("mania-hit50", true, true);
case HitResult.Ok:
return this.GetAnimation("mania-hit100", true, true);
case HitResult.Good:
return this.GetAnimation("mania-hit200", true, true);
case HitResult.Great:
return this.GetAnimation("mania-hit300", true, true);
case HitResult.Perfect:
return this.GetAnimation("mania-hit300g", true, true);
}
return null;
} }
public Texture GetTexture(string componentName) => source.GetTexture(componentName); public Texture GetTexture(string componentName) => source.GetTexture(componentName);

View File

@ -0,0 +1,12 @@
// 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.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public class OsuModTestScene : ModTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
}
}

View File

@ -9,17 +9,11 @@ using osu.Framework.Utils;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods namespace osu.Game.Rulesets.Osu.Tests.Mods
{ {
public class TestSceneOsuModDifficultyAdjust : ModTestScene public class TestSceneOsuModDifficultyAdjust : OsuModTestScene
{ {
public TestSceneOsuModDifficultyAdjust()
: base(new OsuRuleset())
{
}
[Test] [Test]
public void TestNoAdjustment() => CreateModTest(new ModTestData public void TestNoAdjustment() => CreateModTest(new ModTestData
{ {

View File

@ -4,17 +4,11 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests.Mods namespace osu.Game.Rulesets.Osu.Tests.Mods
{ {
public class TestSceneOsuModDoubleTime : ModTestScene public class TestSceneOsuModDoubleTime : OsuModTestScene
{ {
public TestSceneOsuModDoubleTime()
: base(new OsuRuleset())
{
}
[TestCase(0.5)] [TestCase(0.5)]
[TestCase(1.01)] [TestCase(1.01)]
[TestCase(1.5)] [TestCase(1.5)]

View File

@ -8,18 +8,12 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Tests.Visual;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Osu.Tests.Mods namespace osu.Game.Rulesets.Osu.Tests.Mods
{ {
public class TestSceneOsuModHidden : ModTestScene public class TestSceneOsuModHidden : OsuModTestScene
{ {
public TestSceneOsuModHidden()
: base(new OsuRuleset())
{
}
[Test] [Test]
public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData public void TestDefaultBeatmapTest() => CreateModTest(new ModTestData
{ {

View File

@ -13,8 +13,10 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
{ {
public class TestSceneOsuModPerfect : ModPerfectTestScene public class TestSceneOsuModPerfect : ModPerfectTestScene
{ {
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
public TestSceneOsuModPerfect() public TestSceneOsuModPerfect()
: base(new OsuRuleset(), new OsuModPerfect()) : base(new OsuModPerfect())
{ {
} }

View File

@ -9,9 +9,6 @@ namespace osu.Game.Rulesets.Osu.Tests
[TestFixture] [TestFixture]
public class TestSceneEditor : EditorTestScene public class TestSceneEditor : EditorTestScene
{ {
public TestSceneEditor() protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
: base(new OsuRuleset())
{
}
} }
} }

View File

@ -4,19 +4,13 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Tests.Visual;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneHitCircleLongCombo : PlayerTestScene public class TestSceneHitCircleLongCombo : TestSceneOsuPlayer
{ {
public TestSceneHitCircleLongCombo()
: base(new OsuRuleset())
{
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap

View File

@ -19,10 +19,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
public class TestSceneMissHitWindowJudgements : ModTestScene public class TestSceneMissHitWindowJudgements : ModTestScene
{ {
public TestSceneMissHitWindowJudgements() protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
: base(new OsuRuleset())
{
}
[Test] [Test]
public void TestMissViaEarlyHit() public void TestMissViaEarlyHit()

View File

@ -9,9 +9,6 @@ namespace osu.Game.Rulesets.Osu.Tests
[TestFixture] [TestFixture]
public class TestSceneOsuPlayer : PlayerTestScene public class TestSceneOsuPlayer : PlayerTestScene
{ {
public TestSceneOsuPlayer() protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
: base(new OsuRuleset())
{
}
} }
} }

View File

@ -25,13 +25,12 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneSkinFallbacks : PlayerTestScene public class TestSceneSkinFallbacks : TestSceneOsuPlayer
{ {
private readonly TestSource testUserSkin; private readonly TestSource testUserSkin;
private readonly TestSource testBeatmapSkin; private readonly TestSource testBeatmapSkin;
public TestSceneSkinFallbacks() public TestSceneSkinFallbacks()
: base(new OsuRuleset())
{ {
testUserSkin = new TestSource("user"); testUserSkin = new TestSource("user");
testBeatmapSkin = new TestSource("beatmap"); testBeatmapSkin = new TestSource("beatmap");

View File

@ -12,8 +12,10 @@ namespace osu.Game.Rulesets.Taiko.Tests.Mods
{ {
public class TestSceneTaikoModPerfect : ModPerfectTestScene public class TestSceneTaikoModPerfect : ModPerfectTestScene
{ {
protected override Ruleset CreatePlayerRuleset() => new TestTaikoRuleset();
public TestSceneTaikoModPerfect() public TestSceneTaikoModPerfect()
: base(new TestTaikoRuleset(), new TaikoModPerfect()) : base(new TaikoModPerfect())
{ {
} }

View File

@ -9,9 +9,6 @@ namespace osu.Game.Rulesets.Taiko.Tests
[TestFixture] [TestFixture]
public class TestSceneEditor : EditorTestScene public class TestSceneEditor : EditorTestScene
{ {
public TestSceneEditor() protected override Ruleset CreateEditorRuleset() => new TaikoRuleset();
: base(new TaikoRuleset())
{
}
} }
} }

View File

@ -6,7 +6,6 @@ using osu.Framework.Testing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests namespace osu.Game.Rulesets.Taiko.Tests
{ {
@ -14,13 +13,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
/// Taiko has some interesting rules for legacy mappings. /// Taiko has some interesting rules for legacy mappings.
/// </summary> /// </summary>
[HeadlessTest] [HeadlessTest]
public class TestSceneSampleOutput : PlayerTestScene public class TestSceneSampleOutput : TestSceneTaikoPlayer
{ {
public TestSceneSampleOutput()
: base(new TaikoRuleset())
{
}
public override void SetUpSteps() public override void SetUpSteps()
{ {
base.SetUpSteps(); base.SetUpSteps();

View File

@ -5,17 +5,11 @@ using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests namespace osu.Game.Rulesets.Taiko.Tests
{ {
public class TestSceneSwellJudgements : PlayerTestScene public class TestSceneSwellJudgements : TestSceneTaikoPlayer
{ {
public TestSceneSwellJudgements()
: base(new TaikoRuleset())
{
}
[Test] [Test]
public void TestZeroTickTimeOffsets() public void TestZeroTickTimeOffsets()
{ {

View File

@ -0,0 +1,12 @@
// 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.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests
{
public class TestSceneTaikoPlayer : PlayerTestScene
{
protected override Ruleset CreatePlayerRuleset() => new TaikoRuleset();
}
}

View File

@ -11,13 +11,8 @@ using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests namespace osu.Game.Rulesets.Taiko.Tests
{ {
public class TestSceneTaikoSuddenDeath : PlayerTestScene public class TestSceneTaikoSuddenDeath : TestSceneTaikoPlayer
{ {
public TestSceneTaikoSuddenDeath()
: base(new TaikoRuleset())
{
}
protected override bool AllowFail => true; protected override bool AllowFail => true;
protected override TestPlayer CreatePlayer(Ruleset ruleset) protected override TestPlayer CreatePlayer(Ruleset ruleset)

View File

@ -0,0 +1,25 @@
// 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 NUnit.Framework;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
namespace osu.Game.Tests.Gameplay
{
public class TestSceneGameplayClockContainer : OsuTestScene
{
[Test]
public void TestStartThenElapsedTime()
{
GameplayClockContainer gcc = null;
AddStep("create container", () => Add(gcc = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty<Mod>(), 0)));
AddStep("start track", () => gcc.Start());
AddUntilStep("elapsed greater than zero", () => gcc.GameplayClock.ElapsedFrameTime > 0);
}
}
}

View File

@ -16,17 +16,16 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Formats;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Storyboards; using osu.Game.Storyboards;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual.Gameplay;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Tests.Gameplay namespace osu.Game.Tests.Gameplay
{ {
[HeadlessTest] [HeadlessTest]
public class TestSceneHitObjectSamples : PlayerTestScene public class TestSceneHitObjectSamples : OsuPlayerTestScene
{ {
private readonly SkinInfo userSkinInfo = new SkinInfo(); private readonly SkinInfo userSkinInfo = new SkinInfo();
@ -44,11 +43,6 @@ namespace osu.Game.Tests.Gameplay
protected override bool HasCustomSteps => true; protected override bool HasCustomSteps => true;
public TestSceneHitObjectSamples()
: base(new OsuRuleset())
{
}
private SkinSourceDependencyContainer dependencies; private SkinSourceDependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)

View File

@ -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 System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,7 +11,12 @@ using osu.Framework.Audio.Sample;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Storyboards;
using osu.Game.Storyboards.Drawables;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -43,6 +49,27 @@ namespace osu.Game.Tests.Gameplay
AddAssert("sample is non-null", () => channel != null); AddAssert("sample is non-null", () => channel != null);
} }
[Test]
public void TestSamplePlaybackAtZero()
{
GameplayClockContainer gameplayContainer = null;
DrawableStoryboardSample sample = null;
AddStep("create container", () =>
{
Add(gameplayContainer = new GameplayClockContainer(CreateWorkingBeatmap(new OsuRuleset().RulesetInfo), Array.Empty<Mod>(), 0));
gameplayContainer.Add(sample = new DrawableStoryboardSample(new StoryboardSampleInfo(string.Empty, 0, 1))
{
Clock = gameplayContainer.GameplayClock
});
});
AddStep("start time", () => gameplayContainer.Start());
AddUntilStep("sample playback succeeded", () => sample.LifetimeEnd < double.MaxValue);
}
private class TestSkin : LegacySkin private class TestSkin : LegacySkin
{ {
public TestSkin(string resourceName, AudioManager audioManager) public TestSkin(string resourceName, AudioManager audioManager)

View File

@ -4,6 +4,7 @@
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -13,13 +14,10 @@ namespace osu.Game.Tests.Visual.Editing
{ {
public class TestSceneEditorChangeStates : EditorTestScene public class TestSceneEditorChangeStates : EditorTestScene
{ {
public TestSceneEditorChangeStates()
: base(new OsuRuleset())
{
}
private EditorBeatmap editorBeatmap; private EditorBeatmap editorBeatmap;
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
public override void SetUpSteps() public override void SetUpSteps()
{ {
base.SetUpSteps(); base.SetUpSteps();

View File

@ -0,0 +1,16 @@
// 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.Game.Rulesets;
using osu.Game.Rulesets.Osu;
namespace osu.Game.Tests.Visual.Gameplay
{
/// <summary>
/// A <see cref="PlayerTestScene"/> with an arbitrary ruleset value to test with.
/// </summary>
public abstract class OsuPlayerTestScene : PlayerTestScene
{
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
}
}

View File

@ -10,14 +10,13 @@ using osu.Framework.Testing;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Storyboards; using osu.Game.Storyboards;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
public class TestSceneCompletionCancellation : PlayerTestScene public class TestSceneCompletionCancellation : OsuPlayerTestScene
{ {
private Track track; private Track track;
@ -29,11 +28,6 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override bool AllowFail => false; protected override bool AllowFail => false;
public TestSceneCompletionCancellation()
: base(new OsuRuleset())
{
}
[SetUpSteps] [SetUpSteps]
public override void SetUpSteps() public override void SetUpSteps()
{ {

View File

@ -10,23 +10,17 @@ using osu.Framework.Utils;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Storyboards; using osu.Game.Storyboards;
using osuTK; using osuTK;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
public class TestSceneGameplayRewinding : PlayerTestScene public class TestSceneGameplayRewinding : OsuPlayerTestScene
{ {
[Resolved] [Resolved]
private AudioManager audioManager { get; set; } private AudioManager audioManager { get; set; }
public TestSceneGameplayRewinding()
: base(new OsuRuleset())
{
}
private Track track; private Track track;
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)

View File

@ -10,14 +10,13 @@ using osu.Framework.Testing;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
public class TestScenePause : PlayerTestScene public class TestScenePause : OsuPlayerTestScene
{ {
protected new PausePlayer Player => (PausePlayer)base.Player; protected new PausePlayer Player => (PausePlayer)base.Player;
@ -26,7 +25,6 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
public TestScenePause() public TestScenePause()
: base(new OsuRuleset())
{ {
base.Content.Add(content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both }); base.Content.Add(content = new MenuCursorContainer { RelativeSizeAxes = Axes.Both });
} }

View File

@ -8,12 +8,11 @@ using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state. [HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
public class TestScenePauseWhenInactive : PlayerTestScene public class TestScenePauseWhenInactive : OsuPlayerTestScene
{ {
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
@ -27,11 +26,6 @@ namespace osu.Game.Tests.Visual.Gameplay
[Resolved] [Resolved]
private GameHost host { get; set; } private GameHost host { get; set; }
public TestScenePauseWhenInactive()
: base(new OsuRuleset())
{
}
[Test] [Test]
public void TestDoesntPauseDuringIntro() public void TestDoesntPauseDuringIntro()
{ {

View File

@ -1,52 +1,128 @@
// 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.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Online.API.Requests;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Game.Overlays.Comments;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Graphics;
using osu.Game.Users; using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Comments;
namespace osu.Game.Tests.Visual.Online namespace osu.Game.Tests.Visual.Online
{ {
[TestFixture] [TestFixture]
public class TestSceneCommentsContainer : OsuTestScene public class TestSceneCommentsContainer : OsuTestScene
{ {
protected override bool UseOnlineAPI => true;
[Cached] [Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
public TestSceneCommentsContainer() private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
{
BasicScrollContainer scroll;
TestCommentsContainer comments;
Add(scroll = new BasicScrollContainer private CommentsContainer commentsContainer;
[SetUp]
public void SetUp() => Schedule(() =>
Child = new BasicScrollContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = comments = new TestCommentsContainer() Child = commentsContainer = new CommentsContainer()
}); });
AddStep("Big Black comments", () => comments.ShowComments(CommentableType.Beatmapset, 41823)); [Test]
AddStep("Airman comments", () => comments.ShowComments(CommentableType.Beatmapset, 24313)); public void TestIdleState()
AddStep("Lazer build comments", () => comments.ShowComments(CommentableType.Build, 4772));
AddStep("News comments", () => comments.ShowComments(CommentableType.NewsPost, 715));
AddStep("Trigger user change", comments.User.TriggerChange);
AddStep("Idle state", () =>
{
scroll.Clear();
scroll.Add(comments = new TestCommentsContainer());
});
}
private class TestCommentsContainer : CommentsContainer
{ {
public new Bindable<User> User => base.User; AddUntilStep("loading spinner shown",
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().IsLoading);
} }
[Test]
public void TestSingleCommentsPage()
{
setUpCommentsResponse(exampleComments);
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
AddUntilStep("show more button hidden",
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().Alpha == 0);
}
[Test]
public void TestMultipleCommentPages()
{
var comments = exampleComments;
comments.HasMore = true;
comments.TopLevelCount = 10;
setUpCommentsResponse(comments);
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
AddUntilStep("show more button visible",
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().Alpha == 1);
}
[Test]
public void TestMultipleLoads()
{
var comments = exampleComments;
int topLevelCommentCount = exampleComments.Comments.Count(comment => comment.IsTopLevel);
AddStep("hide container", () => commentsContainer.Hide());
setUpCommentsResponse(comments);
AddRepeatStep("show comments multiple times",
() => commentsContainer.ShowComments(CommentableType.Beatmapset, 456), 2);
AddStep("show container", () => commentsContainer.Show());
AddUntilStep("comment count is correct",
() => commentsContainer.ChildrenOfType<DrawableComment>().Count() == topLevelCommentCount);
}
private void setUpCommentsResponse(CommentBundle commentBundle)
=> AddStep("set up response", () =>
{
dummyAPI.HandleRequest = request =>
{
if (!(request is GetCommentsRequest getCommentsRequest))
return;
getCommentsRequest.TriggerSuccess(commentBundle);
};
});
private CommentBundle exampleComments => new CommentBundle
{
Comments = new List<Comment>
{
new Comment
{
Id = 1,
Message = "This is a comment",
LegacyName = "FirstUser",
CreatedAt = DateTimeOffset.Now,
VotesCount = 19,
RepliesCount = 1
},
new Comment
{
Id = 5,
ParentId = 1,
Message = "This is a child comment",
LegacyName = "SecondUser",
CreatedAt = DateTimeOffset.Now,
VotesCount = 4,
},
new Comment
{
Id = 10,
Message = "This is another comment",
LegacyName = "ThirdUser",
CreatedAt = DateTimeOffset.Now,
VotesCount = 0
},
},
IncludedComments = new List<Comment>(),
};
} }
} }

View File

@ -77,6 +77,8 @@ namespace osu.Game.Tournament.Components
flow = new FillFlowContainer flow = new FillFlowContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
// Todo: This is a hack for https://github.com/ppy/osu-framework/issues/3617 since this container is at the very edge of the screen and potentially initially masked away.
Height = 1,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
LayoutDuration = 500, LayoutDuration = 500,
LayoutEasing = Easing.OutQuint, LayoutEasing = Easing.OutQuint,

View File

@ -17,6 +17,8 @@ namespace osu.Game.Graphics.UserInterface
{ {
private readonly SpriteIcon spinner; private readonly SpriteIcon spinner;
protected override bool StartHidden => true;
protected Container MainContents; protected Container MainContents;
public const float TRANSITION_DURATION = 500; public const float TRANSITION_DURATION = 500;

View File

@ -39,6 +39,8 @@ namespace osu.Game.Input.Bindings
new KeyBinding(InputKey.Escape, GlobalAction.Back), new KeyBinding(InputKey.Escape, GlobalAction.Back),
new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back), new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back),
new KeyBinding(new[] { InputKey.Alt, InputKey.Home }, GlobalAction.Home),
new KeyBinding(InputKey.Up, GlobalAction.SelectPrevious), new KeyBinding(InputKey.Up, GlobalAction.SelectPrevious),
new KeyBinding(InputKey.Down, GlobalAction.SelectNext), new KeyBinding(InputKey.Down, GlobalAction.SelectNext),
@ -152,5 +154,8 @@ namespace osu.Game.Input.Bindings
[Description("Next Selection")] [Description("Next Selection")]
SelectNext, SelectNext,
[Description("Home")]
Home,
} }
} }

View File

@ -20,6 +20,10 @@ namespace osu.Game.Overlays.BeatmapListing
[Description("Hip Hop")] [Description("Hip Hop")]
HipHop = 9, HipHop = 9,
Electronic = 10 Electronic = 10,
Metal = 11,
Classical = 12,
Folk = 13,
Jazz = 14
} }
} }

View File

@ -11,8 +11,8 @@ namespace osu.Game.Overlays.BeatmapListing
[Order(0)] [Order(0)]
Any, Any,
[Order(11)] [Order(14)]
Other, Unspecified,
[Order(1)] [Order(1)]
English, English,
@ -23,7 +23,7 @@ namespace osu.Game.Overlays.BeatmapListing
[Order(2)] [Order(2)]
Chinese, Chinese,
[Order(10)] [Order(12)]
Instrumental, Instrumental,
[Order(7)] [Order(7)]
@ -42,6 +42,15 @@ namespace osu.Game.Overlays.BeatmapListing
Spanish, Spanish,
[Order(5)] [Order(5)]
Italian Italian,
[Order(10)]
Russian,
[Order(11)]
Polish,
[Order(13)]
Other
} }
} }

View File

@ -12,6 +12,7 @@ using osu.Game.Online.API.Requests.Responses;
using System.Threading; using System.Threading;
using System.Linq; using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Threading;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Overlays.Comments namespace osu.Game.Overlays.Comments
@ -30,6 +31,7 @@ namespace osu.Game.Overlays.Comments
private IAPIProvider api { get; set; } private IAPIProvider api { get; set; }
private GetCommentsRequest request; private GetCommentsRequest request;
private ScheduledDelegate scheduledCommentsLoad;
private CancellationTokenSource loadCancellation; private CancellationTokenSource loadCancellation;
private int currentPage; private int currentPage;
@ -152,8 +154,9 @@ namespace osu.Game.Overlays.Comments
request?.Cancel(); request?.Cancel();
loadCancellation?.Cancel(); loadCancellation?.Cancel();
scheduledCommentsLoad?.Cancel();
request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0); request = new GetCommentsRequest(id.Value, type.Value, Sort.Value, currentPage++, 0);
request.Success += res => Schedule(() => onSuccess(res)); request.Success += res => scheduledCommentsLoad = Schedule(() => onSuccess(res));
api.PerformAsync(request); api.PerformAsync(request);
} }

View File

@ -62,6 +62,7 @@ namespace osu.Game.Overlays.Toolbar
protected ConstrainedIconContainer IconContainer; protected ConstrainedIconContainer IconContainer;
protected SpriteText DrawableText; protected SpriteText DrawableText;
protected Box HoverBackground; protected Box HoverBackground;
private readonly Box flashBackground;
private readonly FillFlowContainer tooltipContainer; private readonly FillFlowContainer tooltipContainer;
private readonly SpriteText tooltip1; private readonly SpriteText tooltip1;
private readonly SpriteText tooltip2; private readonly SpriteText tooltip2;
@ -82,6 +83,13 @@ namespace osu.Game.Overlays.Toolbar
Blending = BlendingParameters.Additive, Blending = BlendingParameters.Additive,
Alpha = 0, Alpha = 0,
}, },
flashBackground = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Colour = Color4.White.Opacity(100),
Blending = BlendingParameters.Additive,
},
Flow = new FillFlowContainer Flow = new FillFlowContainer
{ {
Direction = FillDirection.Horizontal, Direction = FillDirection.Horizontal,
@ -139,7 +147,7 @@ namespace osu.Game.Overlays.Toolbar
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
HoverBackground.FlashColour(Color4.White.Opacity(100), 500, Easing.OutQuint); flashBackground.FadeOutFromOne(800, Easing.OutQuint);
tooltipContainer.FadeOut(100); tooltipContainer.FadeOut(100);
return base.OnClick(e); return base.OnClick(e);
} }

View File

@ -2,10 +2,12 @@
// 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; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings;
using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarHomeButton : ToolbarButton public class ToolbarHomeButton : ToolbarButton, IKeyBindingHandler<GlobalAction>
{ {
public ToolbarHomeButton() public ToolbarHomeButton()
{ {
@ -13,5 +15,20 @@ namespace osu.Game.Overlays.Toolbar
TooltipMain = "Home"; TooltipMain = "Home";
TooltipSub = "Return to the main menu"; TooltipSub = "Return to the main menu";
} }
public bool OnPressed(GlobalAction action)
{
if (action == GlobalAction.Home)
{
Click();
return true;
}
return false;
}
public void OnReleased(GlobalAction action)
{
}
} }
} }

View File

@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.Mods
[SettingSource("Final rate", "The final speed to ramp to")] [SettingSource("Final rate", "The final speed to ramp to")]
public abstract BindableNumber<double> FinalRate { get; } public abstract BindableNumber<double> FinalRate { get; }
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public abstract BindableBool AdjustPitch { get; }
public override string SettingDescription => $"{InitialRate.Value:N2}x to {FinalRate.Value:N2}x"; public override string SettingDescription => $"{InitialRate.Value:N2}x to {FinalRate.Value:N2}x";
private double finalRateTime; private double finalRateTime;
@ -43,15 +46,16 @@ namespace osu.Game.Rulesets.Mods
protected ModTimeRamp() protected ModTimeRamp()
{ {
// for preview purpose at song select. eventually we'll want to be able to update every frame. // for preview purpose at song select. eventually we'll want to be able to update every frame.
FinalRate.BindValueChanged(val => applyAdjustment(1), true); FinalRate.BindValueChanged(val => applyRateAdjustment(1), true);
AdjustPitch.BindValueChanged(applyPitchAdjustment);
} }
public void ApplyToTrack(Track track) public void ApplyToTrack(Track track)
{ {
this.track = track; this.track = track;
track.AddAdjustment(AdjustableProperty.Frequency, SpeedChange);
FinalRate.TriggerChange(); FinalRate.TriggerChange();
AdjustPitch.TriggerChange();
} }
public virtual void ApplyToBeatmap(IBeatmap beatmap) public virtual void ApplyToBeatmap(IBeatmap beatmap)
@ -66,14 +70,25 @@ namespace osu.Game.Rulesets.Mods
public virtual void Update(Playfield playfield) public virtual void Update(Playfield playfield)
{ {
applyAdjustment((track.CurrentTime - beginRampTime) / finalRateTime); applyRateAdjustment((track.CurrentTime - beginRampTime) / finalRateTime);
} }
/// <summary> /// <summary>
/// Adjust the rate along the specified ramp /// Adjust the rate along the specified ramp
/// </summary> /// </summary>
/// <param name="amount">The amount of adjustment to apply (from 0..1).</param> /// <param name="amount">The amount of adjustment to apply (from 0..1).</param>
private void applyAdjustment(double amount) => private void applyRateAdjustment(double amount) =>
SpeedChange.Value = InitialRate.Value + (FinalRate.Value - InitialRate.Value) * Math.Clamp(amount, 0, 1); SpeedChange.Value = InitialRate.Value + (FinalRate.Value - InitialRate.Value) * Math.Clamp(amount, 0, 1);
private void applyPitchAdjustment(ValueChangedEvent<bool> adjustPitchSetting)
{
// remove existing old adjustment
track.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange);
track.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange);
}
private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue)
=> adjustPitchSettingValue ? AdjustableProperty.Frequency : AdjustableProperty.Tempo;
} }
} }

View File

@ -37,6 +37,13 @@ namespace osu.Game.Rulesets.Mods
Precision = 0.01, Precision = 0.01,
}; };
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public override BindableBool AdjustPitch { get; } = new BindableBool
{
Default = true,
Value = true
};
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray();
} }
} }

View File

@ -37,6 +37,13 @@ namespace osu.Game.Rulesets.Mods
Precision = 0.01, Precision = 0.01,
}; };
[SettingSource("Adjust pitch", "Should pitch be adjusted with speed")]
public override BindableBool AdjustPitch { get; } = new BindableBool
{
Default = true,
Value = true
};
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray();
} }
} }

View File

@ -18,6 +18,8 @@ namespace osu.Game.Scoring
protected override IQueryable<ScoreInfo> AddIncludesForConsumption(IQueryable<ScoreInfo> query) protected override IQueryable<ScoreInfo> AddIncludesForConsumption(IQueryable<ScoreInfo> query)
=> base.AddIncludesForConsumption(query) => base.AddIncludesForConsumption(query)
.Include(s => s.Beatmap) .Include(s => s.Beatmap)
.Include(s => s.Beatmap).ThenInclude(b => b.Metadata)
.Include(s => s.Beatmap).ThenInclude(b => b.BeatmapSet).ThenInclude(s => s.Metadata)
.Include(s => s.Ruleset); .Include(s => s.Ruleset);
} }
} }

View File

@ -44,8 +44,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>(); private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>();
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
[Resolved(canBeNull: true)] [Resolved(canBeNull: true)]
private IPositionSnapProvider snapProvider { get; set; } private IPositionSnapProvider snapProvider { get; set; }

View File

@ -11,6 +11,7 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Edit.Tools;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
namespace osu.Game.Screens.Edit.Compose.Components namespace osu.Game.Screens.Edit.Compose.Components
{ {
@ -26,6 +27,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
private readonly Container<PlacementBlueprint> placementBlueprintContainer; private readonly Container<PlacementBlueprint> placementBlueprintContainer;
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
private InputManager inputManager; private InputManager inputManager;
private readonly IEnumerable<DrawableHitObject> drawableHitObjects; private readonly IEnumerable<DrawableHitObject> drawableHitObjects;

View File

@ -251,8 +251,9 @@ namespace osu.Game.Screens.Play
private class HardwareCorrectionOffsetClock : FramedOffsetClock private class HardwareCorrectionOffsetClock : FramedOffsetClock
{ {
// we always want to apply the same real-time offset, so it should be adjusted by the playback rate to achieve this. // we always want to apply the same real-time offset, so it should be adjusted by the difference in playback rate (from realtime) to achieve this.
public override double CurrentTime => SourceTime + Offset * Rate; // base implementation already adds offset at 1.0 rate, so we only add the difference from that here.
public override double CurrentTime => base.CurrentTime + Offset * (Rate - 1);
public HardwareCorrectionOffsetClock(IClock source, bool processSource = true) public HardwareCorrectionOffsetClock(IClock source, bool processSource = true)
: base(source, processSource) : base(source, processSource)

View File

@ -43,6 +43,12 @@ namespace osu.Game.Skinning
MinimumColumnWidth, MinimumColumnWidth,
LeftStageImage, LeftStageImage,
RightStageImage, RightStageImage,
BottomStageImage BottomStageImage,
Hit300g,
Hit300,
Hit200,
Hit100,
Hit50,
Hit0,
} }
} }

View File

@ -111,11 +111,10 @@ namespace osu.Game.Skinning
HandleColours(currentConfig, line); HandleColours(currentConfig, line);
break; break;
// Custom sprite paths
case string _ when pair.Key.StartsWith("NoteImage"): case string _ when pair.Key.StartsWith("NoteImage"):
currentConfig.ImageLookups[pair.Key] = pair.Value;
break;
case string _ when pair.Key.StartsWith("KeyImage"): case string _ when pair.Key.StartsWith("KeyImage"):
case string _ when pair.Key.StartsWith("Hit"):
currentConfig.ImageLookups[pair.Key] = pair.Value; currentConfig.ImageLookups[pair.Key] = pair.Value;
break; break;
} }

View File

@ -257,6 +257,14 @@ namespace osu.Game.Skinning
case LegacyManiaSkinConfigurationLookups.RightLineWidth: case LegacyManiaSkinConfigurationLookups.RightLineWidth:
Debug.Assert(maniaLookup.TargetColumn != null); Debug.Assert(maniaLookup.TargetColumn != null);
return SkinUtils.As<TValue>(new Bindable<float>(existing.ColumnLineWidth[maniaLookup.TargetColumn.Value + 1])); return SkinUtils.As<TValue>(new Bindable<float>(existing.ColumnLineWidth[maniaLookup.TargetColumn.Value + 1]));
case LegacyManiaSkinConfigurationLookups.Hit0:
case LegacyManiaSkinConfigurationLookups.Hit50:
case LegacyManiaSkinConfigurationLookups.Hit100:
case LegacyManiaSkinConfigurationLookups.Hit200:
case LegacyManiaSkinConfigurationLookups.Hit300:
case LegacyManiaSkinConfigurationLookups.Hit300g:
return SkinUtils.As<TValue>(getManiaImage(existing, maniaLookup.Lookup.ToString()));
} }
return null; return null;

View File

@ -51,7 +51,7 @@ namespace osu.Game.Storyboards.Drawables
LifetimeStart = sampleInfo.StartTime; LifetimeStart = sampleInfo.StartTime;
LifetimeEnd = double.MaxValue; LifetimeEnd = double.MaxValue;
} }
else if (Time.Current - Time.Elapsed < sampleInfo.StartTime) else if (Time.Current - Time.Elapsed <= sampleInfo.StartTime)
{ {
// We've passed the start time of the sample. We only play the sample if we're within an allowable range // We've passed the start time of the sample. We only play the sample if we're within an allowable range
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future // from the sample's start, to reduce layering if we've been fast-forwarded far into the future

View File

@ -2,6 +2,7 @@
// 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.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -15,17 +16,10 @@ namespace osu.Game.Tests.Visual
{ {
protected Editor Editor { get; private set; } protected Editor Editor { get; private set; }
private readonly Ruleset ruleset;
protected EditorTestScene(Ruleset ruleset)
{
this.ruleset = ruleset;
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Beatmap.Value = CreateWorkingBeatmap(ruleset.RulesetInfo); Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
} }
public override void SetUpSteps() public override void SetUpSteps()
@ -37,6 +31,14 @@ namespace osu.Game.Tests.Visual
&& Editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true); && Editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true);
} }
/// <summary>
/// Creates the ruleset for providing a corresponding beatmap to load the editor on.
/// </summary>
[NotNull]
protected abstract Ruleset CreateEditorRuleset();
protected sealed override Ruleset CreateRuleset() => CreateEditorRuleset();
protected virtual Editor CreateEditor() => new Editor(); protected virtual Editor CreateEditor() => new Editor();
} }
} }

View File

@ -10,13 +10,10 @@ namespace osu.Game.Tests.Visual
{ {
public abstract class ModPerfectTestScene : ModTestScene public abstract class ModPerfectTestScene : ModTestScene
{ {
private readonly Ruleset ruleset;
private readonly ModPerfect mod; private readonly ModPerfect mod;
protected ModPerfectTestScene(Ruleset ruleset, ModPerfect mod) protected ModPerfectTestScene(ModPerfect mod)
: base(ruleset)
{ {
this.ruleset = ruleset;
this.mod = mod; this.mod = mod;
} }
@ -25,7 +22,7 @@ namespace osu.Game.Tests.Visual
Mod = mod, Mod = mod,
Beatmap = new Beatmap Beatmap = new Beatmap
{ {
BeatmapInfo = { Ruleset = ruleset.RulesetInfo }, BeatmapInfo = { Ruleset = CreatePlayerRuleset().RulesetInfo },
HitObjects = { testData.HitObject } HitObjects = { testData.HitObject }
}, },
Autoplay = !shouldMiss, Autoplay = !shouldMiss,

View File

@ -14,11 +14,6 @@ namespace osu.Game.Tests.Visual
{ {
protected sealed override bool HasCustomSteps => true; protected sealed override bool HasCustomSteps => true;
protected ModTestScene(Ruleset ruleset)
: base(ruleset)
{
}
private ModTestData currentTestData; private ModTestData currentTestData;
protected void CreateModTest(ModTestData testData) => CreateTest(() => protected void CreateModTest(ModTestData testData) => CreateTest(() =>

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework; using osu.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
@ -125,6 +126,15 @@ namespace osu.Game.Tests.Visual
[Resolved] [Resolved]
protected AudioManager Audio { get; private set; } protected AudioManager Audio { get; private set; }
/// <summary>
/// Creates the ruleset to be used for this test scene.
/// </summary>
/// <remarks>
/// When testing against ruleset-specific components, this method must be overriden to their corresponding ruleset.
/// </remarks>
[CanBeNull]
protected virtual Ruleset CreateRuleset() => null;
protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset);
protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) => protected WorkingBeatmap CreateWorkingBeatmap(RulesetInfo ruleset) =>
@ -136,7 +146,7 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(RulesetStore rulesets) private void load(RulesetStore rulesets)
{ {
Ruleset.Value = rulesets.AvailableRulesets.First(); Ruleset.Value = CreateRuleset()?.RulesetInfo ?? rulesets.AvailableRulesets.First();
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Testing; using osu.Framework.Testing;
@ -19,15 +20,8 @@ namespace osu.Game.Tests.Visual
/// </summary> /// </summary>
protected virtual bool HasCustomSteps { get; } = false; protected virtual bool HasCustomSteps { get; } = false;
private readonly Ruleset ruleset;
protected TestPlayer Player; protected TestPlayer Player;
protected PlayerTestScene(Ruleset ruleset)
{
this.ruleset = ruleset;
}
protected OsuConfigManager LocalConfig; protected OsuConfigManager LocalConfig;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -53,7 +47,7 @@ namespace osu.Game.Tests.Visual
action?.Invoke(); action?.Invoke();
AddStep(ruleset.RulesetInfo.Name, LoadPlayer); AddStep(CreatePlayerRuleset().Description, LoadPlayer);
AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1); AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1);
} }
@ -63,11 +57,10 @@ namespace osu.Game.Tests.Visual
protected void LoadPlayer() protected void LoadPlayer()
{ {
var ruleset = Ruleset.Value.CreateInstance();
var beatmap = CreateBeatmap(ruleset.RulesetInfo); var beatmap = CreateBeatmap(ruleset.RulesetInfo);
Beatmap.Value = CreateWorkingBeatmap(beatmap); Beatmap.Value = CreateWorkingBeatmap(beatmap);
Ruleset.Value = ruleset.RulesetInfo;
SelectedMods.Value = Array.Empty<Mod>(); SelectedMods.Value = Array.Empty<Mod>();
if (!AllowFail) if (!AllowFail)
@ -88,6 +81,14 @@ namespace osu.Game.Tests.Visual
LoadScreen(Player); LoadScreen(Player);
} }
/// <summary>
/// Creates the ruleset for setting up the <see cref="Player"/> component.
/// </summary>
[NotNull]
protected abstract Ruleset CreatePlayerRuleset();
protected sealed override Ruleset CreateRuleset() => CreatePlayerRuleset();
protected virtual TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false); protected virtual TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false);
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -32,9 +33,6 @@ namespace osu.Game.Tests.Visual
{ {
} }
// Required to be part of the per-ruleset implementation to construct the newer version of the Ruleset.
protected abstract Ruleset CreateRulesetForSkinProvider();
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio, SkinManager skinManager) private void load(AudioManager audio, SkinManager skinManager)
{ {
@ -107,7 +105,7 @@ namespace osu.Game.Tests.Visual
{ {
new OutlineBox { Alpha = autoSize ? 1 : 0 }, new OutlineBox { Alpha = autoSize ? 1 : 0 },
mainProvider.WithChild( mainProvider.WithChild(
new SkinProvidingContainer(CreateRulesetForSkinProvider().CreateLegacySkinProvider(mainProvider, beatmap)) new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider, beatmap))
{ {
Child = created, Child = created,
RelativeSizeAxes = !autoSize ? Axes.Both : Axes.None, RelativeSizeAxes = !autoSize ? Axes.Both : Axes.None,
@ -120,6 +118,14 @@ namespace osu.Game.Tests.Visual
}; };
} }
/// <summary>
/// Creates the ruleset for adding the corresponding skin transforming component.
/// </summary>
[NotNull]
protected abstract Ruleset CreateRulesetForSkinProvider();
protected sealed override Ruleset CreateRuleset() => CreateRulesetForSkinProvider();
protected virtual IBeatmap CreateBeatmapForSkinProvider() => CreateWorkingBeatmap(Ruleset.Value).GetPlayableBeatmap(Ruleset.Value); protected virtual IBeatmap CreateBeatmapForSkinProvider() => CreateWorkingBeatmap(Ruleset.Value).GetPlayableBeatmap(Ruleset.Value);
private class OutlineBox : CompositeDrawable private class OutlineBox : CompositeDrawable