Merge remote-tracking branch 'origin/master' into rearrangeable-playlist

This commit is contained in:
smoogipoo
2020-02-04 16:55:55 +09:00
181 changed files with 3643 additions and 1690 deletions

View File

@ -68,10 +68,10 @@ namespace osu.Game.Tests.Visual.Background
[SetUp]
public virtual void SetUp() => Schedule(() =>
{
Child = new OsuScreenStack(songSelect = new DummySongSelect())
{
RelativeSizeAxes = Axes.Both
};
var stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
Child = stack;
stack.Push(songSelect = new DummySongSelect());
});
/// <summary>
@ -277,7 +277,7 @@ namespace osu.Game.Tests.Visual.Background
private void setupUserSettings()
{
AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null);
AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmap != null);
AddStep("Set default user settings", () =>
{
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();
@ -302,8 +302,8 @@ namespace osu.Game.Tests.Visual.Background
}
public readonly Bindable<bool> DimEnabled = new Bindable<bool>();
public readonly Bindable<double> DimLevel = new Bindable<double>();
public readonly Bindable<double> BlurLevel = new Bindable<double>();
public readonly Bindable<double> DimLevel = new BindableDouble();
public readonly Bindable<double> BlurLevel = new BindableDouble();
public new BeatmapCarousel Carousel => base.Carousel;

View File

@ -85,64 +85,64 @@ namespace osu.Game.Tests.Visual.Editor
{
}
protected override void CreateContent(Vector2 startPosition)
protected override void CreateContent()
{
AddInternal(new Circle
{
Origin = Anchor.Centre,
Size = new Vector2(5),
Position = startPosition
Position = StartPosition
});
int beatIndex = 0;
int indexFromPlacement = 0;
for (float s = startPosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
for (float s = StartPosition.X + DistanceSpacing; s <= DrawWidth && indexFromPlacement < MaxIntervals; s += DistanceSpacing, indexFromPlacement++)
{
AddInternal(new Circle
{
Origin = Anchor.Centre,
Size = new Vector2(5, 10),
Position = new Vector2(s, startPosition.Y),
Colour = GetColourForBeatIndex(beatIndex)
Position = new Vector2(s, StartPosition.Y),
Colour = GetColourForIndexFromPlacement(indexFromPlacement)
});
}
beatIndex = 0;
indexFromPlacement = 0;
for (float s = startPosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
for (float s = StartPosition.X - DistanceSpacing; s >= 0 && indexFromPlacement < MaxIntervals; s -= DistanceSpacing, indexFromPlacement++)
{
AddInternal(new Circle
{
Origin = Anchor.Centre,
Size = new Vector2(5, 10),
Position = new Vector2(s, startPosition.Y),
Colour = GetColourForBeatIndex(beatIndex)
Position = new Vector2(s, StartPosition.Y),
Colour = GetColourForIndexFromPlacement(indexFromPlacement)
});
}
beatIndex = 0;
indexFromPlacement = 0;
for (float s = startPosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
for (float s = StartPosition.Y + DistanceSpacing; s <= DrawHeight && indexFromPlacement < MaxIntervals; s += DistanceSpacing, indexFromPlacement++)
{
AddInternal(new Circle
{
Origin = Anchor.Centre,
Size = new Vector2(10, 5),
Position = new Vector2(startPosition.X, s),
Colour = GetColourForBeatIndex(beatIndex)
Position = new Vector2(StartPosition.X, s),
Colour = GetColourForIndexFromPlacement(indexFromPlacement)
});
}
beatIndex = 0;
indexFromPlacement = 0;
for (float s = startPosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
for (float s = StartPosition.Y - DistanceSpacing; s >= 0 && indexFromPlacement < MaxIntervals; s -= DistanceSpacing, indexFromPlacement++)
{
AddInternal(new Circle
{
Origin = Anchor.Centre,
Size = new Vector2(10, 5),
Position = new Vector2(startPosition.X, s),
Colour = GetColourForBeatIndex(beatIndex)
Position = new Vector2(StartPosition.X, s),
Colour = GetColourForIndexFromPlacement(indexFromPlacement)
});
}
}

View File

@ -1,146 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
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.Graphics.Shapes;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestSceneTimelineBlueprintContainer : EditorClockTestScene
public class TestSceneTimelineBlueprintContainer : TimelineTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(TimelineArea),
typeof(Timeline),
typeof(TimelineButton),
typeof(CentreMarker)
};
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
Beatmap.Value = new WaveformTestBeatmap(audio);
var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap, BeatDivisor);
Dependencies.Cache(editorBeatmap);
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new Drawable[]
{
new StartStopButton(),
new AudioVisualiser(),
}
},
new TimelineArea
{
Child = new TimelineBlueprintContainer(),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Size = new Vector2(0.8f, 100)
}
};
}
private class AudioVisualiser : CompositeDrawable
{
private readonly Drawable marker;
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private IAdjustableClock adjustableClock { get; set; }
public AudioVisualiser()
{
Size = new Vector2(250, 25);
InternalChildren = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.25f,
},
marker = new Box
{
RelativePositionAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Width = 2,
}
};
}
protected override void Update()
{
base.Update();
if (beatmap.Value.Track.IsLoaded)
marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length);
}
}
private class StartStopButton : OsuButton
{
private IAdjustableClock adjustableClock;
private bool started;
public StartStopButton()
{
BackgroundColour = Color4.SlateGray;
Size = new Vector2(100, 50);
Text = "Start";
Action = onClick;
}
[BackgroundDependencyLoader]
private void load(IAdjustableClock adjustableClock)
{
this.adjustableClock = adjustableClock;
}
private void onClick()
{
if (started)
{
adjustableClock.Stop();
Text = "Start";
}
else
{
adjustableClock.Start();
Text = "Stop";
}
started = !started;
}
}
public override Drawable CreateTestComponent() => new TimelineBlueprintContainer();
}
}

View File

@ -0,0 +1,32 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Screens.Edit.Compose.Components;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osuTK;
namespace osu.Game.Tests.Visual.Editor
{
[TestFixture]
public class TestSceneTimelineTickDisplay : TimelineTestScene
{
public override Drawable CreateTestComponent() => new TimelineTickDisplay();
[BackgroundDependencyLoader]
private void load()
{
BeatDivisor.Value = 4;
Add(new BeatDivisorControl(BeatDivisor)
{
Anchor = Anchor.TopRight,
Origin = Anchor.TopRight,
Margin = new MarginPadding(30),
Size = new Vector2(90)
});
}
}
}

View File

