mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 19:02:57 +08:00
Merge branch 'master' into better-filter-bypass
This commit is contained in:
commit
e085aa8c1d
42
.vscode/launch.json
vendored
42
.vscode/launch.json
vendored
@ -11,11 +11,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -28,11 +23,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -45,11 +35,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -62,11 +47,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -80,11 +60,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -98,11 +73,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -116,11 +86,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -134,11 +99,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -169,4 +129,4 @@
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,6 @@ namespace osu.Android
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new SimpleUpdateManager());
|
||||
}
|
||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||
}
|
||||
}
|
@ -47,20 +47,25 @@ namespace osu.Desktop
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager()
|
||||
{
|
||||
switch (RuntimeInfo.OS)
|
||||
{
|
||||
case RuntimeInfo.Platform.Windows:
|
||||
return new SquirrelUpdateManager();
|
||||
|
||||
default:
|
||||
return new SimpleUpdateManager();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (!noVersionOverlay)
|
||||
{
|
||||
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
|
||||
|
||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
|
||||
Add(new SquirrelUpdateManager());
|
||||
else
|
||||
Add(new SimpleUpdateManager());
|
||||
}
|
||||
|
||||
LoadComponentAsync(new DiscordRichPresence(), Add);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return base.CreatePlayer(ruleset);
|
||||
|
@ -0,0 +1,86 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public class TestSceneOsuModDifficultyAdjust : ModTestScene
|
||||
{
|
||||
public TestSceneOsuModDifficultyAdjust()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoAdjustment() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust(),
|
||||
Autoplay = true,
|
||||
PassCondition = checkSomeHit
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestCircleSize1() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 1 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsScale(0.78f)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestCircleSize10() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 10 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsScale(0.15f)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestApproachRate1() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsPreempt(1680)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestApproachRate10() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 10 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsPreempt(450)
|
||||
});
|
||||
|
||||
private bool checkObjectsPreempt(double target)
|
||||
{
|
||||
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||
if (!objects.Any())
|
||||
return false;
|
||||
|
||||
return objects.All(o => o.HitObject.TimePreempt == target);
|
||||
}
|
||||
|
||||
private bool checkObjectsScale(float target)
|
||||
{
|
||||
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||
if (!objects.Any())
|
||||
return false;
|
||||
|
||||
return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<ShakeContainer>().First().Children.OfType<Container>().Single().Scale.X, target));
|
||||
}
|
||||
|
||||
private bool checkSomeHit()
|
||||
{
|
||||
return Player.ScoreProcessor.JudgedHits >= 2;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@ -114,6 +117,22 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
assertGroups();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStackedObjects()
|
||||
{
|
||||
addObjectsStep(() => new OsuHitObject[]
|
||||
{
|
||||
new HitCircle { Position = new Vector2(300, 100) },
|
||||
new HitCircle
|
||||
{
|
||||
Position = new Vector2(300, 300),
|
||||
StackHeight = 20
|
||||
},
|
||||
});
|
||||
|
||||
assertDirections();
|
||||
}
|
||||
|
||||
private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[]
|
||||
{
|
||||
new HitCircle { Position = new Vector2(100, 100) },
|
||||
@ -207,6 +226,33 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
});
|
||||
}
|
||||
|
||||
private void assertDirections()
|
||||
{
|
||||
AddAssert("group directions are correct", () =>
|
||||
{
|
||||
for (int i = 0; i < hitObjectContainer.Count; i++)
|
||||
{
|
||||
DrawableOsuHitObject expectedStart = getObject(i);
|
||||
DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null;
|
||||
|
||||
if (expectedEnd == null)
|
||||
continue;
|
||||
|
||||
var points = getGroup(i).ChildrenOfType<FollowPoint>().ToArray();
|
||||
if (points.Length == 0)
|
||||
continue;
|
||||
|
||||
float expectedDirection = MathF.Atan2(expectedStart.Position.Y - expectedEnd.Position.Y, expectedStart.Position.X - expectedEnd.Position.X);
|
||||
float realDirection = MathF.Atan2(expectedStart.Position.Y - points[^1].Position.Y, expectedStart.Position.X - points[^1].Position.X);
|
||||
|
||||
if (!Precision.AlmostEquals(expectedDirection, realDirection))
|
||||
throw new AssertionException($"Expected group {i} in direction {expectedDirection}, but was {realDirection}.");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index];
|
||||
|
||||
private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index];
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
||||
{
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
|
||||
|
||||
|
@ -18,7 +18,6 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Game.Tests.Visual;
|
||||
@ -56,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
private void checkNextHitObject(string skin) =>
|
||||
AddUntilStep($"check skin from {skin}", () =>
|
||||
{
|
||||
var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
||||
var firstObject = Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
||||
|
||||
if (firstObject == null)
|
||||
return false;
|
||||
@ -75,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
[Resolved]
|
||||
private AudioManager audio { get; set; }
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin);
|
||||
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
base.SetUpSteps();
|
||||
|
||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First());
|
||||
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -89,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
AddStep($"seek to {time}", () => track.Seek(time));
|
||||
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||
|
@ -104,8 +104,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 startPosition = osuStart.EndPosition;
|
||||
Vector2 endPosition = osuEnd.Position;
|
||||
Vector2 startPosition = osuStart.StackedEndPosition;
|
||||
Vector2 endPosition = osuEnd.StackedPosition;
|
||||
double endTime = osuEnd.StartTime;
|
||||
|
||||
Vector2 distanceVector = endPosition - startPosition;
|
||||
|
@ -1,23 +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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TestSceneSwellJudgements : PlayerTestScene
|
||||
{
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
public TestSceneSwellJudgements()
|
||||
: base(new TaikoRuleset())
|
||||
{
|
||||
@ -49,25 +42,5 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer();
|
||||
|
||||
protected class TestPlayer : Player
|
||||
{
|
||||
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public TestPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScoreProcessor.NewJudgement += r => Results.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
@ -22,10 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
return base.CreatePlayer(ruleset);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
||||
@ -49,20 +47,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
AddStep("Setup judgements", () =>
|
||||
{
|
||||
judged = false;
|
||||
((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
|
||||
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
||||
});
|
||||
AddUntilStep("swell judged", () => judged);
|
||||
AddAssert("not failed", () => !Player.HasFailed);
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
private DummySongSelect songSelect;
|
||||
private TestPlayerLoader playerLoader;
|
||||
private TestPlayer player;
|
||||
private LoadBlockingTestPlayer player;
|
||||
private BeatmapManager manager;
|
||||
private RulesetStore rulesets;
|
||||
|
||||
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public void PlayerLoaderSettingsHoverTest()
|
||||
{
|
||||
setupUserSettings();
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer { BlockLoad = true })));
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true })));
|
||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
|
||||
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
|
||||
AddStep("Trigger background preview", () =>
|
||||
@ -268,7 +268,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
setupUserSettings();
|
||||
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer(allowPause))));
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer(allowPause))));
|
||||
|
||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
|
||||
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
||||
@ -347,7 +347,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||
}
|
||||
|
||||
private class TestPlayer : Visual.TestPlayer
|
||||
private class LoadBlockingTestPlayer : TestPlayer
|
||||
{
|
||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
||||
|
||||
@ -360,7 +360,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
|
||||
public readonly Bindable<bool> IsPaused = new Bindable<bool>();
|
||||
|
||||
public TestPlayer(bool allowPause = true)
|
||||
public LoadBlockingTestPlayer(bool allowPause = true)
|
||||
: base(allowPause)
|
||||
{
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
@ -14,20 +13,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[Description("Player instantiated with an autoplay mod.")]
|
||||
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
||||
{
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
return new TestPlayer(false, false);
|
||||
}
|
||||
|
||||
protected override void AddCheckSteps()
|
||||
{
|
||||
AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0);
|
||||
AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
||||
AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0);
|
||||
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
||||
AddStep("rewind", () => track.Seek(-10000));
|
||||
AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
}
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
@ -38,18 +39,5 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
return working;
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -11,12 +10,8 @@ using osu.Framework.Utils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
using osuTK;
|
||||
|
||||
@ -24,8 +19,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneGameplayRewinding : PlayerTestScene
|
||||
{
|
||||
private RulesetExposingPlayer player => (RulesetExposingPlayer)Player;
|
||||
|
||||
[Resolved]
|
||||
private AudioManager audioManager { get; set; }
|
||||
|
||||
@ -48,13 +41,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||
addSeekStep(3000);
|
||||
AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
||||
AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
||||
AddStep("clear results", () => player.AppliedResults.Clear());
|
||||
AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
||||
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
||||
AddStep("clear results", () => Player.Results.Clear());
|
||||
addSeekStep(0);
|
||||
AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
||||
AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
AddAssert("no results triggered", () => player.AppliedResults.Count == 0);
|
||||
AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
||||
AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
AddAssert("no results triggered", () => Player.Results.Count == 0);
|
||||
}
|
||||
|
||||
private void addSeekStep(double time)
|
||||
@ -62,13 +55,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddStep($"seek to {time}", () => track.Seek(time));
|
||||
|
||||
// Allow a few frames of lenience
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return new RulesetExposingPlayer();
|
||||
return base.CreatePlayer(ruleset);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
@ -89,29 +82,5 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private class RulesetExposingPlayer : Player
|
||||
{
|
||||
public readonly List<JudgementResult> AppliedResults = new List<JudgementResult>();
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
|
||||
|
||||
public RulesetExposingPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScoreProcessor.NewJudgement += r => AppliedResults.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
@ -282,14 +281,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
||||
|
||||
protected class PausePlayer : TestPlayer
|
||||
{
|
||||
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
||||
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
|
||||
|
||||
public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
|
||||
|
@ -9,15 +9,12 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
||||
public class TestScenePauseWhenInactive : PlayerTestScene
|
||||
{
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
|
||||
@ -46,6 +43,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Utils;
|
||||
@ -307,17 +306,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
||||
}
|
||||
|
||||
private class TestPlayer : Visual.TestPlayer
|
||||
{
|
||||
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
||||
|
||||
public TestPlayer(bool allowPause = true, bool showResults = true)
|
||||
: base(allowPause, showResults)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected class SlowLoadPlayer : Visual.TestPlayer
|
||||
protected class SlowLoadPlayer : TestPlayer
|
||||
{
|
||||
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false);
|
||||
|
||||
|
@ -62,14 +62,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
var frameworkConfig = host.Dependencies.Get<FrameworkConfigManager>();
|
||||
frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity).Disabled = false;
|
||||
|
||||
Game = new TestOsuGame(LocalStorage, API);
|
||||
Game.SetHost(host);
|
||||
|
||||
// todo: this can be removed once we can run audio tracks without a device present
|
||||
// see https://github.com/ppy/osu/issues/1302
|
||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||
|
||||
Add(Game);
|
||||
CreateGame();
|
||||
});
|
||||
|
||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||
@ -78,6 +71,18 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
ConfirmAtMainMenu();
|
||||
}
|
||||
|
||||
protected void CreateGame()
|
||||
{
|
||||
Game = new TestOsuGame(LocalStorage, API);
|
||||
Game.SetHost(host);
|
||||
|
||||
// todo: this can be removed once we can run audio tracks without a device present
|
||||
// see https://github.com/ppy/osu/issues/1302
|
||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||
|
||||
Add(Game);
|
||||
}
|
||||
|
||||
protected void PushAndConfirm(Func<Screen> newScreen)
|
||||
{
|
||||
Screen screen = null;
|
||||
@ -97,12 +102,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
public new SettingsPanel Settings => base.Settings;
|
||||
|
||||
public new MusicController MusicController => base.MusicController;
|
||||
|
||||
public new OsuConfigManager LocalConfig => base.LocalConfig;
|
||||
|
||||
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
|
||||
|
||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||
|
||||
// if we don't do this, when running under nUnit the version that gets populated is that of nUnit.
|
||||
public override string Version => "test game";
|
||||
|
||||
protected override Loader CreateLoader() => new TestLoader();
|
||||
|
||||
public new void PerformFromScreen(Action<IScreen> action, IEnumerable<Type> validScreens = null) => base.PerformFromScreen(action, validScreens);
|
||||
|
@ -114,6 +114,22 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWaitForNextTrackInMenu()
|
||||
{
|
||||
bool trackCompleted = false;
|
||||
|
||||
AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded);
|
||||
AddStep("Seek close to end", () =>
|
||||
{
|
||||
Game.MusicController.SeekTo(Game.Beatmap.Value.Track.Length - 1000);
|
||||
Game.Beatmap.Value.Track.Completed += () => trackCompleted = true;
|
||||
});
|
||||
|
||||
AddUntilStep("Track was completed", () => trackCompleted);
|
||||
AddUntilStep("Track was restarted", () => Game.Beatmap.Value.Track.IsRunning);
|
||||
}
|
||||
|
||||
private void pushEscape() =>
|
||||
AddStep("Press escape", () => pressAndRelease(Key.Escape));
|
||||
|
||||
|
41
osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
Normal file
41
osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Configuration;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
public class TestSettingsMigration : OsuGameTestScene
|
||||
{
|
||||
public override void RecycleLocalStorage()
|
||||
{
|
||||
base.RecycleLocalStorage();
|
||||
|
||||
using (var config = new OsuConfigManager(LocalStorage))
|
||||
{
|
||||
config.Set(OsuSetting.Version, "2020.101.0");
|
||||
config.Set(OsuSetting.DisplayStarsMaximum, 10.0);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisplayStarsMigration()
|
||||
{
|
||||
AddAssert("config has migrated value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10.1));
|
||||
|
||||
AddStep("set value again", () => Game.LocalConfig.Set<double>(OsuSetting.DisplayStarsMaximum, 10));
|
||||
|
||||
AddStep("force save config", () => Game.LocalConfig.Save());
|
||||
|
||||
AddStep("remove game", () => Remove(Game));
|
||||
|
||||
AddStep("create game again", CreateGame);
|
||||
|
||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||
|
||||
AddAssert("config did not migrate value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10));
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
@ -13,13 +15,19 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestFixture]
|
||||
public class TestSceneUserPanel : OsuTestScene
|
||||
{
|
||||
private readonly UserPanel peppy;
|
||||
private readonly Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||
|
||||
public TestSceneUserPanel()
|
||||
private UserPanel peppy;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesetStore { get; set; }
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
UserPanel flyte;
|
||||
|
||||
Add(new FillFlowContainer
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -44,34 +52,38 @@ namespace osu.Game.Tests.Visual.Online
|
||||
SupportLevel = 3,
|
||||
}) { Width = 300 },
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
flyte.Status.Value = new UserStatusOnline();
|
||||
peppy.Status.Value = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UserStatusesTests()
|
||||
{
|
||||
AddStep("online", () => { peppy.Status.Value = new UserStatusOnline(); });
|
||||
AddStep(@"do not disturb", () => { peppy.Status.Value = new UserStatusDoNotDisturb(); });
|
||||
AddStep(@"offline", () => { peppy.Status.Value = new UserStatusOffline(); });
|
||||
AddStep(@"null status", () => { peppy.Status.Value = null; });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UserActivitiesTests()
|
||||
{
|
||||
Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||
|
||||
peppy.Activity.BindTo(activity);
|
||||
});
|
||||
|
||||
AddStep("idle", () => { activity.Value = null; });
|
||||
AddStep("spectating", () => { activity.Value = new UserActivity.Spectating(); });
|
||||
AddStep("solo", () => { activity.Value = new UserActivity.SoloGame(null, null); });
|
||||
AddStep("choosing", () => { activity.Value = new UserActivity.ChoosingBeatmap(); });
|
||||
AddStep("editing", () => { activity.Value = new UserActivity.Editing(null); });
|
||||
AddStep("modding", () => { activity.Value = new UserActivity.Modding(); });
|
||||
[Test]
|
||||
public void TestUserStatus()
|
||||
{
|
||||
AddStep("online", () => peppy.Status.Value = new UserStatusOnline());
|
||||
AddStep("do not disturb", () => peppy.Status.Value = new UserStatusDoNotDisturb());
|
||||
AddStep("offline", () => peppy.Status.Value = new UserStatusOffline());
|
||||
AddStep("null status", () => peppy.Status.Value = null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserActivity()
|
||||
{
|
||||
AddStep("set online status", () => peppy.Status.Value = new UserStatusOnline());
|
||||
|
||||
AddStep("idle", () => activity.Value = null);
|
||||
AddStep("spectating", () => activity.Value = new UserActivity.Spectating());
|
||||
AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0));
|
||||
AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1));
|
||||
AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2));
|
||||
AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3));
|
||||
AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap());
|
||||
AddStep("editing", () => activity.Value = new UserActivity.Editing(null));
|
||||
AddStep("modding", () => activity.Value = new UserActivity.Modding());
|
||||
}
|
||||
|
||||
private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.SoloGame(null, rulesetStore.GetRuleset(rulesetId));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Configuration;
|
||||
using osu.Framework.Configuration.Tracking;
|
||||
using osu.Framework.Extensions;
|
||||
@ -126,6 +127,35 @@ namespace osu.Game.Configuration
|
||||
public OsuConfigManager(Storage storage)
|
||||
: base(storage)
|
||||
{
|
||||
Migrate();
|
||||
}
|
||||
|
||||
public void Migrate()
|
||||
{
|
||||
// arrives as 2020.123.0
|
||||
var rawVersion = Get<string>(OsuSetting.Version);
|
||||
|
||||
if (rawVersion.Length < 6)
|
||||
return;
|
||||
|
||||
var pieces = rawVersion.Split('.');
|
||||
|
||||
// on a fresh install or when coming from a non-release build, execution will end here.
|
||||
// we don't want to run migrations in such cases.
|
||||
if (!int.TryParse(pieces[0], out int year)) return;
|
||||
if (!int.TryParse(pieces[1], out int monthDay)) return;
|
||||
|
||||
int combined = (year * 10000) + monthDay;
|
||||
|
||||
if (combined < 20200305)
|
||||
{
|
||||
// the maximum value of this setting was changed.
|
||||
// if we don't manually increase this, it causes song select to filter out beatmaps the user expects to see.
|
||||
var maxStars = (BindableDouble)GetOriginalBindable<double>(OsuSetting.DisplayStarsMaximum);
|
||||
|
||||
if (maxStars.Value == 10)
|
||||
maxStars.Value = maxStars.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
|
||||
|
@ -43,6 +43,7 @@ using osu.Game.Overlays.Volume;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Updater;
|
||||
using osu.Game.Utils;
|
||||
using LogLevel = osu.Framework.Logging.LogLevel;
|
||||
|
||||
@ -390,24 +391,35 @@ namespace osu.Game
|
||||
|
||||
protected virtual Loader CreateLoader() => new Loader();
|
||||
|
||||
protected virtual UpdateManager CreateUpdateManager() => new UpdateManager();
|
||||
|
||||
protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything);
|
||||
|
||||
#region Beatmap progression
|
||||
|
||||
private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> beatmap)
|
||||
{
|
||||
var nextBeatmap = beatmap.NewValue;
|
||||
if (nextBeatmap?.Track != null)
|
||||
nextBeatmap.Track.Completed += currentTrackCompleted;
|
||||
|
||||
var oldBeatmap = beatmap.OldValue;
|
||||
if (oldBeatmap?.Track != null)
|
||||
oldBeatmap.Track.Completed -= currentTrackCompleted;
|
||||
beatmap.OldValue?.CancelAsyncLoad();
|
||||
|
||||
updateModDefaults();
|
||||
|
||||
oldBeatmap?.CancelAsyncLoad();
|
||||
nextBeatmap?.BeginAsyncLoad();
|
||||
var newBeatmap = beatmap.NewValue;
|
||||
|
||||
if (newBeatmap != null)
|
||||
{
|
||||
newBeatmap.Track.Completed += () => Scheduler.AddOnce(() => trackCompleted(newBeatmap));
|
||||
newBeatmap.BeginAsyncLoad();
|
||||
}
|
||||
|
||||
void trackCompleted(WorkingBeatmap b)
|
||||
{
|
||||
// the source of track completion is the audio thread, so the beatmap may have changed before firing.
|
||||
if (Beatmap.Value != b)
|
||||
return;
|
||||
|
||||
if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled)
|
||||
MusicController.NextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
private void modsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
@ -428,12 +440,6 @@ namespace osu.Game
|
||||
}
|
||||
}
|
||||
|
||||
private void currentTrackCompleted() => Schedule(() =>
|
||||
{
|
||||
if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled)
|
||||
musicController.NextTrack();
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
private ScheduledDelegate performFromMainMenuTask;
|
||||
@ -585,7 +591,7 @@ namespace osu.Game
|
||||
|
||||
loadComponentSingleFile(new OnScreenDisplay(), Add, true);
|
||||
|
||||
loadComponentSingleFile(musicController = new MusicController(), Add, true);
|
||||
loadComponentSingleFile(MusicController = new MusicController(), Add, true);
|
||||
|
||||
loadComponentSingleFile(notifications = new NotificationOverlay
|
||||
{
|
||||
@ -628,6 +634,7 @@ namespace osu.Game
|
||||
chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible;
|
||||
|
||||
Add(externalLinkOpener = new ExternalLinkOpener());
|
||||
Add(CreateUpdateManager()); // dependency on notification overlay
|
||||
|
||||
// side overlays which cancel each other.
|
||||
var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications };
|
||||
@ -893,7 +900,7 @@ namespace osu.Game
|
||||
|
||||
private ScalingContainer screenContainer;
|
||||
|
||||
private MusicController musicController;
|
||||
protected MusicController MusicController { get; private set; }
|
||||
|
||||
protected override bool OnExiting()
|
||||
{
|
||||
@ -951,7 +958,7 @@ namespace osu.Game
|
||||
{
|
||||
OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode;
|
||||
|
||||
musicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
|
||||
MusicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
|
||||
|
||||
if (newOsuScreen.HideOverlaysOnEnter)
|
||||
CloseAllOverlays();
|
||||
|
@ -97,7 +97,7 @@ namespace osu.Game
|
||||
|
||||
public bool IsDeployedBuild => AssemblyVersion.Major > 0;
|
||||
|
||||
public string Version
|
||||
public virtual string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -211,6 +211,10 @@ namespace osu.Game
|
||||
Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));
|
||||
|
||||
Beatmap = new NonNullableBindable<WorkingBeatmap>(defaultBeatmap);
|
||||
|
||||
// ScheduleAfterChildren is safety against something in the current frame accessing the previous beatmap's track
|
||||
// and potentially causing a reload of it after just unloading.
|
||||
// Note that the reason for this being added *has* been resolved, so it may be feasible to removed this if required.
|
||||
Beatmap.BindValueChanged(b => ScheduleAfterChildren(() =>
|
||||
{
|
||||
// compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Overlays.SearchableList
|
||||
{
|
||||
public abstract class SearchableListOverlay : FullscreenOverlay
|
||||
{
|
||||
public const float WIDTH_PADDING = 10;
|
||||
public const float WIDTH_PADDING = 80;
|
||||
|
||||
protected SearchableListOverlay(OverlayColourScheme colourScheme)
|
||||
: base(colourScheme)
|
||||
@ -80,7 +80,7 @@ namespace osu.Game.Overlays.SearchableList
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Horizontal = WIDTH_PADDING, Bottom = 50 },
|
||||
Padding = new MarginPadding { Horizontal = 10, Bottom = 50 },
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
},
|
||||
|
99
osu.Game/Tests/Visual/ModTestScene.cs
Normal file
99
osu.Game/Tests/Visual/ModTestScene.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 System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public abstract class ModTestScene : PlayerTestScene
|
||||
{
|
||||
protected sealed override bool HasCustomSteps => true;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ModTestScene)
|
||||
};
|
||||
|
||||
protected ModTestScene(Ruleset ruleset)
|
||||
: base(ruleset)
|
||||
{
|
||||
}
|
||||
|
||||
private ModTestData currentTestData;
|
||||
|
||||
protected void CreateModTest(ModTestData testData) => CreateTest(() =>
|
||||
{
|
||||
AddStep("set test data", () => currentTestData = testData);
|
||||
});
|
||||
|
||||
public override void TearDownSteps()
|
||||
{
|
||||
AddUntilStep("test passed", () =>
|
||||
{
|
||||
if (currentTestData == null)
|
||||
return true;
|
||||
|
||||
return currentTestData.PassCondition?.Invoke() ?? false;
|
||||
});
|
||||
|
||||
base.TearDownSteps();
|
||||
}
|
||||
|
||||
protected sealed override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTestData?.Beatmap ?? base.CreateBeatmap(ruleset);
|
||||
|
||||
protected sealed override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
var mods = new List<Mod>(SelectedMods.Value);
|
||||
|
||||
if (currentTestData.Mod != null)
|
||||
mods.Add(currentTestData.Mod);
|
||||
if (currentTestData.Autoplay)
|
||||
mods.Add(ruleset.GetAutoplayMod());
|
||||
|
||||
SelectedMods.Value = mods;
|
||||
|
||||
return new ModTestPlayer(AllowFail);
|
||||
}
|
||||
|
||||
protected class ModTestPlayer : TestPlayer
|
||||
{
|
||||
protected override bool AllowFail { get; }
|
||||
|
||||
public ModTestPlayer(bool allowFail)
|
||||
: base(false, false)
|
||||
{
|
||||
AllowFail = allowFail;
|
||||
}
|
||||
}
|
||||
|
||||
protected class ModTestData
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to use a replay to simulate an auto-play. True by default.
|
||||
/// </summary>
|
||||
public bool Autoplay = true;
|
||||
|
||||
/// <summary>
|
||||
/// The beatmap for this test case.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public IBeatmap Beatmap;
|
||||
|
||||
/// <summary>
|
||||
/// The conditions that cause this test case to pass.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public Func<bool> PassCondition;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Mod"/> this test case tests.
|
||||
/// </summary>
|
||||
public Mod Mod;
|
||||
}
|
||||
}
|
||||
}
|
@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual
|
||||
base.Content.Add(content = new DrawSizePreservingFillContainer());
|
||||
}
|
||||
|
||||
public void RecycleLocalStorage()
|
||||
public virtual void RecycleLocalStorage()
|
||||
{
|
||||
if (localStorage?.IsValueCreated == true)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
@ -8,15 +9,19 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public abstract class PlayerTestScene : RateAdjustedBeatmapTestScene
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether custom test steps are provided. Custom tests should invoke <see cref="CreateTest"/> to create the test steps.
|
||||
/// </summary>
|
||||
protected virtual bool HasCustomSteps { get; } = false;
|
||||
|
||||
private readonly Ruleset ruleset;
|
||||
|
||||
protected Player Player;
|
||||
protected TestPlayer Player;
|
||||
|
||||
protected PlayerTestScene(Ruleset ruleset)
|
||||
{
|
||||
@ -37,7 +42,18 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep(ruleset.RulesetInfo.Name, loadPlayer);
|
||||
if (!HasCustomSteps)
|
||||
CreateTest(null);
|
||||
}
|
||||
|
||||
protected void CreateTest(Action action)
|
||||
{
|
||||
if (action != null && !HasCustomSteps)
|
||||
throw new InvalidOperationException($"Cannot add custom test steps without {nameof(HasCustomSteps)} being set.");
|
||||
|
||||
action?.Invoke();
|
||||
|
||||
AddStep(ruleset.RulesetInfo.Name, LoadPlayer);
|
||||
AddUntilStep("player loaded", () => Player.IsLoaded && Player.Alpha == 1);
|
||||
}
|
||||
|
||||
@ -45,12 +61,14 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
protected virtual bool Autoplay => false;
|
||||
|
||||
private void loadPlayer()
|
||||
protected void LoadPlayer()
|
||||
{
|
||||
var beatmap = CreateBeatmap(ruleset.RulesetInfo);
|
||||
|
||||
Beatmap.Value = CreateWorkingBeatmap(beatmap);
|
||||
|
||||
SelectedMods.Value = Array.Empty<Mod>();
|
||||
|
||||
if (!AllowFail)
|
||||
{
|
||||
var noFailMod = ruleset.GetAllMods().FirstOrDefault(m => m is ModNoFail);
|
||||
@ -69,6 +87,6 @@ namespace osu.Game.Tests.Visual
|
||||
LoadScreen(Player);
|
||||
}
|
||||
|
||||
protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false);
|
||||
protected virtual TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Tests.Visual
|
||||
public virtual void SetUpSteps() => addExitAllScreensStep();
|
||||
|
||||
[TearDownSteps]
|
||||
public void TearDownSteps() => addExitAllScreensStep();
|
||||
public virtual void TearDownSteps() => addExitAllScreensStep();
|
||||
|
||||
private void addExitAllScreensStep()
|
||||
{
|
||||
|
@ -1,23 +1,51 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
/// <summary>
|
||||
/// A player that exposes many components that would otherwise not be available, for testing purposes.
|
||||
/// </summary>
|
||||
public class TestPlayer : Player
|
||||
{
|
||||
protected override bool PauseOnFocusLost { get; }
|
||||
|
||||
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
|
||||
|
||||
/// <summary>
|
||||
/// Mods from *player* (not OsuScreen).
|
||||
/// </summary>
|
||||
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
||||
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
||||
|
||||
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
||||
|
||||
public TestPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
|
||||
: base(allowPause, showResults)
|
||||
{
|
||||
PauseOnFocusLost = pauseOnFocusLost;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScoreProcessor.NewJudgement += r => Results.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,12 +34,14 @@ namespace osu.Game.Updater
|
||||
|
||||
if (game.IsDeployedBuild && version != lastVersion)
|
||||
{
|
||||
config.Set(OsuSetting.Version, version);
|
||||
|
||||
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
|
||||
if (!string.IsNullOrEmpty(lastVersion))
|
||||
Notifications.Post(new UpdateCompleteNotification(version));
|
||||
}
|
||||
|
||||
// debug / local compilations will reset to a non-release string.
|
||||
// can be useful to check when an install has transitioned between release and otherwise (see OsuConfigManager's migrations).
|
||||
config.Set(OsuSetting.Version, version);
|
||||
}
|
||||
|
||||
private class UpdateCompleteNotification : SimpleNotification
|
||||
|
@ -11,12 +11,5 @@ namespace osu.iOS
|
||||
public class OsuGameIOS : OsuGame
|
||||
{
|
||||
public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString());
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new UpdateManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user