mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 15:44:04 +09:00
Merge branch 'master' into use-dummy-api-for-overall-tests
This commit is contained in:
@ -482,5 +482,17 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
Assert.AreEqual(hitObjects[0].Samples[0].Bank, hitObjects[0].Samples[1].Bank);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidEventStillPasses()
|
||||
{
|
||||
var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
|
||||
|
||||
using (var badResStream = TestResources.OpenResource("invalid-events.osu"))
|
||||
using (var badStream = new StreamReader(badResStream))
|
||||
{
|
||||
Assert.DoesNotThrow(() => decoder.Decode(badStream));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
|
||||
int spriteCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSprite));
|
||||
int animationCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardAnimation));
|
||||
int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSample));
|
||||
int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSampleInfo));
|
||||
|
||||
Assert.AreEqual(15, spriteCount);
|
||||
Assert.AreEqual(1, animationCount);
|
||||
|
116
osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs
Normal file
116
osu.Game.Tests/Beatmaps/SliderEventGenerationTest.cs
Normal file
@ -0,0 +1,116 @@
|
||||
// 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.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
[TestFixture]
|
||||
public class SliderEventGenerationTest
|
||||
{
|
||||
private const double start_time = 0;
|
||||
private const double span_duration = 1000;
|
||||
|
||||
[Test]
|
||||
public void TestSingleSpan()
|
||||
{
|
||||
var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 1, null).ToArray();
|
||||
|
||||
Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head));
|
||||
Assert.That(events[0].Time, Is.EqualTo(start_time));
|
||||
|
||||
Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[1].Time, Is.EqualTo(span_duration / 2));
|
||||
|
||||
Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tail));
|
||||
Assert.That(events[3].Time, Is.EqualTo(span_duration));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeat()
|
||||
{
|
||||
var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 2, null).ToArray();
|
||||
|
||||
Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head));
|
||||
Assert.That(events[0].Time, Is.EqualTo(start_time));
|
||||
|
||||
Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[1].Time, Is.EqualTo(span_duration / 2));
|
||||
|
||||
Assert.That(events[2].Type, Is.EqualTo(SliderEventType.Repeat));
|
||||
Assert.That(events[2].Time, Is.EqualTo(span_duration));
|
||||
|
||||
Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[3].Time, Is.EqualTo(span_duration + span_duration / 2));
|
||||
|
||||
Assert.That(events[5].Type, Is.EqualTo(SliderEventType.Tail));
|
||||
Assert.That(events[5].Time, Is.EqualTo(2 * span_duration));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonEvenTicks()
|
||||
{
|
||||
var events = SliderEventGenerator.Generate(start_time, span_duration, 1, 300, span_duration, 2, null).ToArray();
|
||||
|
||||
Assert.That(events[0].Type, Is.EqualTo(SliderEventType.Head));
|
||||
Assert.That(events[0].Time, Is.EqualTo(start_time));
|
||||
|
||||
Assert.That(events[1].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[1].Time, Is.EqualTo(300));
|
||||
|
||||
Assert.That(events[2].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[2].Time, Is.EqualTo(600));
|
||||
|
||||
Assert.That(events[3].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[3].Time, Is.EqualTo(900));
|
||||
|
||||
Assert.That(events[4].Type, Is.EqualTo(SliderEventType.Repeat));
|
||||
Assert.That(events[4].Time, Is.EqualTo(span_duration));
|
||||
|
||||
Assert.That(events[5].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[5].Time, Is.EqualTo(1100));
|
||||
|
||||
Assert.That(events[6].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[6].Time, Is.EqualTo(1400));
|
||||
|
||||
Assert.That(events[7].Type, Is.EqualTo(SliderEventType.Tick));
|
||||
Assert.That(events[7].Time, Is.EqualTo(1700));
|
||||
|
||||
Assert.That(events[9].Type, Is.EqualTo(SliderEventType.Tail));
|
||||
Assert.That(events[9].Time, Is.EqualTo(2 * span_duration));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLegacyLastTickOffset()
|
||||
{
|
||||
var events = SliderEventGenerator.Generate(start_time, span_duration, 1, span_duration / 2, span_duration, 1, 100).ToArray();
|
||||
|
||||
Assert.That(events[2].Type, Is.EqualTo(SliderEventType.LegacyLastTick));
|
||||
Assert.That(events[2].Time, Is.EqualTo(900));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMinimumTickDistance()
|
||||
{
|
||||
const double velocity = 5;
|
||||
const double min_distance = velocity * 10;
|
||||
|
||||
var events = SliderEventGenerator.Generate(start_time, span_duration, velocity, velocity, span_duration, 2, 0).ToArray();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
int tickIndex = -1;
|
||||
|
||||
while (++tickIndex < events.Length)
|
||||
{
|
||||
if (events[tickIndex].Type != SliderEventType.Tick)
|
||||
continue;
|
||||
|
||||
Assert.That(events[tickIndex].Time, Is.LessThan(span_duration - min_distance).Or.GreaterThan(span_duration + min_distance));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -119,6 +119,53 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(11, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOldFormatLinkWithBalancedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a (tricky (one))[https://osu.ppy.sh]!" });
|
||||
|
||||
Assert.AreEqual("This is a tricky (one)!", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(12, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOldFormatLinkWithEscapedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is (another loose bracket \\))[https://osu.ppy.sh]." });
|
||||
|
||||
Assert.AreEqual("This is another loose bracket ).", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(8, result.Links[0].Index);
|
||||
Assert.AreEqual(23, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOldFormatWithBackslashes()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This link (should end with a backslash \\)[https://osu.ppy.sh]." });
|
||||
Assert.AreEqual("This link should end with a backslash \\.", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(29, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOldFormatLinkWithEscapedAndBalancedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a (\\)super\\(\\( tricky (one))[https://osu.ppy.sh]!" });
|
||||
|
||||
Assert.AreEqual("This is a )super(( tricky (one)!", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(21, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewFormatLink()
|
||||
{
|
||||
@ -131,6 +178,42 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(11, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewFormatLinkWithEscapedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh nasty link with escaped brackets: \\] and \\[]" });
|
||||
|
||||
Assert.AreEqual("This is a nasty link with escaped brackets: ] and [", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(41, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewFormatLinkWithBackslashesInside()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh link \\ with \\ backslashes \\]" });
|
||||
|
||||
Assert.AreEqual("This is a link \\ with \\ backslashes \\", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(27, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewFormatLinkWithEscapedAndBalancedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh [link [with \\] too many brackets \\[ ]]]" });
|
||||
|
||||
Assert.AreEqual("This is a [link [with ] too many brackets [ ]]", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(36, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMarkdownFormatLink()
|
||||
{
|
||||
@ -143,6 +226,53 @@ namespace osu.Game.Tests.Chat
|
||||
Assert.AreEqual(11, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMarkdownFormatLinkWithBalancedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [tricky [one]](https://osu.ppy.sh)!" });
|
||||
|
||||
Assert.AreEqual("This is a tricky [one]!", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(12, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMarkdownFormatLinkWithEscapedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is [another loose bracket \\]](https://osu.ppy.sh)." });
|
||||
|
||||
Assert.AreEqual("This is another loose bracket ].", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(8, result.Links[0].Index);
|
||||
Assert.AreEqual(23, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMarkdownFormatWithBackslashes()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This link [should end with a backslash \\](https://osu.ppy.sh)." });
|
||||
Assert.AreEqual("This link should end with a backslash \\.", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(29, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMarkdownFormatLinkWithEscapedAndBalancedBrackets()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [\\]super\\[\\[ tricky [one]](https://osu.ppy.sh)!" });
|
||||
|
||||
Assert.AreEqual("This is a ]super[[ tricky [one]!", result.DisplayContent);
|
||||
Assert.AreEqual(1, result.Links.Count);
|
||||
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
|
||||
Assert.AreEqual(10, result.Links[0].Index);
|
||||
Assert.AreEqual(21, result.Links[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChannelLink()
|
||||
{
|
||||
|
14
osu.Game.Tests/Resources/invalid-events.osu
Normal file
14
osu.Game.Tests/Resources/invalid-events.osu
Normal file
@ -0,0 +1,14 @@
|
||||
osu file format v14
|
||||
|
||||
[Events]
|
||||
bad,event,this,should,fail
|
||||
//Background and Video events
|
||||
0,0,"machinetop_background.jpg",0,0
|
||||
//Break Periods
|
||||
2,122474,140135
|
||||
//Storyboard Layer 0 (Background)
|
||||
this,is,also,bad
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
@ -119,14 +119,14 @@ namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
performFullSetup();
|
||||
createFakeStoryboard();
|
||||
AddStep("Storyboard Enabled", () =>
|
||||
AddStep("Enable Storyboard", () =>
|
||||
{
|
||||
player.ReplacesBackground.Value = true;
|
||||
player.StoryboardEnabled.Value = true;
|
||||
});
|
||||
waitForDim();
|
||||
AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible);
|
||||
AddStep("Storyboard Disabled", () =>
|
||||
AddStep("Disable Storyboard", () =>
|
||||
{
|
||||
player.ReplacesBackground.Value = false;
|
||||
player.StoryboardEnabled.Value = false;
|
||||
@ -149,22 +149,44 @@ namespace osu.Game.Tests.Visual.Background
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the <see cref="UserDimContainer"/> is properly accepting user-defined visual changes at all.
|
||||
/// Ensure <see cref="UserDimContainer"/> is properly accepting user-defined visual changes for a background.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DisableUserDimTest()
|
||||
public void DisableUserDimBackgroundTest()
|
||||
{
|
||||
performFullSetup();
|
||||
waitForDim();
|
||||
AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
||||
AddStep("EnableUserDim disabled", () => songSelect.DimEnabled.Value = false);
|
||||
AddStep("Enable user dim", () => songSelect.DimEnabled.Value = false);
|
||||
waitForDim();
|
||||
AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.IsUserBlurDisabled());
|
||||
AddStep("EnableUserDim enabled", () => songSelect.DimEnabled.Value = true);
|
||||
AddStep("Disable user dim", () => songSelect.DimEnabled.Value = true);
|
||||
waitForDim();
|
||||
AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure <see cref="UserDimContainer"/> is properly accepting user-defined visual changes for a storyboard.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DisableUserDimStoryboardTest()
|
||||
{
|
||||
performFullSetup();
|
||||
createFakeStoryboard();
|
||||
AddStep("Enable Storyboard", () =>
|
||||
{
|
||||
player.ReplacesBackground.Value = true;
|
||||
player.StoryboardEnabled.Value = true;
|
||||
});
|
||||
AddStep("Enable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = true);
|
||||
AddStep("Set dim level to 1", () => songSelect.DimLevel.Value = 1f);
|
||||
waitForDim();
|
||||
AddAssert("Storyboard is invisible", () => !player.IsStoryboardVisible);
|
||||
AddStep("Disable user dim", () => player.DimmableStoryboard.EnableUserDim.Value = false);
|
||||
waitForDim();
|
||||
AddAssert("Storyboard is visible", () => player.IsStoryboardVisible);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the visual settings container retains dim and blur when pausing
|
||||
/// </summary>
|
||||
|
@ -16,15 +16,13 @@ using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Compose;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
[Cached(Type = typeof(IPlacementHandler))]
|
||||
public class TestSceneHitObjectComposer : OsuTestScene, IPlacementHandler
|
||||
public class TestSceneHitObjectComposer : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -39,8 +37,6 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
typeof(HitCirclePlacementBlueprint),
|
||||
};
|
||||
|
||||
private HitObjectComposer composer;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -67,15 +63,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
Dependencies.CacheAs<IAdjustableClock>(clock);
|
||||
Dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||
|
||||
Child = composer = new OsuHitObjectComposer(new OsuRuleset());
|
||||
Child = new OsuHitObjectComposer(new OsuRuleset());
|
||||
}
|
||||
|
||||
public void BeginPlacement(HitObject hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject) => composer.Add(hitObject);
|
||||
|
||||
public void Delete(HitObject hitObject) => composer.Remove(hitObject);
|
||||
}
|
||||
}
|
||||
|
119
osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs
Normal file
119
osu.Game.Tests/Visual/Gameplay/TestSceneBarHitErrorMeter.cs
Normal file
@ -0,0 +1,119 @@
|
||||
// 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.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneBarHitErrorMeter : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(HitErrorMeter),
|
||||
};
|
||||
|
||||
private HitErrorMeter meter;
|
||||
private HitErrorMeter meter2;
|
||||
private HitWindows hitWindows;
|
||||
|
||||
public TestSceneBarHitErrorMeter()
|
||||
{
|
||||
recreateDisplay(new OsuHitWindows(), 5);
|
||||
|
||||
AddRepeatStep("New random judgement", () => newJudgement(), 40);
|
||||
|
||||
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.HalfWindowFor(HitResult.Meh)), 20);
|
||||
AddRepeatStep("New max positive", () => newJudgement(hitWindows.HalfWindowFor(HitResult.Meh)), 20);
|
||||
AddStep("New fixed judgement (50ms)", () => newJudgement(50));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOsu()
|
||||
{
|
||||
AddStep("OD 1", () => recreateDisplay(new OsuHitWindows(), 1));
|
||||
AddStep("OD 10", () => recreateDisplay(new OsuHitWindows(), 10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTaiko()
|
||||
{
|
||||
AddStep("OD 1", () => recreateDisplay(new TaikoHitWindows(), 1));
|
||||
AddStep("OD 10", () => recreateDisplay(new TaikoHitWindows(), 10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMania()
|
||||
{
|
||||
AddStep("OD 1", () => recreateDisplay(new ManiaHitWindows(), 1));
|
||||
AddStep("OD 10", () => recreateDisplay(new ManiaHitWindows(), 10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCatch()
|
||||
{
|
||||
AddStep("OD 1", () => recreateDisplay(new CatchHitWindows(), 1));
|
||||
AddStep("OD 10", () => recreateDisplay(new CatchHitWindows(), 10));
|
||||
}
|
||||
|
||||
private void recreateDisplay(HitWindows hitWindows, float overallDifficulty)
|
||||
{
|
||||
this.hitWindows = hitWindows;
|
||||
|
||||
hitWindows?.SetDifficulty(overallDifficulty);
|
||||
|
||||
Clear();
|
||||
|
||||
Add(new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new SpriteText { Text = $@"Great: {hitWindows?.Great}" },
|
||||
new SpriteText { Text = $@"Good: {hitWindows?.Good}" },
|
||||
new SpriteText { Text = $@"Meh: {hitWindows?.Meh}" },
|
||||
}
|
||||
});
|
||||
|
||||
Add(meter = new BarHitErrorMeter(hitWindows, true)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
});
|
||||
|
||||
Add(meter2 = new BarHitErrorMeter(hitWindows, false)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
});
|
||||
}
|
||||
|
||||
private void newJudgement(double offset = 0)
|
||||
{
|
||||
var judgement = new JudgementResult(new HitObject(), new Judgement())
|
||||
{
|
||||
TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset,
|
||||
Type = HitResult.Perfect,
|
||||
};
|
||||
|
||||
meter.OnNewJudgement(judgement);
|
||||
meter2.OnNewJudgement(judgement);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
@ -11,78 +14,172 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[TestFixture]
|
||||
public class TestSceneBreakOverlay : OsuTestScene
|
||||
{
|
||||
private readonly BreakOverlay breakOverlay;
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(BreakOverlay),
|
||||
};
|
||||
|
||||
private readonly TestBreakOverlay breakOverlay;
|
||||
|
||||
private readonly IReadOnlyList<BreakPeriod> testBreaks = new List<BreakPeriod>
|
||||
{
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = 1000,
|
||||
EndTime = 5000,
|
||||
},
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = 6000,
|
||||
EndTime = 13500,
|
||||
},
|
||||
};
|
||||
|
||||
public TestSceneBreakOverlay()
|
||||
{
|
||||
Child = breakOverlay = new BreakOverlay(true);
|
||||
|
||||
AddStep("2s break", () => startBreak(2000));
|
||||
AddStep("5s break", () => startBreak(5000));
|
||||
AddStep("10s break", () => startBreak(10000));
|
||||
AddStep("15s break", () => startBreak(15000));
|
||||
AddStep("2s, 2s", startMultipleBreaks);
|
||||
AddStep("0.5s, 0.7s, 1s, 2s", startAnotherMultipleBreaks);
|
||||
Add(breakOverlay = new TestBreakOverlay(true));
|
||||
}
|
||||
|
||||
private void startBreak(double duration)
|
||||
[Test]
|
||||
public void TestShowBreaks()
|
||||
{
|
||||
breakOverlay.Breaks = new List<BreakPeriod>
|
||||
setClock(false);
|
||||
|
||||
addShowBreakStep(2);
|
||||
addShowBreakStep(5);
|
||||
addShowBreakStep(15);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoEffectsBreak()
|
||||
{
|
||||
var shortBreak = new BreakPeriod { EndTime = 500 };
|
||||
|
||||
setClock(true);
|
||||
loadBreaksStep("short break", new[] { shortBreak });
|
||||
|
||||
addBreakSeeks(shortBreak, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleBreaks()
|
||||
{
|
||||
setClock(true);
|
||||
loadBreaksStep("multiple breaks", testBreaks);
|
||||
|
||||
foreach (var b in testBreaks)
|
||||
addBreakSeeks(b, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRewindBreaks()
|
||||
{
|
||||
setClock(true);
|
||||
loadBreaksStep("multiple breaks", testBreaks);
|
||||
|
||||
foreach (var b in testBreaks.Reverse())
|
||||
addBreakSeeks(b, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSkipBreaks()
|
||||
{
|
||||
setClock(true);
|
||||
loadBreaksStep("multiple breaks", testBreaks);
|
||||
|
||||
seekAndAssertBreak("seek to break start", testBreaks[1].StartTime, true);
|
||||
AddAssert("is skipped to break #2", () => breakOverlay.CurrentBreakIndex == 1);
|
||||
|
||||
seekAndAssertBreak("seek to break middle", testBreaks[1].StartTime + testBreaks[1].Duration / 2, true);
|
||||
seekAndAssertBreak("seek to break end", testBreaks[1].EndTime, false);
|
||||
seekAndAssertBreak("seek to break after end", testBreaks[1].EndTime + 500, false);
|
||||
}
|
||||
|
||||
private void addShowBreakStep(double seconds)
|
||||
{
|
||||
AddStep($"show '{seconds}s' break", () => breakOverlay.Breaks = new List<BreakPeriod>
|
||||
{
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = Clock.CurrentTime,
|
||||
EndTime = Clock.CurrentTime + duration,
|
||||
EndTime = Clock.CurrentTime + seconds * 1000,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void startMultipleBreaks()
|
||||
private void setClock(bool useManual)
|
||||
{
|
||||
double currentTime = Clock.CurrentTime;
|
||||
|
||||
breakOverlay.Breaks = new List<BreakPeriod>
|
||||
{
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = currentTime,
|
||||
EndTime = currentTime + 2000,
|
||||
},
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = currentTime + 4000,
|
||||
EndTime = currentTime + 6000,
|
||||
}
|
||||
};
|
||||
AddStep($"set {(useManual ? "manual" : "realtime")} clock", () => breakOverlay.SwitchClock(useManual));
|
||||
}
|
||||
|
||||
private void startAnotherMultipleBreaks()
|
||||
private void loadBreaksStep(string breakDescription, IReadOnlyList<BreakPeriod> breaks)
|
||||
{
|
||||
double currentTime = Clock.CurrentTime;
|
||||
AddStep($"load {breakDescription}", () => breakOverlay.Breaks = breaks);
|
||||
seekAndAssertBreak("seek back to 0", 0, false);
|
||||
}
|
||||
|
||||
breakOverlay.Breaks = new List<BreakPeriod>
|
||||
private void addBreakSeeks(BreakPeriod b, bool isReversed)
|
||||
{
|
||||
if (isReversed)
|
||||
{
|
||||
new BreakPeriod // Duration is less than 650 - too short to appear
|
||||
{
|
||||
StartTime = currentTime,
|
||||
EndTime = currentTime + 500,
|
||||
},
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = currentTime + 1500,
|
||||
EndTime = currentTime + 2200,
|
||||
},
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = currentTime + 3200,
|
||||
EndTime = currentTime + 4200,
|
||||
},
|
||||
new BreakPeriod
|
||||
{
|
||||
StartTime = currentTime + 5200,
|
||||
EndTime = currentTime + 7200,
|
||||
}
|
||||
};
|
||||
seekAndAssertBreak("seek to break after end", b.EndTime + 500, false);
|
||||
seekAndAssertBreak("seek to break end", b.EndTime, false);
|
||||
seekAndAssertBreak("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect);
|
||||
seekAndAssertBreak("seek to break start", b.StartTime, b.HasEffect);
|
||||
}
|
||||
else
|
||||
{
|
||||
seekAndAssertBreak("seek to break start", b.StartTime, b.HasEffect);
|
||||
seekAndAssertBreak("seek to break middle", b.StartTime + b.Duration / 2, b.HasEffect);
|
||||
seekAndAssertBreak("seek to break end", b.EndTime, false);
|
||||
seekAndAssertBreak("seek to break after end", b.EndTime + 500, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void seekAndAssertBreak(string seekStepDescription, double time, bool shouldBeBreak)
|
||||
{
|
||||
AddStep(seekStepDescription, () => breakOverlay.ManualClockTime = time);
|
||||
AddAssert($"is{(!shouldBeBreak ? " not" : string.Empty)} break time", () =>
|
||||
{
|
||||
breakOverlay.ProgressTime();
|
||||
return breakOverlay.IsBreakTime.Value == shouldBeBreak;
|
||||
});
|
||||
}
|
||||
|
||||
private class TestBreakOverlay : BreakOverlay
|
||||
{
|
||||
private readonly FramedClock framedManualClock;
|
||||
private readonly ManualClock manualClock;
|
||||
private IFrameBasedClock originalClock;
|
||||
|
||||
public new int CurrentBreakIndex => base.CurrentBreakIndex;
|
||||
|
||||
public double ManualClockTime
|
||||
{
|
||||
get => manualClock.CurrentTime;
|
||||
set => manualClock.CurrentTime = value;
|
||||
}
|
||||
|
||||
public TestBreakOverlay(bool letterboxing)
|
||||
: base(letterboxing)
|
||||
{
|
||||
framedManualClock = new FramedClock(manualClock = new ManualClock());
|
||||
ProcessCustomClock = false;
|
||||
}
|
||||
|
||||
public void ProgressTime()
|
||||
{
|
||||
framedManualClock.ProcessFrame();
|
||||
Update();
|
||||
}
|
||||
|
||||
public void SwitchClock(bool setManual) => Clock = setManual ? framedManualClock : originalClock;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
originalClock = Clock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,305 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneDrawableScrollingRuleset : OsuTestScene
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of time visible by the "view window" of the playfield.
|
||||
/// All hitobjects added through <see cref="createBeatmap"/> are spaced apart by this value, such that for a beat length of 1000,
|
||||
/// there will be at most 2 hitobjects visible in the "view window".
|
||||
/// </summary>
|
||||
private const double time_range = 1000;
|
||||
|
||||
private readonly ManualClock testClock = new ManualClock();
|
||||
private TestDrawableScrollingRuleset drawableRuleset;
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() => testClock.CurrentTime = 0);
|
||||
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleSingleTimingPoint()
|
||||
{
|
||||
var beatmap = createBeatmap(new TimingControlPoint { BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
assertPosition(0, 0f);
|
||||
|
||||
// The single timing point is 1x speed relative to itself, such that the hitobject occurring time_range milliseconds later should appear
|
||||
// at the bottom of the view window regardless of the timing point's beat length
|
||||
assertPosition(1, 1f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleTimingPointBeyondEndDoesNotBecomeDominant()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range / 2 },
|
||||
new TimingControlPoint { Time = 12000, BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 100000, BeatLength = time_range });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
assertPosition(0, 0f);
|
||||
assertPosition(1, 1f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRelativeBeatLengthScaleFromSecondTimingPoint()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||
|
||||
// The first timing point should have a relative velocity of 2
|
||||
assertPosition(0, 0f);
|
||||
assertPosition(1, 0.5f);
|
||||
assertPosition(2, 1f);
|
||||
|
||||
// Move to the second timing point
|
||||
setTime(3 * time_range);
|
||||
assertPosition(3, 0f);
|
||||
|
||||
// As above, this is the timing point that is 1x speed relative to itself, so the hitobject occurring time_range milliseconds later should be at the bottom of the view window
|
||||
assertPosition(4, 1f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonRelativeScale()
|
||||
{
|
||||
var beatmap = createBeatmap(
|
||||
new TimingControlPoint { BeatLength = time_range },
|
||||
new TimingControlPoint { Time = 3 * time_range, BeatLength = time_range / 2 });
|
||||
|
||||
createTest(beatmap);
|
||||
|
||||
assertPosition(0, 0f);
|
||||
assertPosition(1, 1);
|
||||
|
||||
// Move to the second timing point
|
||||
setTime(3 * time_range);
|
||||
assertPosition(3, 0f);
|
||||
|
||||
// For a beat length of 500, the view window of this timing point is elongated 2x (1000 / 500), such that the second hitobject is two TimeRanges away (offscreen)
|
||||
// To bring it on-screen, half TimeRange is added to the current time, bringing the second half of the view window into view, and the hitobject should appear at the bottom
|
||||
setTime(3 * time_range + time_range / 2);
|
||||
assertPosition(4, 1f);
|
||||
}
|
||||
|
||||
private void assertPosition(int index, float relativeY) => AddAssert($"hitobject {index} at {relativeY}",
|
||||
() => Precision.AlmostEquals(drawableRuleset.Playfield.AllHitObjects.ElementAt(index).DrawPosition.Y, drawableRuleset.Playfield.HitObjectContainer.DrawHeight * relativeY));
|
||||
|
||||
private void setTime(double time)
|
||||
{
|
||||
AddStep($"set time = {time}", () => testClock.CurrentTime = time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IBeatmap"/>, containing 10 hitobjects and user-provided timing points.
|
||||
/// The hitobjects are spaced <see cref="time_range"/> milliseconds apart.
|
||||
/// </summary>
|
||||
/// <param name="timingControlPoints">The timing points to add to the beatmap.</param>
|
||||
/// <returns>The <see cref="IBeatmap"/>.</returns>
|
||||
private IBeatmap createBeatmap(params TimingControlPoint[] timingControlPoints)
|
||||
{
|
||||
var beatmap = new Beatmap<HitObject> { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } };
|
||||
|
||||
beatmap.ControlPointInfo.TimingPoints.AddRange(timingControlPoints);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range });
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private void createTest(IBeatmap beatmap, Action<TestDrawableScrollingRuleset> overrideAction = null) => AddStep("create test", () =>
|
||||
{
|
||||
var ruleset = new TestScrollingRuleset();
|
||||
|
||||
drawableRuleset = (TestDrawableScrollingRuleset)ruleset.CreateDrawableRulesetWith(CreateWorkingBeatmap(beatmap), Array.Empty<Mod>());
|
||||
drawableRuleset.FrameStablePlayback = false;
|
||||
|
||||
overrideAction?.Invoke(drawableRuleset);
|
||||
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Height = 0.75f,
|
||||
Width = 400,
|
||||
Masking = true,
|
||||
Clock = new FramedClock(testClock),
|
||||
Child = drawableRuleset
|
||||
};
|
||||
});
|
||||
|
||||
#region Ruleset
|
||||
|
||||
private class TestScrollingRuleset : Ruleset
|
||||
{
|
||||
public TestScrollingRuleset(RulesetInfo rulesetInfo = null)
|
||||
: base(rulesetInfo)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => throw new NotImplementedException();
|
||||
|
||||
public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new TestDrawableScrollingRuleset(this, beatmap, mods);
|
||||
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap);
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
|
||||
|
||||
public override string Description { get; } = string.Empty;
|
||||
|
||||
public override string ShortName { get; } = string.Empty;
|
||||
}
|
||||
|
||||
private class TestDrawableScrollingRuleset : DrawableScrollingRuleset<TestHitObject>
|
||||
{
|
||||
public bool RelativeScaleBeatLengthsOverride { get; set; }
|
||||
|
||||
protected override bool RelativeScaleBeatLengths => RelativeScaleBeatLengthsOverride;
|
||||
|
||||
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping;
|
||||
|
||||
public TestDrawableScrollingRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
TimeRange.Value = time_range;
|
||||
}
|
||||
|
||||
public override DrawableHitObject<TestHitObject> CreateDrawableRepresentation(TestHitObject h) => new DrawableTestHitObject(h);
|
||||
|
||||
protected override PassThroughInputManager CreateInputManager() => new PassThroughInputManager();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new TestPlayfield();
|
||||
}
|
||||
|
||||
private class TestPlayfield : ScrollingPlayfield
|
||||
{
|
||||
public TestPlayfield()
|
||||
{
|
||||
AddInternal(new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = 150 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 2,
|
||||
Colour = Color4.Green
|
||||
},
|
||||
HitObjectContainer
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class TestBeatmapConverter : BeatmapConverter<TestHitObject>
|
||||
{
|
||||
public TestBeatmapConverter(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> ValidConversionTypes => new[] { typeof(HitObject) };
|
||||
|
||||
protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
|
||||
{
|
||||
yield return new TestHitObject
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
EndTime = (original as IHasEndTime)?.EndTime ?? (original.StartTime + 100)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HitObject
|
||||
|
||||
private class TestHitObject : HitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime { get; set; }
|
||||
|
||||
public double Duration => EndTime - StartTime;
|
||||
}
|
||||
|
||||
private class DrawableTestHitObject : DrawableHitObject<TestHitObject>
|
||||
{
|
||||
public DrawableTestHitObject(TestHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
Size = new Vector2(100, 25);
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.LightPink
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 2,
|
||||
Colour = Color4.Red
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -3,12 +3,13 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
@ -16,7 +17,7 @@ using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
[Description("player pause/fail screens")]
|
||||
[System.ComponentModel.Description("player pause/fail screens")]
|
||||
public class TestSceneGameplayMenuOverlay : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseOverlay) };
|
||||
@ -29,57 +30,118 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game)
|
||||
{
|
||||
Child = globalActionContainer = new GlobalActionContainer(game)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
pauseOverlay = new PauseOverlay
|
||||
{
|
||||
OnResume = () => Logger.Log(@"Resume"),
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
},
|
||||
failOverlay = new FailOverlay
|
||||
Child = globalActionContainer = new GlobalActionContainer(game);
|
||||
}
|
||||
|
||||
{
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
}
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
globalActionContainer.Children = new Drawable[]
|
||||
{
|
||||
pauseOverlay = new PauseOverlay
|
||||
{
|
||||
OnResume = () => Logger.Log(@"Resume"),
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
},
|
||||
failOverlay = new FailOverlay
|
||||
|
||||
{
|
||||
OnRetry = () => Logger.Log(@"Retry"),
|
||||
OnQuit = () => Logger.Log(@"Quit"),
|
||||
}
|
||||
};
|
||||
|
||||
InputManager.MoveMouseTo(Vector2.Zero);
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestAdjustRetryCount()
|
||||
{
|
||||
showOverlay();
|
||||
|
||||
var retryCount = 0;
|
||||
|
||||
AddStep("Add retry", () =>
|
||||
AddRepeatStep("Add retry", () =>
|
||||
{
|
||||
retryCount++;
|
||||
pauseOverlay.Retries = failOverlay.Retries = retryCount;
|
||||
});
|
||||
}, 10);
|
||||
}
|
||||
|
||||
AddToggleStep("Toggle pause overlay", t => pauseOverlay.ToggleVisibility());
|
||||
AddToggleStep("Toggle fail overlay", t => failOverlay.ToggleVisibility());
|
||||
/// <summary>
|
||||
/// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnterWithoutSelection()
|
||||
{
|
||||
showOverlay();
|
||||
|
||||
testHideResets();
|
||||
AddStep("Press select", () => press(GlobalAction.Select));
|
||||
AddAssert("Overlay still open", () => pauseOverlay.State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
testEnterWithoutSelection();
|
||||
testKeyUpFromInitial();
|
||||
testKeyDownFromInitial();
|
||||
testKeyUpWrapping();
|
||||
testKeyDownWrapping();
|
||||
/// <summary>
|
||||
/// Tests that pressing the up arrow from the initial state selects the last button.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestKeyUpFromInitial()
|
||||
{
|
||||
showOverlay();
|
||||
|
||||
testMouseSelectionAfterKeySelection();
|
||||
testKeySelectionAfterMouseSelection();
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected.Value);
|
||||
}
|
||||
|
||||
testMouseDeselectionResets();
|
||||
/// <summary>
|
||||
/// Tests that pressing the down arrow from the initial state selects the first button.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestKeyDownFromInitial()
|
||||
{
|
||||
showOverlay();
|
||||
|
||||
testClickSelection();
|
||||
testEnterKeySelection();
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => getButton(0).Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the up arrow repeatedly causes the selected button to wrap correctly.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestKeyUpWrapping()
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the down arrow repeatedly causes the selected button to wrap correctly.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestKeyDownWrapping()
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that hiding the overlay after hovering a button will reset the overlay to the initial state with no buttons selected.
|
||||
/// </summary>
|
||||
private void testHideResets()
|
||||
[Test]
|
||||
public void TestHideResets()
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
@ -90,141 +152,73 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred.
|
||||
/// Tests that entering menu with cursor initially on button selects it.
|
||||
/// </summary>
|
||||
private void testEnterWithoutSelection()
|
||||
[Test]
|
||||
public void TestInitialButtonHover()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
showOverlay();
|
||||
|
||||
AddStep("Press select", () => press(GlobalAction.Select));
|
||||
AddAssert("Overlay still open", () => pauseOverlay.State.Value == Visibility.Visible);
|
||||
AddStep("Hover first button", () => InputManager.MoveMouseTo(getButton(0)));
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
}
|
||||
showOverlay();
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the up arrow from the initial state selects the last button.
|
||||
/// </summary>
|
||||
private void testKeyUpFromInitial()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the down arrow from the initial state selects the first button.
|
||||
/// </summary>
|
||||
private void testKeyDownFromInitial()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the up arrow repeatedly causes the selected button to wrap correctly.
|
||||
/// </summary>
|
||||
private void testKeyUpWrapping()
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => failOverlay.Hide());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing the down arrow repeatedly causes the selected button to wrap correctly.
|
||||
/// </summary>
|
||||
private void testKeyDownWrapping()
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value);
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => failOverlay.Hide());
|
||||
AddAssert("First button selected", () => getButton(0).Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that hovering a button that was previously selected with the keyboard correctly selects the new button and deselects the previous button.
|
||||
/// </summary>
|
||||
private void testMouseSelectionAfterKeySelection()
|
||||
[Test]
|
||||
public void TestMouseSelectionAfterKeySelection()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
showOverlay();
|
||||
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected.Value);
|
||||
AddAssert("Second button selected", () => secondButton.Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1)));
|
||||
AddAssert("First button not selected", () => !getButton(0).Selected.Value);
|
||||
AddAssert("Second button selected", () => getButton(1).Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing a key after selecting a button with a hover event correctly selects a new button and deselects the previous button.
|
||||
/// </summary>
|
||||
private void testKeySelectionAfterMouseSelection()
|
||||
[Test]
|
||||
public void TestKeySelectionAfterMouseSelection()
|
||||
{
|
||||
AddStep("Show overlay", () =>
|
||||
{
|
||||
pauseOverlay.Show();
|
||||
InputManager.MoveMouseTo(Vector2.Zero);
|
||||
});
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1)));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Second button not selected", () => !secondButton.Selected.Value);
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
AddAssert("Second button not selected", () => !getButton(1).Selected.Value);
|
||||
AddAssert("First button selected", () => getButton(0).Selected.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that deselecting with the mouse by losing hover will reset the overlay to the initial state.
|
||||
/// </summary>
|
||||
private void testMouseDeselectionResets()
|
||||
[Test]
|
||||
public void TestMouseDeselectionResets()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
showOverlay();
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(getButton(1)));
|
||||
AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); // Initial state condition
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
AddAssert("First button selected", () => getButton(0).Selected.Value); // Initial state condition
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that clicking on a button correctly causes a click event for that button.
|
||||
/// </summary>
|
||||
private void testClickSelection()
|
||||
[Test]
|
||||
public void TestClickSelection()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
var retryButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
showOverlay();
|
||||
|
||||
bool triggered = false;
|
||||
AddStep("Click retry button", () =>
|
||||
@ -232,7 +226,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
var lastAction = pauseOverlay.OnRetry;
|
||||
pauseOverlay.OnRetry = () => triggered = true;
|
||||
|
||||
retryButton.Click();
|
||||
getButton(1).Click();
|
||||
pauseOverlay.OnRetry = lastAction;
|
||||
});
|
||||
|
||||
@ -243,9 +237,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
/// <summary>
|
||||
/// Tests that pressing the enter key with a button selected correctly causes a click event for that button.
|
||||
/// </summary>
|
||||
private void testEnterKeySelection()
|
||||
[Test]
|
||||
public void TestEnterKeySelection()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
showOverlay();
|
||||
|
||||
AddStep("Select second button", () =>
|
||||
{
|
||||
@ -275,6 +270,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
private void showOverlay() => AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
private DialogButton getButton(int index) => pauseOverlay.Buttons.Skip(index).First();
|
||||
|
||||
private void press(Key key)
|
||||
{
|
||||
InputManager.PressKey(key);
|
||||
|
@ -17,6 +17,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
private bool exitAction;
|
||||
|
||||
protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
|
@ -200,10 +200,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestDrawableHitObject : DrawableHitObject<HitObject>
|
||||
@ -216,10 +212,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
AddInternal(new Box { Size = new Vector2(75) });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,13 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Skinning;
|
||||
@ -27,7 +29,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
AddStep("setup layout larger source", () =>
|
||||
{
|
||||
Child = new LocalSkinOverrideContainer(new SizedSource(50))
|
||||
Child = new SkinProvidingContainer(new SizedSource(50))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = fill = new FillFlowContainer<ExposedSkinnableDrawable>
|
||||
@ -59,7 +61,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
AddStep("setup layout larger source", () =>
|
||||
{
|
||||
Child = new LocalSkinOverrideContainer(new SizedSource(30))
|
||||
Child = new SkinProvidingContainer(new SizedSource(30))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = fill = new FillFlowContainer<ExposedSkinnableDrawable>
|
||||
@ -95,7 +97,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Child = new SkinSourceContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new LocalSkinOverrideContainer(secondarySource)
|
||||
Child = new SkinProvidingContainer(secondarySource)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true)
|
||||
@ -120,7 +122,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Child = new SkinSourceContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = target = new LocalSkinOverrideContainer(secondarySource)
|
||||
Child = target = new SkinProvidingContainer(secondarySource)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
@ -132,12 +134,54 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchOff()
|
||||
{
|
||||
SkinConsumer consumer = null;
|
||||
SwitchableSkinProvidingContainer target = null;
|
||||
|
||||
AddStep("setup layout", () =>
|
||||
{
|
||||
Child = new SkinSourceContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = target = new SwitchableSkinProvidingContainer(new SecondarySource())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true)));
|
||||
AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox);
|
||||
AddStep("disable", () => target.Disable());
|
||||
AddAssert("consumer using base source", () => consumer.Drawable is BaseSourceBox);
|
||||
}
|
||||
|
||||
private class SwitchableSkinProvidingContainer : SkinProvidingContainer
|
||||
{
|
||||
private bool allow = true;
|
||||
|
||||
protected override bool AllowDrawableLookup(ISkinComponent component) => allow;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
allow = false;
|
||||
TriggerSourceChanged();
|
||||
}
|
||||
|
||||
public SwitchableSkinProvidingContainer(ISkin skin)
|
||||
: base(skin)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class ExposedSkinnableDrawable : SkinnableDrawable
|
||||
{
|
||||
public new Drawable Drawable => base.Drawable;
|
||||
|
||||
public ExposedSkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
||||
: base(name, defaultImplementation, allowFallback, confineMode)
|
||||
public ExposedSkinnableDrawable(string name, Func<ISkinComponent, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
||||
: base(new TestSkinComponent(name), defaultImplementation, allowFallback, confineMode)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -205,8 +249,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public new Drawable Drawable => base.Drawable;
|
||||
public int SkinChangedCount { get; private set; }
|
||||
|
||||
public SkinConsumer(string name, Func<string, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null)
|
||||
: base(name, defaultImplementation, allowFallback)
|
||||
public SkinConsumer(string name, Func<ISkinComponent, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null)
|
||||
: base(new TestSkinComponent(name), defaultImplementation, allowFallback)
|
||||
{
|
||||
}
|
||||
|
||||
@ -242,8 +286,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Drawable GetDrawableComponent(string componentName) =>
|
||||
componentName == "available"
|
||||
public Drawable GetDrawableComponent(ISkinComponent componentName) =>
|
||||
componentName.LookupName == "available"
|
||||
? new DrawWidthBox
|
||||
{
|
||||
Colour = Color4.Yellow,
|
||||
@ -253,31 +297,48 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||
|
||||
public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
|
||||
public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
|
||||
|
||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private class SecondarySource : ISkin
|
||||
{
|
||||
public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox();
|
||||
public Drawable GetDrawableComponent(ISkinComponent componentName) => new SecondarySourceBox();
|
||||
|
||||
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||
|
||||
public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
|
||||
public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
|
||||
|
||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private class SkinSourceContainer : Container, ISkin
|
||||
[Cached(typeof(ISkinSource))]
|
||||
private class SkinSourceContainer : Container, ISkinSource
|
||||
{
|
||||
public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox();
|
||||
public Drawable GetDrawableComponent(ISkinComponent componentName) => new BaseSourceBox();
|
||||
|
||||
public Texture GetTexture(string componentName) => throw new NotImplementedException();
|
||||
|
||||
public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
|
||||
public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
|
||||
|
||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
|
||||
|
||||
public event Action SourceChanged;
|
||||
}
|
||||
|
||||
private class TestSkinComponent : ISkinComponent
|
||||
{
|
||||
private readonly string name;
|
||||
|
||||
public TestSkinComponent(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public string ComponentGroup => string.Empty;
|
||||
|
||||
public string LookupName => name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,32 +21,38 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
private readonly Container<DrawableStoryboard> storyboardContainer;
|
||||
private DrawableStoryboard storyboard;
|
||||
|
||||
[Cached]
|
||||
private MusicController musicController = new MusicController();
|
||||
|
||||
public TestSceneStoryboard()
|
||||
{
|
||||
Clock = new FramedClock();
|
||||
|
||||
Add(new Container
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
musicController,
|
||||
new Container
|
||||
{
|
||||
new Box
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
storyboardContainer = new Container<DrawableStoryboard>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
storyboardContainer = new Container<DrawableStoryboard>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Add(new MusicController
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
State = { Value = Visibility.Visible },
|
||||
new NowPlayingOverlay
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
State = { Value = Visibility.Visible },
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("Restart", restart);
|
||||
|
15
osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs
Normal file
15
osu.Game.Tests/Visual/Menus/TestSceneIntroTriangles.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneIntroTriangles : IntroTestScene
|
||||
{
|
||||
protected override IScreen CreateScreen() => new IntroTriangles();
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
// 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.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Multi.Match.Components;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Audio;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
[Cached(typeof(IPreviewTrackOwner))]
|
||||
public class TestSceneMatchBeatmapPanel : MultiplayerTestScene, IPreviewTrackOwner
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(MatchBeatmapPanel)
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private PreviewTrackManager previewTrackManager { get; set; }
|
||||
|
||||
public TestSceneMatchBeatmapPanel()
|
||||
{
|
||||
Add(new MatchBeatmapPanel
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
|
||||
Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1763072 } });
|
||||
Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2101557 } });
|
||||
Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1973466 } });
|
||||
Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 2109801 } });
|
||||
Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { OnlineBeatmapID = 1922035 } });
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep("Select random beatmap", () =>
|
||||
{
|
||||
Room.CurrentItem.Value = Room.Playlist[RNG.Next(Room.Playlist.Count)];
|
||||
previewTrackManager.StopAnyPlaying(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
typeof(Info),
|
||||
typeof(HeaderButton),
|
||||
typeof(ReadyButton),
|
||||
typeof(ViewBeatmapButton)
|
||||
typeof(MatchBeatmapPanel)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -137,6 +137,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
|
||||
downloadAssert(true);
|
||||
|
||||
AddStep("show many difficulties", () => overlay.ShowBeatmapSet(createManyDifficultiesBeatmapSet()));
|
||||
downloadAssert(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -175,6 +178,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
HasVideo = true,
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
Language = new BeatmapSetOnlineLanguage { Id = 3, Name = "English" },
|
||||
Genre = new BeatmapSetOnlineGenre { Id = 4, Name = "Rock" },
|
||||
},
|
||||
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
@ -224,6 +229,56 @@ namespace osu.Game.Tests.Visual.Online
|
||||
AddStep(@"show without reload", overlay.Show);
|
||||
}
|
||||
|
||||
private BeatmapSetInfo createManyDifficultiesBeatmapSet()
|
||||
{
|
||||
var beatmaps = new List<BeatmapInfo>();
|
||||
|
||||
for (int i = 1; i < 41; i++)
|
||||
{
|
||||
beatmaps.Add(new BeatmapInfo
|
||||
{
|
||||
OnlineBeatmapID = i * 10,
|
||||
Version = $"Test #{i}",
|
||||
Ruleset = Ruleset.Value,
|
||||
StarDifficulty = 2 + i * 0.1,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
OverallDifficulty = 3.5f,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo(),
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(j => j % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(j => j % 12 - 6).ToArray(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 123,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"many difficulties beatmap",
|
||||
Artist = @"none",
|
||||
Author = new User
|
||||
{
|
||||
Username = @"BanchoBot",
|
||||
Id = 3,
|
||||
},
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Preview = @"https://b.ppy.sh/preview/123.mp3",
|
||||
HasVideo = true,
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
|
||||
Beatmaps = beatmaps,
|
||||
};
|
||||
}
|
||||
|
||||
private void downloadAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown);
|
||||
|
@ -127,6 +127,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- <Version 0>]", 1, true, expectedActions: LinkAction.OpenBeatmap);
|
||||
addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3,
|
||||
expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External });
|
||||
addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", 1, expectedActions: LinkAction.External);
|
||||
addMessageWithChecks("(Old link format with escaped (and \\( paired) parentheses)[https://osu.ppy.sh/home] and [[also a rogue wiki link]]", 2, expectedActions: new[] { LinkAction.External, LinkAction.External });
|
||||
// note that there's 0 links here (they get removed if a channel is not found)
|
||||
addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present).");
|
||||
addMessageWithChecks("I am important!", 0, false, true);
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
@ -24,7 +23,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(IconPill)
|
||||
};
|
||||
|
||||
private BeatmapSetInfo getUndownloadableBeatmapSet(RulesetInfo ruleset) => new BeatmapSetInfo
|
||||
private BeatmapSetInfo getUndownloadableBeatmapSet() => new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 123,
|
||||
Metadata = new BeatmapMetadata
|
||||
@ -56,23 +55,62 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
Ruleset = Ruleset.Value,
|
||||
Version = "Test",
|
||||
StarDifficulty = 6.42,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private BeatmapSetInfo getManyDifficultiesBeatmapSet(RulesetStore rulesets)
|
||||
{
|
||||
var ruleset = new OsuRuleset().RulesetInfo;
|
||||
var beatmaps = new List<BeatmapInfo>();
|
||||
|
||||
var normal = CreateWorkingBeatmap(ruleset).BeatmapSetInfo;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
beatmaps.Add(new BeatmapInfo
|
||||
{
|
||||
Ruleset = rulesets.GetRuleset(i % 4),
|
||||
StarDifficulty = 2 + i % 4 * 2,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
OverallDifficulty = 3.5f,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 1,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = "many difficulties beatmap",
|
||||
Artist = "test",
|
||||
Author = new User
|
||||
{
|
||||
Username = "BanchoBot",
|
||||
Id = 3,
|
||||
}
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
HasVideo = true,
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Beatmaps = beatmaps,
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
var normal = CreateWorkingBeatmap(Ruleset.Value).BeatmapSetInfo;
|
||||
normal.OnlineInfo.HasVideo = true;
|
||||
normal.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
var undownloadable = getUndownloadableBeatmapSet(ruleset);
|
||||
var undownloadable = getUndownloadableBeatmapSet();
|
||||
var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets);
|
||||
|
||||
Child = new BasicScrollContainer
|
||||
{
|
||||
@ -81,15 +119,17 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Direction = FillDirection.Full,
|
||||
Padding = new MarginPadding(20),
|
||||
Spacing = new Vector2(0, 20),
|
||||
Spacing = new Vector2(5, 20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DirectGridPanel(normal),
|
||||
new DirectListPanel(normal),
|
||||
new DirectGridPanel(undownloadable),
|
||||
new DirectGridPanel(manyDifficulties),
|
||||
new DirectListPanel(normal),
|
||||
new DirectListPanel(undownloadable),
|
||||
new DirectListPanel(manyDifficulties),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
246
osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs
Normal file
246
osu.Game.Tests/Visual/Online/TestSceneKudosuHistory.cs
Normal file
@ -0,0 +1,246 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Overlays.Profile.Sections.Kudosu;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneKudosuHistory : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(DrawableKudosuHistoryItem),
|
||||
};
|
||||
|
||||
private readonly Box background;
|
||||
|
||||
public TestSceneKudosuHistory()
|
||||
{
|
||||
FillFlowContainer<DrawableKudosuHistoryItem> content;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
content = new FillFlowContainer<DrawableKudosuHistoryItem>
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.7f,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
}
|
||||
});
|
||||
|
||||
items.ForEach(t => content.Add(new DrawableKudosuHistoryItem(t)));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
background.Colour = colours.GreySeafoam;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<APIKudosuHistory> items = new[]
|
||||
{
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 10,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2011, 11, 11)),
|
||||
Source = KudosuSource.DenyKudosu,
|
||||
Action = KudosuAction.Reset,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 1",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username1",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 5,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2012, 10, 11)),
|
||||
Source = KudosuSource.Forum,
|
||||
Action = KudosuAction.Give,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 2",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username2",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 8,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2013, 9, 11)),
|
||||
Source = KudosuSource.Forum,
|
||||
Action = KudosuAction.Reset,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 3",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username3",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 7,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2014, 8, 11)),
|
||||
Source = KudosuSource.Forum,
|
||||
Action = KudosuAction.Revoke,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 4",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username4",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 100,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2015, 7, 11)),
|
||||
Source = KudosuSource.Vote,
|
||||
Action = KudosuAction.Give,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 5",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username5",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 20,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)),
|
||||
Source = KudosuSource.Vote,
|
||||
Action = KudosuAction.Reset,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 6",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username6",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 11,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)),
|
||||
Source = KudosuSource.AllowKudosu,
|
||||
Action = KudosuAction.Give,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 7",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username7",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 24,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2014, 6, 11)),
|
||||
Source = KudosuSource.Delete,
|
||||
Action = KudosuAction.Reset,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 8",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username8",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 12,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2016, 6, 11)),
|
||||
Source = KudosuSource.Restore,
|
||||
Action = KudosuAction.Give,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 9",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username9",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 2,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2012, 6, 11)),
|
||||
Source = KudosuSource.Recalculate,
|
||||
Action = KudosuAction.Give,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 10",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username10",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
},
|
||||
new APIKudosuHistory
|
||||
{
|
||||
Amount = 32,
|
||||
CreatedAt = new DateTimeOffset(new DateTime(2019, 8, 11)),
|
||||
Source = KudosuSource.Recalculate,
|
||||
Action = KudosuAction.Reset,
|
||||
Post = new APIKudosuHistory.ModdingPost
|
||||
{
|
||||
Title = @"Random post 11",
|
||||
Url = @"https://osu.ppy.sh/b/1234",
|
||||
},
|
||||
Giver = new APIKudosuHistory.KudosuGiver
|
||||
{
|
||||
Username = @"Username11",
|
||||
Url = @"https://osu.ppy.sh/u/1234"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +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 osu.Game.Overlays.BeatmapSet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneLeaderboardScopeSelector : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(LeaderboardScopeSelector),
|
||||
};
|
||||
|
||||
public TestSceneLeaderboardScopeSelector()
|
||||
{
|
||||
Bindable<BeatmapLeaderboardScope> scope = new Bindable<BeatmapLeaderboardScope>();
|
||||
|
||||
Add(new LeaderboardScopeSelector
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Current = { BindTarget = scope }
|
||||
});
|
||||
|
||||
AddStep(@"Select global", () => scope.Value = BeatmapLeaderboardScope.Global);
|
||||
AddStep(@"Select country", () => scope.Value = BeatmapLeaderboardScope.Country);
|
||||
AddStep(@"Select friend", () => scope.Value = BeatmapLeaderboardScope.Friend);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -23,18 +25,25 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public TestSceneProfileRulesetSelector()
|
||||
{
|
||||
ProfileRulesetSelector selector;
|
||||
Bindable<User> user = new Bindable<User>();
|
||||
|
||||
Child = selector = new ProfileRulesetSelector
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
User = { BindTarget = user }
|
||||
};
|
||||
|
||||
AddStep("set osu! as default", () => selector.SetDefaultRuleset(new OsuRuleset().RulesetInfo));
|
||||
AddStep("set mania as default", () => selector.SetDefaultRuleset(new ManiaRuleset().RulesetInfo));
|
||||
AddStep("set taiko as default", () => selector.SetDefaultRuleset(new TaikoRuleset().RulesetInfo));
|
||||
AddStep("set catch as default", () => selector.SetDefaultRuleset(new CatchRuleset().RulesetInfo));
|
||||
AddStep("select default ruleset", selector.SelectDefaultRuleset);
|
||||
|
||||
AddStep("User with osu as default", () => user.Value = new User { PlayMode = "osu" });
|
||||
AddStep("User with mania as default", () => user.Value = new User { PlayMode = "mania" });
|
||||
AddStep("User with taiko as default", () => user.Value = new User { PlayMode = "taiko" });
|
||||
AddStep("User with catch as default", () => user.Value = new User { PlayMode = "fruits" });
|
||||
AddStep("null user", () => user.Value = null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,28 +69,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("null user", () => graph.User.Value = null);
|
||||
AddStep("null user", () => graph.Statistics.Value = null);
|
||||
AddStep("rank only", () =>
|
||||
{
|
||||
graph.User.Value = new User
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 123456 },
|
||||
PP = 12345,
|
||||
}
|
||||
Ranks = new UserStatistics.UserRanks { Global = 123456 },
|
||||
PP = 12345,
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("with rank history", () =>
|
||||
{
|
||||
graph.User.Value = new User
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
PP = 12345,
|
||||
},
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Data = data,
|
||||
@ -100,13 +94,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddStep("with zero values", () =>
|
||||
{
|
||||
graph.User.Value = new User
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
PP = 12345,
|
||||
},
|
||||
Ranks = new UserStatistics.UserRanks { Global = 89000 },
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Data = dataWithZeros,
|
||||
@ -116,13 +107,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddStep("small amount of data", () =>
|
||||
{
|
||||
graph.User.Value = new User
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
PP = 12345,
|
||||
},
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Data = smallData,
|
||||
@ -132,13 +120,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddStep("graph with edges", () =>
|
||||
{
|
||||
graph.User.Value = new User
|
||||
graph.Statistics.Value = new UserStatistics
|
||||
{
|
||||
Statistics = new UserStatistics
|
||||
{
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
PP = 12345,
|
||||
},
|
||||
Ranks = new UserStatistics.UserRanks { Global = 12000 },
|
||||
PP = 12345,
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Data = edgyData,
|
||||
|
@ -52,12 +52,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
Current = 727,
|
||||
Progress = 69,
|
||||
}
|
||||
},
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Mode = @"osu",
|
||||
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
|
||||
},
|
||||
RankHistory = new User.RankHistoryData
|
||||
{
|
||||
Mode = @"osu",
|
||||
Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
|
||||
},
|
||||
},
|
||||
Badges = new[]
|
||||
{
|
||||
|
@ -0,0 +1,69 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Profile.Header.Components;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneUserProfilePreviousUsernames : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(PreviousUsernames)
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
private readonly Bindable<User> user = new Bindable<User>();
|
||||
|
||||
public TestSceneUserProfilePreviousUsernames()
|
||||
{
|
||||
Child = new PreviousUsernames
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
User = { BindTarget = user },
|
||||
};
|
||||
|
||||
User[] users =
|
||||
{
|
||||
new User { PreviousUsernames = new[] { "username1" } },
|
||||
new User { PreviousUsernames = new[] { "longusername", "longerusername" } },
|
||||
new User { PreviousUsernames = new[] { "test", "angelsim", "verylongusername" } },
|
||||
new User { PreviousUsernames = new[] { "ihavenoidea", "howcani", "makethistext", "anylonger" } },
|
||||
new User { PreviousUsernames = new string[0] },
|
||||
null
|
||||
};
|
||||
|
||||
AddStep("single username", () => user.Value = users[0]);
|
||||
AddStep("two usernames", () => user.Value = users[1]);
|
||||
AddStep("three usernames", () => user.Value = users[2]);
|
||||
AddStep("four usernames", () => user.Value = users[3]);
|
||||
AddStep("no username", () => user.Value = users[4]);
|
||||
AddStep("null user", () => user.Value = users[5]);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep("online user (Angelsim)", () =>
|
||||
{
|
||||
var request = new GetUserRequest(1777162);
|
||||
request.Success += user => this.user.Value = user;
|
||||
api.Queue(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
109
osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs
Normal file
109
osu.Game.Tests/Visual/Online/TestSceneUserRequest.cs
Normal file
@ -0,0 +1,109 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneUserRequest : OsuTestScene
|
||||
{
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
private readonly Bindable<User> user = new Bindable<User>();
|
||||
private GetUserRequest request;
|
||||
private readonly DimmedLoadingLayer loading;
|
||||
|
||||
public TestSceneUserRequest()
|
||||
{
|
||||
Add(new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new UserTestContainer
|
||||
{
|
||||
User = { BindTarget = user }
|
||||
},
|
||||
loading = new DimmedLoadingLayer
|
||||
{
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep(@"local user", () => getUser());
|
||||
AddStep(@"local user with taiko ruleset", () => getUser(ruleset: new TaikoRuleset().RulesetInfo));
|
||||
AddStep(@"cookiezi", () => getUser(124493));
|
||||
AddStep(@"cookiezi with mania ruleset", () => getUser(124493, new ManiaRuleset().RulesetInfo));
|
||||
}
|
||||
|
||||
private void getUser(long? userId = null, RulesetInfo ruleset = null)
|
||||
{
|
||||
loading.Show();
|
||||
|
||||
request?.Cancel();
|
||||
request = new GetUserRequest(userId, ruleset);
|
||||
request.Success += user =>
|
||||
{
|
||||
this.user.Value = user;
|
||||
loading.Hide();
|
||||
};
|
||||
api.Queue(request);
|
||||
}
|
||||
|
||||
private class UserTestContainer : FillFlowContainer
|
||||
{
|
||||
public readonly Bindable<User> User = new Bindable<User>();
|
||||
|
||||
public UserTestContainer()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Vertical;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
User.BindValueChanged(onUserUpdate, true);
|
||||
}
|
||||
|
||||
private void onUserUpdate(ValueChangedEvent<User> user)
|
||||
{
|
||||
Clear();
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
new SpriteText
|
||||
{
|
||||
Text = $@"Username: {user.NewValue?.Username}"
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = $@"RankedScore: {user.NewValue?.Statistics.RankedScore}"
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -516,6 +516,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
OnlineBeatmapID = b * 10,
|
||||
Path = $"extra{b}.osu",
|
||||
Version = $"Extra {b}",
|
||||
Ruleset = rulesets.GetRuleset((b - 1) % 4),
|
||||
StarDifficulty = 2,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
|
@ -15,6 +15,7 @@ using osu.Framework.MathUtils;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@ -79,8 +80,12 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default));
|
||||
|
||||
Beatmap.SetDefault();
|
||||
|
||||
Dependencies.Cache(config = new OsuConfigManager(LocalStorage));
|
||||
}
|
||||
|
||||
private OsuConfigManager config;
|
||||
|
||||
[SetUp]
|
||||
public virtual void SetUp() => Schedule(() =>
|
||||
{
|
||||
@ -111,13 +116,15 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
|
||||
|
||||
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
|
||||
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
|
||||
AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; });
|
||||
AddStep(@"Sort by DateAdded", delegate { songSelect.FilterControl.Sort = SortMode.DateAdded; });
|
||||
AddStep(@"Sort by BPM", delegate { songSelect.FilterControl.Sort = SortMode.BPM; });
|
||||
AddStep(@"Sort by Length", delegate { songSelect.FilterControl.Sort = SortMode.Length; });
|
||||
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
|
||||
var sortMode = config.GetBindable<SortMode>(OsuSetting.SongSelectSortingMode);
|
||||
|
||||
AddStep(@"Sort by Artist", delegate { sortMode.Value = SortMode.Artist; });
|
||||
AddStep(@"Sort by Title", delegate { sortMode.Value = SortMode.Title; });
|
||||
AddStep(@"Sort by Author", delegate { sortMode.Value = SortMode.Author; });
|
||||
AddStep(@"Sort by DateAdded", delegate { sortMode.Value = SortMode.DateAdded; });
|
||||
AddStep(@"Sort by BPM", delegate { sortMode.Value = SortMode.BPM; });
|
||||
AddStep(@"Sort by Length", delegate { sortMode.Value = SortMode.Length; });
|
||||
AddStep(@"Sort by Difficulty", delegate { sortMode.Value = SortMode.Difficulty; });
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -2,7 +2,9 @@
|
||||
// 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.Track;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -22,30 +24,41 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[TestFixture]
|
||||
public class TestSceneBeatSyncedContainer : OsuTestScene
|
||||
{
|
||||
private readonly MusicController mc;
|
||||
private readonly NowPlayingOverlay np;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(BeatSyncedContainer)
|
||||
};
|
||||
|
||||
[Cached]
|
||||
private MusicController musicController = new MusicController();
|
||||
|
||||
public TestSceneBeatSyncedContainer()
|
||||
{
|
||||
Clock = new FramedClock();
|
||||
Clock.ProcessFrame();
|
||||
|
||||
Add(new BeatContainer
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
});
|
||||
|
||||
Add(mc = new MusicController
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
musicController,
|
||||
new BeatContainer
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
},
|
||||
np = new NowPlayingOverlay
|
||||
{
|
||||
Origin = Anchor.TopRight,
|
||||
Anchor = Anchor.TopRight,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
mc.ToggleVisibility();
|
||||
np.ToggleVisibility();
|
||||
}
|
||||
|
||||
private class BeatContainer : BeatSyncedContainer
|
||||
@ -147,7 +160,9 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
if (timingPoints[timingPoints.Count - 1] == current)
|
||||
return current;
|
||||
|
||||
return timingPoints[timingPoints.IndexOf(current) + 1];
|
||||
int index = timingPoints.IndexOf(current); // -1 means that this is a "default beat"
|
||||
|
||||
return index == -1 ? current : timingPoints[index + 1];
|
||||
}
|
||||
|
||||
private int calculateBeatCount(TimingControlPoint current)
|
||||
|
@ -249,7 +249,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Size = new Vector2(50);
|
||||
Masking = true;
|
||||
|
||||
Blending = BlendingMode.Additive;
|
||||
Blending = BlendingParameters.Additive;
|
||||
Alpha = 0.5f;
|
||||
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both };
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
@ -12,7 +13,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneHoldToConfirmOverlay : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ExitConfirmOverlay) };
|
||||
protected override double TimePerAction => 100; // required for the early exit test, since hold-to-confirm delay is 200ms
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ExitConfirmOverlay),
|
||||
typeof(HoldToConfirmContainer),
|
||||
};
|
||||
|
||||
public TestSceneHoldToConfirmOverlay()
|
||||
{
|
||||
|
@ -82,14 +82,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
var easierMods = instance.GetModsFor(ModType.DifficultyReduction);
|
||||
var harderMods = instance.GetModsFor(ModType.DifficultyIncrease);
|
||||
var assistMods = instance.GetModsFor(ModType.Automation);
|
||||
|
||||
var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail);
|
||||
var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden);
|
||||
|
||||
var doubleTimeMod = harderMods.OfType<MultiMod>().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime));
|
||||
|
||||
var autoPilotMod = assistMods.FirstOrDefault(m => m is OsuModAutopilot);
|
||||
var spunOutMod = easierMods.FirstOrDefault(m => m is OsuModSpunOut);
|
||||
|
||||
var easy = easierMods.FirstOrDefault(m => m is OsuModEasy);
|
||||
var hardRock = harderMods.FirstOrDefault(m => m is OsuModHardRock);
|
||||
@ -101,7 +100,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour);
|
||||
testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour);
|
||||
|
||||
testUnimplementedMod(autoPilotMod);
|
||||
testUnimplementedMod(spunOutMod);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -2,6 +2,7 @@
|
||||
// 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.Framework.Timing;
|
||||
using osu.Game.Overlays;
|
||||
@ -9,22 +10,27 @@ using osu.Game.Overlays;
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneMusicController : OsuTestScene
|
||||
public class TestSceneNowPlayingOverlay : OsuTestScene
|
||||
{
|
||||
public TestSceneMusicController()
|
||||
[Cached]
|
||||
private MusicController musicController = new MusicController();
|
||||
|
||||
public TestSceneNowPlayingOverlay()
|
||||
{
|
||||
Clock = new FramedClock();
|
||||
|
||||
var mc = new MusicController
|
||||
var np = new NowPlayingOverlay
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre
|
||||
};
|
||||
Add(mc);
|
||||
|
||||
AddStep(@"show", () => mc.Show());
|
||||
Add(musicController);
|
||||
Add(np);
|
||||
|
||||
AddStep(@"show", () => np.Show());
|
||||
AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state);
|
||||
AddStep(@"show", () => mc.Hide());
|
||||
AddStep(@"show", () => np.Hide());
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ using osu.Framework.Configuration;
|
||||
using osu.Framework.Configuration.Tracking;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.OSD;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
@ -22,6 +23,12 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
osd.BeginTracking(this, config);
|
||||
Add(osd);
|
||||
|
||||
AddStep("Display empty osd toast", () => osd.Display(new EmptyToast()));
|
||||
AddAssert("Toast width is 240", () => osd.Child.Width == 240);
|
||||
|
||||
AddStep("Display toast with lengthy text", () => osd.Display(new LengthyToast()));
|
||||
AddAssert("Toast width is greater than 240", () => osd.Child.Width > 240);
|
||||
|
||||
AddRepeatStep("Change toggle (no bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingNoKeybind), 2);
|
||||
AddRepeatStep("Change toggle (with bind)", () => config.ToggleSetting(TestConfigSetting.ToggleSettingWithKeybind), 2);
|
||||
AddRepeatStep("Change enum (no bind)", () => config.IncrementEnumSetting(TestConfigSetting.EnumSettingNoKeybind), 3);
|
||||
@ -86,6 +93,22 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
Setting4
|
||||
}
|
||||
|
||||
private class EmptyToast : Toast
|
||||
{
|
||||
public EmptyToast()
|
||||
: base("", "", "")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class LengthyToast : Toast
|
||||
{
|
||||
public LengthyToast()
|
||||
: base("Toast with a very very very long text", "A very very very very very very long text also", "A very very very very very long shortcut")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestOnScreenDisplay : OnScreenDisplay
|
||||
{
|
||||
protected override void DisplayTemporarily(Drawable toDisplay) => toDisplay.FadeIn().ResizeHeightTo(110);
|
||||
|
@ -5,7 +5,7 @@
|
||||
<PackageReference Include="DeepEqual" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
|
Reference in New Issue
Block a user