@ -0,0 +1,148 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Editor
{
public abstract class TimelineTestScene : EditorClockTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(TimelineArea),
typeof(Timeline),
typeof(TimelineButton),
typeof(CentreMarker)
};
protected TimelineArea TimelineArea { get; private set; }
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
Beatmap.Value = new WaveformTestBeatmap(audio);
var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap, BeatDivisor);
Dependencies.Cache(editorBeatmap);
Dependencies.CacheAs<IBeatSnapProvider>(editorBeatmap);
AddRange(new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new Drawable[]
{
new StartStopButton(),
new AudioVisualiser(),
}
},
TimelineArea = new TimelineArea
{
Child = CreateTestComponent(),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Size = new Vector2(0.8f, 100),
}
});
}
public abstract Drawable CreateTestComponent();
private class AudioVisualiser : CompositeDrawable
{
private readonly Drawable marker;
[Resolved]
private IBindable<WorkingBeatmap> beatmap { get; set; }
[Resolved]
private IAdjustableClock adjustableClock { get; set; }
public AudioVisualiser()
{
Size = new Vector2(250, 25);
InternalChildren = new[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.25f,
},
marker = new Box
{
RelativePositionAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Width = 2,
}
};
}
protected override void Update()
{
base.Update();
if (beatmap.Value.Track.IsLoaded)
marker.X = (float)(adjustableClock.CurrentTime / beatmap.Value.Track.Length);
}
}
private class StartStopButton : OsuButton
{
private IAdjustableClock adjustableClock;
private bool started;
public StartStopButton()
{
BackgroundColour = Color4.SlateGray;
Size = new Vector2(100, 50);
Text = "Start";
Action = onClick;
}
[BackgroundDependencyLoader]
private void load(IAdjustableClock adjustableClock)
{
this.adjustableClock = adjustableClock;
}
private void onClick()
{
if (started)
{
adjustableClock.Stop();
Text = "Start";
}
else
{
adjustableClock.Start();
Text = "Stop";
}
started = !started;
}
}
}
}

View File

@ -0,0 +1,89 @@
// 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.Allocation;
using osu.Framework.Screens;
using osu.Game.Configuration;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
/// <summary>
/// A base class which runs <see cref="Player"/> test for all available rulesets.
/// Steps to be run for each ruleset should be added via <see cref="AddCheckSteps"/>.
/// </summary>
public abstract class TestSceneAllRulesetPlayers : RateAdjustedBeatmapTestScene
{
protected Player Player;
[BackgroundDependencyLoader]
private void load(RulesetStore rulesets)
{
OsuConfigManager manager;
Dependencies.Cache(manager = new OsuConfigManager(LocalStorage));
manager.GetBindable<double>(OsuSetting.DimLevel).Value = 1.0;
}
[Test]
public void TestOsu() => runForRuleset(new OsuRuleset().RulesetInfo);
[Test]
public void TestTaiko() => runForRuleset(new TaikoRuleset().RulesetInfo);
[Test]
public void TestCatch() => runForRuleset(new CatchRuleset().RulesetInfo);
[Test]
public void TestMania() => runForRuleset(new ManiaRuleset().RulesetInfo);
private void runForRuleset(RulesetInfo ruleset)
{
Player p = null;
AddStep($"load {ruleset.Name} player", () => p = loadPlayerFor(ruleset));
AddUntilStep("player loaded", () =>
{
if (p?.IsLoaded == true)
{
p = null;
return true;
}
return false;
});
AddCheckSteps();
}
protected abstract void AddCheckSteps();
private Player loadPlayerFor(RulesetInfo rulesetInfo)
{
Ruleset.Value = rulesetInfo;
var ruleset = rulesetInfo.CreateInstance();
var working = CreateWorkingBeatmap(rulesetInfo);
Beatmap.Value = working;
SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) };
Player?.Exit();
Player = null;
Player = CreatePlayer(ruleset);
LoadScreen(Player);
return Player;
}
protected virtual Player CreatePlayer(Ruleset ruleset) => new TestPlayer(false, false);
}
}

View File

@ -12,7 +12,7 @@ using osu.Game.Storyboards;
namespace osu.Game.Tests.Visual.Gameplay
{
[Description("Player instantiated with an autoplay mod.")]
public class TestSceneAutoplay : AllPlayersTestScene
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
{
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;

View File

@ -10,7 +10,7 @@ using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneFailAnimation : AllPlayersTestScene
public class TestSceneFailAnimation : TestSceneAllRulesetPlayers
{
protected override Player CreatePlayer(Ruleset ruleset)
{
@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(AllPlayersTestScene),
typeof(TestSceneAllRulesetPlayers),
typeof(TestPlayer),
typeof(Player),
};

View File

@ -10,7 +10,7 @@ using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneFailJudgement : AllPlayersTestScene
public class TestSceneFailJudgement : TestSceneAllRulesetPlayers
{
protected override Player CreatePlayer(Ruleset ruleset)
{

View File

@ -2,12 +2,16 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Configuration;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Play;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
{
@ -15,7 +19,9 @@ namespace osu.Game.Tests.Visual.Gameplay
{
private HUDOverlay hudOverlay;
private Drawable hideTarget => hudOverlay.KeyCounter; // best way of checking hideTargets without exposing.
// best way to check without exposing.
private Drawable hideTarget => hudOverlay.KeyCounter;
private FillFlowContainer<KeyCounter> keyCounterFlow => hudOverlay.KeyCounter.ChildrenOfType<FillFlowContainer<KeyCounter>>().First();
[Resolved]
private OsuConfigManager config { get; set; }
@ -28,6 +34,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("showhud is set", () => hudOverlay.ShowHud.Value);
AddAssert("hidetarget is visible", () => hideTarget.IsPresent);
AddAssert("key counter flow is visible", () => keyCounterFlow.IsPresent);
AddAssert("pause button is visible", () => hudOverlay.HoldToQuit.IsPresent);
}
@ -50,6 +57,9 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent);
AddAssert("pause button is still visible", () => hudOverlay.HoldToQuit.IsPresent);
// Key counter flow container should not be affected by this, only the key counter display will be hidden as checked above.
AddAssert("key counter flow not affected", () => keyCounterFlow.IsPresent);
}
[Test]
@ -68,12 +78,40 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("config unchanged", () => originalConfigValue == config.Get<bool>(OsuSetting.ShowInterface));
}
[Test]
public void TestChangeHUDVisibilityOnHiddenKeyCounter()
{
bool keyCounterVisibleValue = false;
createNew();
AddStep("save keycounter visible value", () => keyCounterVisibleValue = config.Get<bool>(OsuSetting.KeyOverlay));
AddStep("set keycounter visible false", () =>
{
config.Set<bool>(OsuSetting.KeyOverlay, false);
hudOverlay.KeyCounter.AlwaysVisible.Value = false;
});
AddStep("set showhud false", () => hudOverlay.ShowHud.Value = false);
AddUntilStep("hidetarget is hidden", () => !hideTarget.IsPresent);
AddAssert("key counters hidden", () => !keyCounterFlow.IsPresent);
AddStep("set showhud true", () => hudOverlay.ShowHud.Value = true);
AddUntilStep("hidetarget is visible", () => hideTarget.IsPresent);
AddAssert("key counters still hidden", () => !keyCounterFlow.IsPresent);
AddStep("return value", () => config.Set<bool>(OsuSetting.KeyOverlay, keyCounterVisibleValue));
}
private void createNew(Action<HUDOverlay> action = null)
{
AddStep("create overlay", () =>
{
Child = hudOverlay = new HUDOverlay(null, null, null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(new KeyCounterKeyboard(Key.Space));
action?.Invoke(hudOverlay);
});
}

View File

@ -36,6 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override void SetUpSteps()
{
base.SetUpSteps();
AddStep("resume player", () => Player.GameplayClockContainer.Start());
confirmClockRunning(true);
}

View File

@ -207,9 +207,11 @@ namespace osu.Game.Tests.Visual.Gameplay
{
RelativeSizeAxes = Axes.Both;
OsuScreenStack stack;
InternalChildren = new Drawable[]
{
new OsuScreenStack(screen)
stack = new OsuScreenStack
{
RelativeSizeAxes = Axes.Both,
},
@ -224,6 +226,8 @@ namespace osu.Game.Tests.Visual.Gameplay
Origin = Anchor.TopLeft,
}
};
stack.Push(screen);
}
}

View File

@ -10,7 +10,7 @@ using osu.Game.Storyboards;
namespace osu.Game.Tests.Visual.Gameplay
{
public class TestScenePlayerReferenceLeaking : AllPlayersTestScene
public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers
{
private readonly WeakList<WorkingBeatmap> workingWeakReferences = new WeakList<WorkingBeatmap>();

View File

@ -13,7 +13,7 @@ using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
[Description("Player instantiated with a replay.")]
public class TestSceneReplay : AllPlayersTestScene
public class TestSceneReplay : TestSceneAllRulesetPlayers
{
protected override Player CreatePlayer(Ruleset ruleset)
{

View File

@ -75,10 +75,16 @@ namespace osu.Game.Tests.Visual.Gameplay
public void ResultsWithoutPlayer()
{
TestSoloResults screen = null;
OsuScreenStack stack;
AddStep("load results", () => Child = new OsuScreenStack(screen = createResultsScreen())
AddStep("load results", () =>
{
RelativeSizeAxes = Axes.Both
Child = stack = new OsuScreenStack
{
RelativeSizeAxes = Axes.Both
};
stack.Push(screen = createResultsScreen());
});
AddUntilStep("wait for loaded", () => screen.IsLoaded);
AddAssert("retry overlay not present", () => screen.RetryOverlay == null);
@ -102,11 +108,14 @@ namespace osu.Game.Tests.Visual.Gameplay
public TestResultsContainer(IScreen screen)
{
RelativeSizeAxes = Axes.Both;
OsuScreenStack stack;
InternalChild = new OsuScreenStack(screen)
InternalChild = stack = new OsuScreenStack
{
RelativeSizeAxes = Axes.Both,
};
stack.Push(screen);
}
}

View File

@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Menus
protected IntroTestScene()
{
Drawable introStack = null;
OsuScreenStack introStack = null;
Children = new Drawable[]
{
@ -57,10 +57,12 @@ namespace osu.Game.Tests.Visual.Menus
introStack?.Expire();
Add(introStack = new OsuScreenStack(CreateScreen())
Add(introStack = new OsuScreenStack
{
RelativeSizeAxes = Axes.Both,
});
introStack.Push(CreateScreen());
});
}

View File

@ -16,7 +16,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
int index = 0;
OsuScreenStack screenStack = new OsuScreenStack(new TestMultiplayerSubScreen(index)) { RelativeSizeAxes = Axes.Both };
OsuScreenStack screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
screenStack.Push(new TestMultiplayerSubScreen(index));
Children = new Drawable[]
{

View File

@ -0,0 +1,133 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Screens;
using osu.Game.Screens.Menu;
using osuTK.Graphics;
using IntroSequence = osu.Game.Configuration.IntroSequence;
namespace osu.Game.Tests.Visual.Navigation
{
/// <summary>
/// A scene which tests full game flow.
/// </summary>
public abstract class OsuGameTestScene : ManualInputManagerTestScene
{
private GameHost host;
protected TestOsuGame Game;
[BackgroundDependencyLoader]
private void load(GameHost host)
{
this.host = host;
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
};
}
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create new game instance", () =>
{
if (Game != null)
{
Remove(Game);
Game.Dispose();
}
RecycleLocalStorage();
// see MouseSettings
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);
});
AddUntilStep("Wait for load", () => Game.IsLoaded);
AddUntilStep("Wait for intro", () => Game.ScreenStack.CurrentScreen is IntroScreen);
ConfirmAtMainMenu();
}
protected void PushAndConfirm(Func<Screen> newScreen)
{
Screen screen = null;
AddStep("Push new screen", () => Game.ScreenStack.Push(screen = newScreen()));
AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen == screen && screen.IsLoaded);
}
protected void ConfirmAtMainMenu() => AddUntilStep("Wait for main menu", () => Game.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded);
public class TestOsuGame : OsuGame
{
public new ScreenStack ScreenStack => base.ScreenStack;
public new BackButton BackButton => base.BackButton;
public new BeatmapManager BeatmapManager => base.BeatmapManager;
public new SettingsPanel Settings => base.Settings;
public new OsuConfigManager LocalConfig => base.LocalConfig;
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
protected override Loader CreateLoader() => new TestLoader();
public new void PerformFromScreen(Action<IScreen> action, IEnumerable<Type> validScreens = null) => base.PerformFromScreen(action, validScreens);
public TestOsuGame(Storage storage, IAPIProvider api)
{
Storage = storage;
API = api;
}
protected override void LoadComplete()
{
base.LoadComplete();
API.Login("Rhythm Champion", "osu!");
}
}
public class TestLoader : Loader
{
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler();
private class TestShaderPrecompiler : ShaderPrecompiler
{
protected override bool AllLoaded => true;
}
}
}
}

View File

@ -0,0 +1,72 @@
// 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.Game.Screens.Menu;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.Navigation
{
public class TestScenePerformFromScreen : OsuGameTestScene
{
[Test]
public void TestPerformAtMenu()
{
AddAssert("could perform immediately", () =>
{
bool actionPerformed = false;
Game.PerformFromScreen(_ => actionPerformed = true);
return actionPerformed;
});
}
[Test]
public void TestPerformAtSongSelect()
{
PushAndConfirm(() => new PlaySongSelect());
AddAssert("could perform immediately", () =>
{
bool actionPerformed = false;
Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(PlaySongSelect) });
return actionPerformed;
});
}
[Test]
public void TestPerformAtMenuFromSongSelect()
{
PushAndConfirm(() => new PlaySongSelect());
bool actionPerformed = false;
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true));
AddUntilStep("returned to menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
AddAssert("did perform", () => actionPerformed);
}
[Test]
public void TestPerformAtSongSelectFromPlayerLoader()
{
PushAndConfirm(() => new PlaySongSelect());
PushAndConfirm(() => new PlayerLoader(() => new Player()));
bool actionPerformed = false;
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(PlaySongSelect) }));
AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
AddAssert("did perform", () => actionPerformed);
}
[Test]
public void TestPerformAtMenuFromPlayerLoader()
{
PushAndConfirm(() => new PlaySongSelect());
PushAndConfirm(() => new PlayerLoader(() => new Player()));
bool actionPerformed = false;
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true));
AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is MainMenu);
AddAssert("did perform", () => actionPerformed);
}
}
}

View File

@ -0,0 +1,110 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Menu;
namespace osu.Game.Tests.Visual.Navigation
{
public class TestScenePresentBeatmap : OsuGameTestScene
{
[Test]
public void TestFromMainMenu()
{
var firstImport = importBeatmap(1);
presentAndConfirm(firstImport);
AddStep("return to menu", () => Game.ScreenStack.CurrentScreen.Exit());
AddUntilStep("wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
var secondimport = importBeatmap(2);
presentAndConfirm(secondimport);
}
[Test]
public void TestFromMainMenuDifferentRuleset()
{
var firstImport = importBeatmap(1);
presentAndConfirm(firstImport);
AddStep("return to menu", () => Game.ScreenStack.CurrentScreen.Exit());
AddUntilStep("wait for menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
var secondimport = importBeatmap(2, new ManiaRuleset().RulesetInfo);
presentAndConfirm(secondimport);
}
[Test]
public void TestFromSongSelect()
{
var firstImport = importBeatmap(1);
presentAndConfirm(firstImport);
var secondimport = importBeatmap(2);
presentAndConfirm(secondimport);
}
[Test]
public void TestFromSongSelectDifferentRuleset()
{
var firstImport = importBeatmap(1);
presentAndConfirm(firstImport);
var secondimport = importBeatmap(2, new ManiaRuleset().RulesetInfo);
presentAndConfirm(secondimport);
}
private Func<BeatmapSetInfo> importBeatmap(int i, RulesetInfo ruleset = null)
{
BeatmapSetInfo imported = null;
AddStep($"import beatmap {i}", () =>
{
var difficulty = new BeatmapDifficulty();
var metadata = new BeatmapMetadata
{
Artist = "SomeArtist",
AuthorString = "SomeAuthor",
Title = $"import {i}"
};
imported = Game.BeatmapManager.Import(new BeatmapSetInfo
{
Hash = Guid.NewGuid().ToString(),
OnlineBeatmapSetID = i,
Metadata = metadata,
Beatmaps = new List<BeatmapInfo>
{
new BeatmapInfo
{
OnlineBeatmapID = i * 1024,
Metadata = metadata,
BaseDifficulty = difficulty,
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
},
}
}).Result;
});
AddAssert($"import {i} succeeded", () => imported != null);
return () => imported;
}
private void presentAndConfirm(Func<BeatmapSetInfo> getImport)
{
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.ID == getImport().ID);
AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID);
}
}
}

View File

@ -1,90 +1,36 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Screens;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select;
using osu.Game.Tests.Beatmaps.IO;
using osuTK;
using osuTK.Graphics;
using osuTK.Input;
using IntroSequence = osu.Game.Configuration.IntroSequence;
namespace osu.Game.Tests.Visual.Menus
namespace osu.Game.Tests.Visual.Navigation
{
public class TestSceneScreenNavigation : ManualInputManagerTestScene
public class TestSceneScreenNavigation : OsuGameTestScene
{
private const float click_padding = 25;
private GameHost host;
private TestOsuGame game;
private Vector2 backButtonPosition => Game.ToScreenSpace(new Vector2(click_padding, Game.LayoutRectangle.Bottom - click_padding));
private Vector2 backButtonPosition => game.ToScreenSpace(new Vector2(click_padding, game.LayoutRectangle.Bottom - click_padding));
private Vector2 optionsButtonPosition => game.ToScreenSpace(new Vector2(click_padding, click_padding));
[BackgroundDependencyLoader]
private void load(GameHost host)
{
this.host = host;
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
};
}
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Create new game instance", () =>
{
if (game != null)
{
Remove(game);
game.Dispose();
}
game = new TestOsuGame(LocalStorage, API);
game.SetHost(host);
// todo: this can be removed once we can run audio trakcs without a device present
// see https://github.com/ppy/osu/issues/1302
game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
Add(game);
});
AddUntilStep("Wait for load", () => game.IsLoaded);
AddUntilStep("Wait for intro", () => game.ScreenStack.CurrentScreen is IntroScreen);
confirmAtMainMenu();
}
private Vector2 optionsButtonPosition => Game.ToScreenSpace(new Vector2(click_padding, click_padding));
[Test]
public void TestExitSongSelectWithEscape()
{
TestSongSelect songSelect = null;
pushAndConfirm(() => songSelect = new TestSongSelect());
PushAndConfirm(() => songSelect = new TestSongSelect());
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
pushEscape();
@ -98,21 +44,21 @@ namespace osu.Game.Tests.Visual.Menus
{
Player player = null;
WorkingBeatmap beatmap() => game.Beatmap.Value;
WorkingBeatmap beatmap() => Game.Beatmap.Value;
Track track() => beatmap().Track;
pushAndConfirm(() => new TestSongSelect());
PushAndConfirm(() => new TestSongSelect());
AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Wait());
AddStep("import beatmap", () => ImportBeatmapTest.LoadOszIntoOsu(Game, virtualTrack: true).Wait());
AddUntilStep("wait for selected", () => !game.Beatmap.IsDefault);
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
if (withUserPause)
AddStep("pause", () => game.Dependencies.Get<MusicController>().Stop());
AddStep("pause", () => Game.Dependencies.Get<MusicController>().Stop());
AddStep("press enter", () => pressAndRelease(Key.Enter));
AddUntilStep("wait for player", () => (player = game.ScreenStack.CurrentScreen as Player) != null);
AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null);
AddUntilStep("wait for fail", () => player.HasFailed);
AddUntilStep("wait for track stop", () => !track().IsRunning);
@ -129,13 +75,13 @@ namespace osu.Game.Tests.Visual.Menus
{
TestSongSelect songSelect = null;
pushAndConfirm(() => songSelect = new TestSongSelect());
PushAndConfirm(() => songSelect = new TestSongSelect());
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition));
// BackButton handles hover using its child button, so this checks whether or not any of BackButton's children are hovered.
AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == game.BackButton));
AddUntilStep("Back button is hovered", () => InputManager.HoveredDrawables.Any(d => d.Parent == Game.BackButton));
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
@ -145,34 +91,27 @@ namespace osu.Game.Tests.Visual.Menus
[Test]
public void TestExitMultiWithEscape()
{
pushAndConfirm(() => new Screens.Multi.Multiplayer());
PushAndConfirm(() => new Screens.Multi.Multiplayer());
exitViaEscapeAndConfirm();
}
[Test]
public void TestExitMultiWithBackButton()
{
pushAndConfirm(() => new Screens.Multi.Multiplayer());
PushAndConfirm(() => new Screens.Multi.Multiplayer());
exitViaBackButtonAndConfirm();
}
[Test]
public void TestOpenOptionsAndExitWithEscape()
{
AddUntilStep("Wait for options to load", () => game.Settings.IsLoaded);
AddUntilStep("Wait for options to load", () => Game.Settings.IsLoaded);
AddStep("Enter menu", () => pressAndRelease(Key.Enter));
AddStep("Move mouse to options overlay", () => InputManager.MoveMouseTo(optionsButtonPosition));
AddStep("Click options overlay", () => InputManager.Click(MouseButton.Left));
AddAssert("Options overlay was opened", () => game.Settings.State.Value == Visibility.Visible);
AddAssert("Options overlay was opened", () => Game.Settings.State.Value == Visibility.Visible);
AddStep("Hide options overlay using escape", () => pressAndRelease(Key.Escape));
AddAssert("Options overlay was closed", () => game.Settings.State.Value == Visibility.Hidden);
}
private void pushAndConfirm(Func<Screen> newScreen)
{
Screen screen = null;
AddStep("Push new screen", () => game.ScreenStack.Push(screen = newScreen()));
AddUntilStep("Wait for new screen", () => game.ScreenStack.CurrentScreen == screen && screen.IsLoaded);
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
}
private void pushEscape() =>
@ -181,64 +120,25 @@ namespace osu.Game.Tests.Visual.Menus
private void exitViaEscapeAndConfirm()
{
pushEscape();
confirmAtMainMenu();
ConfirmAtMainMenu();
}
private void exitViaBackButtonAndConfirm()
{
AddStep("Move mouse to backButton", () => InputManager.MoveMouseTo(backButtonPosition));
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
confirmAtMainMenu();
ConfirmAtMainMenu();
}
private void confirmAtMainMenu() => AddUntilStep("Wait for main menu", () => game.ScreenStack.CurrentScreen is MainMenu menu && menu.IsLoaded);
private void pressAndRelease(Key key)
{
InputManager.PressKey(key);
InputManager.ReleaseKey(key);
}
private class TestOsuGame : OsuGame
{
public new ScreenStack ScreenStack => base.ScreenStack;
public new BackButton BackButton => base.BackButton;
public new SettingsPanel Settings => base.Settings;
public new OsuConfigManager LocalConfig => base.LocalConfig;
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
protected override Loader CreateLoader() => new TestLoader();
public TestOsuGame(Storage storage, IAPIProvider api)
{
Storage = storage;
API = api;
}
protected override void LoadComplete()
{
base.LoadComplete();
API.Login("Rhythm Champion", "osu!");
}
}
private class TestSongSelect : PlaySongSelect
{
public ModSelectOverlay ModSelectOverlay => ModSelect;
}
private class TestLoader : Loader
{
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler();
private class TestShaderPrecompiler : ShaderPrecompiler
{
protected override bool AllLoaded => true;
}
}
}
}

View File

@ -5,6 +5,7 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics.UserInterface;
using osu.Game.Beatmaps;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Rulesets;
using System;
@ -21,6 +22,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(BeatmapRulesetTabItem),
};
[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
private readonly TestRulesetSelector selector;
public TestSceneBeatmapRulesetSelector()

View File

@ -3,12 +3,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Testing;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Chat;
using osu.Game.Overlays;
using osu.Game.Overlays.Chat;
@ -35,8 +38,21 @@ namespace osu.Game.Tests.Visual.Online
private TestChatOverlay chatOverlay;
private ChannelManager channelManager;
private readonly Channel channel1 = new Channel(new User()) { Name = "test really long username" };
private readonly Channel channel2 = new Channel(new User()) { Name = "test2" };
private readonly List<Channel> channels;
private Channel channel1 => channels[0];
private Channel channel2 => channels[1];
public TestSceneChatOverlay()
{
channels = Enumerable.Range(1, 10)
.Select(index => new Channel(new User())
{
Name = $"Channel no. {index}",
Topic = index == 3 ? null : $"We talk about the number {index} here"
})
.ToList();
}
[SetUp]
public void Setup()
@ -45,7 +61,7 @@ namespace osu.Game.Tests.Visual.Online
{
ChannelManagerContainer container;
Child = container = new ChannelManagerContainer(new List<Channel> { channel1, channel2 })
Child = container = new ChannelManagerContainer(channels)
{
RelativeSizeAxes = Axes.Both,
};
@ -96,6 +112,47 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Selector is visible", () => chatOverlay.SelectionOverlayState == Visibility.Visible);
}
[Test]
public void TestSearchInSelector()
{
AddStep("search for 'no. 2'", () => chatOverlay.ChildrenOfType<SearchTextBox>().First().Text = "no. 2");
AddUntilStep("only channel 2 visible", () =>
{
var listItems = chatOverlay.ChildrenOfType<ChannelListItem>().Where(c => c.IsPresent);
return listItems.Count() == 1 && listItems.Single().Channel == channel2;
});
}
[Test]
public void TestChannelShortcutKeys()
{
AddStep("join 10 channels", () => channels.ForEach(channel => channelManager.JoinChannel(channel)));
AddStep("close channel selector", () =>
{
InputManager.PressKey(Key.Escape);
InputManager.ReleaseKey(Key.Escape);
});
AddUntilStep("wait for close", () => chatOverlay.SelectionOverlayState == Visibility.Hidden);
for (int zeroBasedIndex = 0; zeroBasedIndex < 10; ++zeroBasedIndex)
{
var oneBasedIndex = zeroBasedIndex + 1;
var targetNumberKey = oneBasedIndex % 10;
var targetChannel = channels[zeroBasedIndex];
AddStep($"press Alt+{targetNumberKey}", () => pressChannelHotkey(targetNumberKey));
AddAssert($"channel #{oneBasedIndex} is selected", () => channelManager.CurrentChannel.Value == targetChannel);
}
}
private void pressChannelHotkey(int number)
{
var channelKey = Key.Number0 + number;
InputManager.PressKey(Key.AltLeft);
InputManager.PressKey(channelKey);
InputManager.ReleaseKey(Key.AltLeft);
InputManager.ReleaseKey(channelKey);
}
private void clickDrawable(Drawable d)
{
InputManager.MoveMouseTo(d);

View File

@ -24,8 +24,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(HeaderButton),
typeof(SortTabControl),
typeof(ShowChildrenButton),
typeof(DeletedChildrenPlaceholder),
typeof(VotePill)
typeof(DeletedCommentsCounter),
typeof(VotePill),
typeof(CommentsPage),
};
protected override bool UseOnlineAPI => true;

View File

@ -0,0 +1,162 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Overlays.Comments;
using osu.Game.Overlays;
using osu.Framework.Allocation;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Users;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osuTK;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneCommentsPage : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DrawableComment),
typeof(CommentsPage),
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
private readonly BindableBool showDeleted = new BindableBool();
private readonly Container content;
public TestSceneCommentsPage()
{
Add(new FillFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
new Container
{
AutoSizeAxes = Axes.Y,
Width = 200,
Child = new OsuCheckbox
{
Current = showDeleted,
LabelText = @"Show Deleted"
}
},
content = new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
}
}
});
AddStep("load comments", () => createPage(comment_bundle));
AddStep("load empty comments", () => createPage(empty_comment_bundle));
}
private void createPage(CommentBundle commentBundle)
{
content.Clear();
content.Add(new CommentsPage(commentBundle)
{
ShowDeleted = { BindTarget = showDeleted }
});
}
private static readonly CommentBundle empty_comment_bundle = new CommentBundle
{
Comments = new List<Comment>(),
Total = 0,
};
private static readonly CommentBundle comment_bundle = new CommentBundle
{
Comments = new List<Comment>
{
new Comment
{
Id = 1,
Message = "Simple test comment",
LegacyName = "TestUser1",
CreatedAt = DateTimeOffset.Now,
VotesCount = 5
},
new Comment
{
Id = 2,
Message = "This comment has been deleted :( but visible for admins",
LegacyName = "TestUser2",
CreatedAt = DateTimeOffset.Now,
DeletedAt = DateTimeOffset.Now,
VotesCount = 5
},
new Comment
{
Id = 3,
Message = "This comment is a top level",
LegacyName = "TestUser3",
CreatedAt = DateTimeOffset.Now,
RepliesCount = 2,
},
new Comment
{
Id = 4,
ParentId = 3,
Message = "And this is a reply",
RepliesCount = 1,
LegacyName = "TestUser1",
CreatedAt = DateTimeOffset.Now,
},
new Comment
{
Id = 15,
ParentId = 4,
Message = "Reply to reply",
LegacyName = "TestUser1",
CreatedAt = DateTimeOffset.Now,
},
new Comment
{
Id = 6,
ParentId = 3,
LegacyName = "TestUser11515",
CreatedAt = DateTimeOffset.Now,
DeletedAt = DateTimeOffset.Now,
},
new Comment
{
Id = 5,
Message = "This comment is voted and edited",
LegacyName = "BigBrainUser",
CreatedAt = DateTimeOffset.Now,
EditedAt = DateTimeOffset.Now,
VotesCount = 1000,
EditedById = 1,
}
},
IncludedComments = new List<Comment>(),
UserVotes = new List<long>
{
5
},
Users = new List<User>
{
new User
{
Id = 1,
Username = "Good_Admin"
}
},
TopLevelCount = 4,
Total = 7
};
}
}

View File

@ -4,10 +4,12 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile.Sections;
using osu.Game.Overlays.Profile.Sections.Historical;
using osu.Game.Users;
@ -24,9 +26,11 @@ namespace osu.Game.Tests.Visual.Online
typeof(HistoricalSection),
typeof(PaginatedMostPlayedBeatmapContainer),
typeof(DrawableMostPlayedBeatmap),
typeof(DrawableProfileRow)
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
public TestSceneHistoricalSection()
{
HistoricalSection section;

View File

@ -11,6 +11,8 @@ using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using osu.Game.Users;
using osu.Framework.Bindables;
using osu.Game.Overlays;
using osu.Framework.Allocation;
namespace osu.Game.Tests.Visual.Online
{
@ -22,10 +24,13 @@ namespace osu.Game.Tests.Visual.Online
typeof(ProfileRulesetTabItem),
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
public TestSceneProfileRulesetSelector()
{
ProfileRulesetSelector selector;
Bindable<User> user = new Bindable<User>();
var user = new Bindable<User>();
Child = selector = new ProfileRulesetSelector
{

View File

@ -4,11 +4,13 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Users;
using osuTK;
@ -24,6 +26,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(LineGraph)
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
public TestSceneRankGraph()
{
RankGraph graph;

View File

@ -0,0 +1,87 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Rankings;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneRankingsSpotlightSelector : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(SpotlightSelector),
};
protected override bool UseOnlineAPI => true;
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
[Resolved]
private IAPIProvider api { get; set; }
private readonly SpotlightSelector selector;
public TestSceneRankingsSpotlightSelector()
{
Add(selector = new SpotlightSelector());
}
[Test]
public void TestLocalSpotlights()
{
var spotlights = new[]
{
new APISpotlight
{
Name = "Spotlight 1",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
new APISpotlight
{
Name = "Spotlight 2",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
new APISpotlight
{
Name = "Spotlight 3",
StartDate = DateTimeOffset.Now,
EndDate = DateTimeOffset.Now,
},
};
AddStep("load spotlights", () => selector.Spotlights = spotlights);
AddStep("change to spotlight 3", () => selector.Current.Value = spotlights[2]);
}
[Test]
public void TestOnlineSpotlights()
{
List<APISpotlight> spotlights = null;
AddStep("retrieve spotlights", () =>
{
var req = new GetSpotlightsRequest();
req.Success += res => spotlights = res.Spotlights;
api.Perform(req);
});
AddStep("set spotlights", () =>
{
if (spotlights != null)
selector.Spotlights = spotlights;
});
}
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -12,6 +13,7 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile.Sections;
using osu.Game.Overlays.Profile.Sections.Recent;
@ -28,6 +30,9 @@ namespace osu.Game.Tests.Visual.Online
typeof(MedalIcon)
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
public TestSceneUserProfileRecentSection()
{
Children = new Drawable[]
@ -131,6 +136,22 @@ namespace osu.Game.Tests.Visual.Online
Beatmap = dummyBeatmap,
},
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.Rank,
Rank = 1,
Mode = "vitaru",
Beatmap = dummyBeatmap,
},
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.Rank,
Rank = 1,
Mode = "fruits",
Beatmap = dummyBeatmap,
},
new APIRecentActivity
{
User = dummyUser,
Type = RecentActivityType.RankLost,

View File

@ -0,0 +1,101 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Game.Overlays.Profile.Sections;
using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Framework.Graphics;
using osu.Game.Scoring;
using osu.Framework.Graphics.Containers;
using osuTK;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Overlays;
using osu.Framework.Allocation;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneUserProfileScores : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DrawableProfileScore),
typeof(DrawableProfileWeightedScore),
typeof(ProfileItemContainer),
};
public TestSceneUserProfileScores()
{
var score = new ScoreInfo
{
PP = 134.32,
Rank = ScoreRank.A,
Beatmap = new BeatmapInfo
{
Metadata = new BeatmapMetadata
{
Title = "Triumph & Regret",
Artist = "typeMARS"
},
Version = "[4K] Regret"
},
Date = DateTimeOffset.Now,
Mods = new Mod[]
{
new OsuModHardRock(),
new OsuModDoubleTime(),
},
Accuracy = 0.998546
};
var noPPScore = new ScoreInfo
{
Rank = ScoreRank.B,
Beatmap = new BeatmapInfo
{
Metadata = new BeatmapMetadata
{
Title = "C18H27NO3(extend)",
Artist = "Team Grimoire"
},
Version = "[4K] Cataclysmic Hypernova"
},
Date = DateTimeOffset.Now,
Accuracy = 0.55879
};
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 10),
Children = new[]
{
new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(score)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(noPPScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(score, 0.85))
}
});
}
private class ColourProvidedContainer : Container
{
[Cached]
private readonly OverlayColourProvider colourProvider;
public ColourProvidedContainer(OverlayColourScheme colourScheme, DrawableProfileScore score)
{
colourProvider = new OverlayColourProvider(colourScheme);
AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X;
Add(score);
}
}
}
}

View File

@ -4,11 +4,13 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile.Sections;
using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Game.Users;
@ -20,7 +22,15 @@ namespace osu.Game.Tests.Visual.Online
{
protected override bool UseOnlineAPI => true;
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) };
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DrawableProfileScore),
typeof(DrawableProfileWeightedScore),
typeof(RanksSection)
};
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
public TestSceneUserRanks()
{

View File

@ -0,0 +1,175 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select.Details;
using osuTK.Graphics;
namespace osu.Game.Tests.Visual.SongSelect
{
[System.ComponentModel.Description("Advanced beatmap statistics display")]
public class TestSceneAdvancedStats : OsuTestScene
{
private TestAdvancedStats advancedStats;
[Resolved]
private RulesetStore rulesets { get; set; }
[Resolved]
private OsuColour colours { get; set; }
[SetUp]
public void Setup() => Schedule(() => Child = advancedStats = new TestAdvancedStats
{
Width = 500
});
private BeatmapInfo exampleBeatmapInfo => new BeatmapInfo
{
RulesetID = 0,
Ruleset = rulesets.AvailableRulesets.First(),
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 7.2f,
DrainRate = 3,
OverallDifficulty = 5.7f,
ApproachRate = 3.5f
},
StarDifficulty = 4.5f
};
[Test]
public void TestNoMod()
{
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
AddStep("no mods selected", () => SelectedMods.Value = Array.Empty<Mod>());
AddAssert("first bar text is Circle Size", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Circle Size");
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
}
[Test]
public void TestManiaFirstBarText()
{
AddStep("set beatmap", () => advancedStats.Beatmap = new BeatmapInfo
{
Ruleset = rulesets.GetRuleset(3),
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 5,
DrainRate = 4.3f,
OverallDifficulty = 4.5f,
ApproachRate = 3.1f
},
StarDifficulty = 8
});
AddAssert("first bar text is Key Count", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Key Count");
}
[Test]
public void TestEasyMod()
{
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
AddStep("select EZ mod", () =>
{
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModEasy>().Single() };
});
AddAssert("circle size bar is blue", () => barIsBlue(advancedStats.FirstValue));
AddAssert("HP drain bar is blue", () => barIsBlue(advancedStats.HpDrain));
AddAssert("accuracy bar is blue", () => barIsBlue(advancedStats.Accuracy));
AddAssert("approach rate bar is blue", () => barIsBlue(advancedStats.ApproachRate));
}
[Test]
public void TestHardRockMod()
{
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
AddStep("select HR mod", () =>
{
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModHardRock>().Single() };
});
AddAssert("circle size bar is red", () => barIsRed(advancedStats.FirstValue));
AddAssert("HP drain bar is red", () => barIsRed(advancedStats.HpDrain));
AddAssert("accuracy bar is red", () => barIsRed(advancedStats.Accuracy));
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
}
[Test]
public void TestUnchangedDifficultyAdjustMod()
{
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
AddStep("select unchanged Difficulty Adjust mod", () =>
{
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
difficultyAdjustMod.ReadFromDifficulty(advancedStats.Beatmap.BaseDifficulty);
SelectedMods.Value = new[] { difficultyAdjustMod };
});
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
}
[Test]
public void TestChangedDifficultyAdjustMod()
{
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
AddStep("select changed Difficulty Adjust mod", () =>
{
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
var originalDifficulty = advancedStats.Beatmap.BaseDifficulty;
var adjustedDifficulty = new BeatmapDifficulty
{
CircleSize = originalDifficulty.CircleSize,
DrainRate = originalDifficulty.DrainRate - 0.5f,
OverallDifficulty = originalDifficulty.OverallDifficulty,
ApproachRate = originalDifficulty.ApproachRate + 2.2f,
};
difficultyAdjustMod.ReadFromDifficulty(adjustedDifficulty);
SelectedMods.Value = new[] { difficultyAdjustMod };
});
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
AddAssert("drain rate bar is blue", () => barIsBlue(advancedStats.HpDrain));
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
}
private bool barIsWhite(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == Color4.White;
private bool barIsBlue(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.BlueDark;
private bool barIsRed(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.Red;
private class TestAdvancedStats : AdvancedStats
{
public new StatisticRow FirstValue => base.FirstValue;
public new StatisticRow HpDrain => base.HpDrain;
public new StatisticRow Accuracy => base.Accuracy;
public new StatisticRow ApproachRate => base.ApproachRate;
}
}
}

View File

@ -3,14 +3,8 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.SongSelect
@ -180,27 +174,5 @@ namespace osu.Game.Tests.Visual.SongSelect
OnlineBeatmapID = 162,
});
}
[Resolved]
private RulesetStore rulesets { get; set; }
[Resolved]
private OsuColour colours { get; set; }
[Test]
public void TestModAdjustments()
{
TestAllMetrics();
Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance();
AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) });
AddAssert("first bar coloured blue", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.BlueDark);
AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) });
AddAssert("first bar coloured red", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.Red);
}
}
}

View File

@ -23,6 +23,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Taiko;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Carousel;
using osu.Game.Screens.Select.Filter;
@ -72,19 +73,23 @@ namespace osu.Game.Tests.Visual.SongSelect
// required to get bindables attached
Add(music);
Beatmap.SetDefault();
Dependencies.Cache(config = new OsuConfigManager(LocalStorage));
}
private OsuConfigManager config;
[SetUp]
public virtual void SetUp() => Schedule(() =>
public override void SetUpSteps()
{
Ruleset.Value = new OsuRuleset().RulesetInfo;
manager?.Delete(manager.GetAllUsableBeatmapSets());
});
base.SetUpSteps();
AddStep("delete all beatmaps", () =>
{
Ruleset.Value = new OsuRuleset().RulesetInfo;
manager?.Delete(manager.GetAllUsableBeatmapSets());
Beatmap.SetDefault();
});
}
[Test]
public void TestSingleFilterOnEnter()
@ -118,10 +123,8 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.ReleaseKey(Key.Enter);
});
AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen());
AddAssert("ensure selection changed", () => selected != Beatmap.Value);
AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen());
AddUntilStep("bindable lease returned", () => !Beatmap.Disabled);
}
[Test]
@ -145,10 +148,8 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.ReleaseKey(Key.Down);
});
AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen());
AddAssert("ensure selection didn't change", () => selected == Beatmap.Value);
AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen());
AddUntilStep("bindable lease returned", () => !Beatmap.Disabled);
}
[Test]
@ -176,10 +177,8 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.ReleaseKey(Key.Enter);
});
AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen());
AddAssert("ensure selection changed", () => selected != Beatmap.Value);
AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen());
AddUntilStep("bindable lease returned", () => !Beatmap.Disabled);
}
[Test]
@ -208,10 +207,8 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.ReleaseButton(MouseButton.Left);
});
AddUntilStep("wait for not current", () => !songSelect.IsCurrentScreen());
AddAssert("ensure selection didn't change", () => selected == Beatmap.Value);
AddUntilStep("wait for return to song select", () => songSelect.IsCurrentScreen());
AddUntilStep("bindable lease returned", () => !Beatmap.Disabled);
}
[Test]
@ -429,6 +426,31 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("start not requested", () => !startRequested);
}
[Test]
public void TestAutoplayViaCtrlEnter()
{
addRulesetImportStep(0);
createSongSelect();
AddStep("press ctrl+enter", () =>
{
InputManager.PressKey(Key.ControlLeft);
InputManager.PressKey(Key.Enter);
InputManager.ReleaseKey(Key.ControlLeft);
InputManager.ReleaseKey(Key.Enter);
});
AddUntilStep("wait for player", () => Stack.CurrentScreen is PlayerLoader);
AddAssert("autoplay enabled", () => songSelect.Mods.Value.FirstOrDefault() is ModAutoplay);
AddUntilStep("wait for return to ss", () => songSelect.IsCurrentScreen());
AddAssert("mod disabled", () => songSelect.Mods.Value.Count == 0);
}
[Test]
public void TestHideSetSelectsCorrectBeatmap()
{

View File

@ -16,7 +16,8 @@ namespace osu.Game.Tests.Visual.UserInterface
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(FooterButtonMods)
typeof(FooterButtonMods),
typeof(FooterButton)
};
private readonly TestFooterButtonMods footerButtonMods;

View File

@ -60,9 +60,9 @@ namespace osu.Game.Tests.Visual.UserInterface
{
modSelect = new TestModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
SelectedMods = { BindTarget = SelectedMods }
},
modDisplay = new ModDisplay

View File

@ -27,6 +27,13 @@ namespace osu.Game.Tests.Visual.UserInterface
private readonly Mod testCustomisableAutoOpenMod = new TestModCustomisable2();
[SetUp]
public void SetUp() => Schedule(() =>
{
SelectedMods.Value = Array.Empty<Mod>();
Ruleset.Value = new TestRulesetInfo();
});
[Test]
public void TestButtonShowsOnCustomisableMod()
{
@ -70,13 +77,11 @@ namespace osu.Game.Tests.Visual.UserInterface
{
AddStep("create mod select", () =>
{
Ruleset.Value = new TestRulesetInfo();
Child = modSelect = new TestModSelectOverlay
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
SelectedMods = { BindTarget = SelectedMods }
};
});
}

View File

@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.UserInterface
addHeader("Orange OverlayHeader (no background)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange);
addHeader("Blue OverlayHeader", new TestNoControlHeader(), OverlayColourScheme.Blue);
addHeader("Green TabControlOverlayHeader (string)", new TestStringTabControlHeader(), OverlayColourScheme.Green);
addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green);
addHeader("Pink TabControlOverlayHeader (enum)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink);
addHeader("Red BreadcrumbControlOverlayHeader (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red);
}
@ -116,6 +116,8 @@ namespace osu.Game.Tests.Visual.UserInterface
protected override ScreenTitle CreateTitle() => new TestTitle();
protected override Drawable CreateTitleContent() => new OverlayRulesetSelector();
public TestStringTabControlHeader()
{
TabControl.AddItem("tab1");

View File

@ -0,0 +1,82 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using osu.Framework.Bindables;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osuTK;
using osu.Framework.Allocation;
namespace osu.Game.Tests.Visual.UserInterface
{
public class TestSceneOverlayRulesetSelector : OsuTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(OverlayRulesetSelector),
typeof(OverlayRulesetTabItem),
};
private readonly OverlayRulesetSelector selector;
private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
public TestSceneOverlayRulesetSelector()
{
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(0, 5),
Children = new[]
{
new ColourProvidedContainer(OverlayColourScheme.Green, selector = new OverlayRulesetSelector { Current = ruleset }),
new ColourProvidedContainer(OverlayColourScheme.Blue, new OverlayRulesetSelector { Current = ruleset }),
new ColourProvidedContainer(OverlayColourScheme.Orange, new OverlayRulesetSelector { Current = ruleset }),
new ColourProvidedContainer(OverlayColourScheme.Pink, new OverlayRulesetSelector { Current = ruleset }),
new ColourProvidedContainer(OverlayColourScheme.Purple, new OverlayRulesetSelector { Current = ruleset }),
new ColourProvidedContainer(OverlayColourScheme.Red, new OverlayRulesetSelector { Current = ruleset }),
}
});
}
private class ColourProvidedContainer : Container
{
[Cached]
private readonly OverlayColourProvider colourProvider;
public ColourProvidedContainer(OverlayColourScheme colourScheme, OverlayRulesetSelector rulesetSelector)
{
colourProvider = new OverlayColourProvider(colourScheme);
AutoSizeAxes = Axes.Both;
Add(rulesetSelector);
}
}
[Test]
public void TestSelection()
{
AddStep("Select osu!", () => ruleset.Value = new OsuRuleset().RulesetInfo);
AddAssert("Check osu! selected", () => selector.Current.Value.Equals(new OsuRuleset().RulesetInfo));
AddStep("Select mania", () => ruleset.Value = new ManiaRuleset().RulesetInfo);
AddAssert("Check mania selected", () => selector.Current.Value.Equals(new ManiaRuleset().RulesetInfo));
AddStep("Select taiko", () => ruleset.Value = new TaikoRuleset().RulesetInfo);
AddAssert("Check taiko selected", () => selector.Current.Value.Equals(new TaikoRuleset().RulesetInfo));
AddStep("Select catch", () => ruleset.Value = new CatchRuleset().RulesetInfo);
AddAssert("Check catch selected", () => selector.Current.Value.Equals(new CatchRuleset().RulesetInfo));
}
}
}

View File

@ -25,7 +25,9 @@ namespace osu.Game.Tests.Visual.UserInterface
OsuSpriteText titleText;
IScreen startScreen = new TestScreenOne();
screenStack = new OsuScreenStack(startScreen) { RelativeSizeAxes = Axes.Both };
screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
screenStack.Push(startScreen);
Children = new Drawable[]
{