mirror of
https://github.com/ppy/osu.git
synced 2026-06-05 16:24:13 +08:00
Compare commits
294 Commits
+1
-1
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.108.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.303.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -146,9 +146,13 @@ namespace osu.Desktop
|
||||
{
|
||||
base.SetHost(host);
|
||||
|
||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||
if (iconStream != null)
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
// Apple operating systems use a better icon provided via external assets.
|
||||
if (!RuntimeInfo.IsApple)
|
||||
{
|
||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||
if (iconStream != null)
|
||||
host.Window.SetIconFromStream(iconStream);
|
||||
}
|
||||
|
||||
host.Window.Title = Name;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using BenchmarkDotNet.Attributes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Tests.NonVisual.Filtering;
|
||||
|
||||
namespace osu.Game.Benchmarks
|
||||
{
|
||||
@@ -42,7 +42,7 @@ namespace osu.Game.Benchmarks
|
||||
Status = BeatmapOnlineStatus.Loved
|
||||
};
|
||||
|
||||
private CarouselBeatmap carouselBeatmap = null!;
|
||||
private FilterMatchingTest.CarouselBeatmap carouselBeatmap = null!;
|
||||
private FilterCriteria criteria1 = null!;
|
||||
private FilterCriteria criteria2 = null!;
|
||||
private FilterCriteria criteria3 = null!;
|
||||
@@ -55,7 +55,7 @@ namespace osu.Game.Benchmarks
|
||||
var beatmap = getExampleBeatmap();
|
||||
beatmap.OnlineID = 20201010;
|
||||
beatmap.BeatmapSet = new BeatmapSetInfo { OnlineID = 1535 };
|
||||
carouselBeatmap = new CarouselBeatmap(beatmap);
|
||||
carouselBeatmap = new FilterMatchingTest.CarouselBeatmap(beatmap);
|
||||
criteria1 = new FilterCriteria();
|
||||
criteria2 = new FilterCriteria
|
||||
{
|
||||
|
||||
@@ -35,11 +35,9 @@
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
</plist>
|
||||
|
||||
@@ -176,15 +176,20 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.LargeTickMiss,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.SmallTickMiss,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,9 @@
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
</plist>
|
||||
|
||||
@@ -383,7 +383,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v);
|
||||
}
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
@@ -392,9 +392,11 @@ namespace osu.Game.Rulesets.Mania
|
||||
HitResult.Good,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
HitResult.Miss,
|
||||
|
||||
// HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as
|
||||
// it would be a bit redundant to show this to the user.
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.ComboBreak,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
@@ -31,47 +31,45 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsEnumDropdown<ManiaScrollingDirection>
|
||||
new SettingsItemV2(new FormEnumDropdown<ManiaScrollingDirection>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.ScrollingDirection,
|
||||
Caption = RulesetSettingsStrings.ScrollingDirection,
|
||||
Current = config.GetBindable<ManiaScrollingDirection>(ManiaRulesetSetting.ScrollDirection)
|
||||
},
|
||||
new SettingsSlider<double, ManiaScrollSlider>
|
||||
}),
|
||||
new SettingsItemV2(new FormSliderBar<double>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.ScrollSpeed,
|
||||
Caption = RulesetSettingsStrings.ScrollSpeed,
|
||||
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollSpeed),
|
||||
KeyboardStep = 1
|
||||
},
|
||||
new SettingsCheckbox
|
||||
KeyboardStep = 1,
|
||||
LabelFormat = v => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(v), v),
|
||||
}),
|
||||
new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
Caption = RulesetSettingsStrings.TimingBasedColouring,
|
||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TimingBasedNoteColouring),
|
||||
})
|
||||
{
|
||||
Keywords = new[] { "color" },
|
||||
LabelText = RulesetSettingsStrings.TimingBasedColouring,
|
||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TimingBasedNoteColouring),
|
||||
},
|
||||
};
|
||||
|
||||
Add(new SettingsCheckbox
|
||||
Add(new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.TouchOverlay,
|
||||
Caption = RulesetSettingsStrings.TouchOverlay,
|
||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TouchOverlay)
|
||||
});
|
||||
}));
|
||||
|
||||
if (RuntimeInfo.IsMobile)
|
||||
{
|
||||
Add(new SettingsEnumDropdown<ManiaMobileLayout>
|
||||
Add(new SettingsItemV2(new FormEnumDropdown<ManiaMobileLayout>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.MobileLayout,
|
||||
Caption = RulesetSettingsStrings.MobileLayout,
|
||||
Current = config.GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout),
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
Items = Enum.GetValues<ManiaMobileLayout>().Where(l => l != ManiaMobileLayout.LandscapeWithOverlay),
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private partial class ManiaScrollSlider : RoundedSliderBar<double>
|
||||
{
|
||||
public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
var hitWindows = new ManiaHitWindows();
|
||||
|
||||
AddInternal(judgementPooler = new JudgementPooler<DrawableManiaJudgement>(Enum.GetValues<HitResult>().Where(r => hitWindows.IsHitResultAllowed(r))));
|
||||
AddInternal(judgementPooler = new JudgementPooler<DrawableManiaJudgement>(Enum.GetValues<HitResult>().Where(hitWindows.IsHitResultAllowed)));
|
||||
|
||||
RegisterPool<BarLine, DrawableBarLine>(50, 200);
|
||||
}
|
||||
|
||||
@@ -35,11 +35,9 @@
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
</plist>
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
@@ -30,6 +33,16 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
PathType.LINEAR,
|
||||
new Vector2(100, 0),
|
||||
new Vector2(100, 100)
|
||||
),
|
||||
createPathSegment(
|
||||
PathType.PERFECT_CURVE,
|
||||
new Vector2(100.009f, -50.0009f),
|
||||
new Vector2(200.0089f, -100)
|
||||
),
|
||||
createPathSegment(
|
||||
PathType.PERFECT_CURVE,
|
||||
new Vector2(25, -50),
|
||||
new Vector2(100, 75)
|
||||
)
|
||||
};
|
||||
|
||||
@@ -48,9 +61,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
|
||||
[TestCase(0, 250)]
|
||||
[TestCase(0, 200)]
|
||||
[TestCase(1, 120)]
|
||||
[TestCase(1, 80)]
|
||||
public void TestSliderReversal(int pathIndex, double length)
|
||||
[TestCase(1, 120, false, false)]
|
||||
[TestCase(1, 80, false, false)]
|
||||
[TestCase(2, 250)]
|
||||
[TestCase(2, 190)]
|
||||
[TestCase(3, 250)]
|
||||
[TestCase(3, 190)]
|
||||
public void TestSliderReversal(int pathIndex, double length, bool assertEqualDistances = true, bool assertSliderReduction = true)
|
||||
{
|
||||
var controlPoints = paths[pathIndex];
|
||||
|
||||
@@ -90,6 +107,215 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
InputManager.ReleaseKey(Key.LControl);
|
||||
});
|
||||
|
||||
if (pathIndex == 2)
|
||||
{
|
||||
AddRepeatStep("Reverse slider again", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.LControl);
|
||||
InputManager.Key(Key.G);
|
||||
InputManager.ReleaseKey(Key.LControl);
|
||||
}, 2);
|
||||
}
|
||||
|
||||
if (assertEqualDistances)
|
||||
{
|
||||
AddAssert("Middle control point has the same distance from start to end", () =>
|
||||
{
|
||||
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[0].Position);
|
||||
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||
|
||||
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||
});
|
||||
}
|
||||
|
||||
AddAssert("Middle control point is not at start or end", () =>
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldStartPos) > 1 &&
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldEndPos) > 1
|
||||
);
|
||||
|
||||
AddAssert("Slider has correct length", () =>
|
||||
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||
|
||||
AddAssert("Slider has correct start position", () =>
|
||||
Vector2.Distance(selectedSlider.Position, oldEndPos) < 1);
|
||||
|
||||
AddAssert("Slider has correct end position", () =>
|
||||
Vector2.Distance(selectedSlider.EndPosition, oldStartPos) < 1);
|
||||
|
||||
AddAssert("Control points have correct types", () =>
|
||||
{
|
||||
var newControlPointTypes = selectedSlider.Path.ControlPoints.Select(p => p.Type).ToArray();
|
||||
|
||||
return oldControlPointTypes.Take(newControlPointTypes.Length).SequenceEqual(newControlPointTypes);
|
||||
});
|
||||
|
||||
if (assertSliderReduction)
|
||||
{
|
||||
AddStep("Move to marker", () =>
|
||||
{
|
||||
var marker = this.ChildrenOfType<SliderEndDragMarker>().Single();
|
||||
var markerPos = (marker.ScreenSpaceDrawQuad.TopRight + marker.ScreenSpaceDrawQuad.BottomRight) / 2;
|
||||
// sometimes the cursor may miss the marker's hitbox so we
|
||||
// add a little offset here to be sure it lands in a clickable position.
|
||||
var position = new Vector2(markerPos.X + 2f, markerPos.Y);
|
||||
InputManager.MoveMouseTo(position);
|
||||
});
|
||||
AddStep("Click", () => InputManager.PressButton(MouseButton.Left));
|
||||
AddStep("Reduce slider", () =>
|
||||
{
|
||||
var middleControlPoint = this.ChildrenOfType<PathControlPointPiece<Slider>>().ToArray()[^2];
|
||||
InputManager.MoveMouseTo(middleControlPoint);
|
||||
});
|
||||
AddStep("Release click", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
|
||||
AddStep("Save half slider info", () =>
|
||||
{
|
||||
oldStartPos = selectedSlider.Position;
|
||||
oldEndPos = selectedSlider.EndPosition;
|
||||
oldDistance = selectedSlider.Path.Distance;
|
||||
});
|
||||
|
||||
AddStep("Reverse slider", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.LControl);
|
||||
InputManager.Key(Key.G);
|
||||
InputManager.ReleaseKey(Key.LControl);
|
||||
});
|
||||
|
||||
AddAssert("Middle control point has the same distance from start to end", () =>
|
||||
{
|
||||
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[0].Position);
|
||||
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||
|
||||
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||
});
|
||||
|
||||
AddAssert("Middle control point is not at start or end", () =>
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldStartPos) > 1 &&
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldEndPos) > 1
|
||||
);
|
||||
|
||||
AddAssert("Slider has correct length", () =>
|
||||
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||
|
||||
AddAssert("Slider has correct start position", () =>
|
||||
Vector2.Distance(selectedSlider.Position, oldEndPos) < 1);
|
||||
|
||||
AddAssert("Slider has correct end position", () =>
|
||||
Vector2.Distance(selectedSlider.EndPosition, oldStartPos) < 1);
|
||||
|
||||
AddAssert("Control points have correct types", () =>
|
||||
{
|
||||
var newControlPointTypes = selectedSlider.Path.ControlPoints.Select(p => p.Type).ToArray();
|
||||
|
||||
return oldControlPointTypes.Take(newControlPointTypes.Length).SequenceEqual(newControlPointTypes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSegmentedSliderReversal()
|
||||
{
|
||||
PathControlPoint[] segmentedSliderPath =
|
||||
[
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(0, 0),
|
||||
Type = PathType.PERFECT_CURVE
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(100, 150),
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(75, -50),
|
||||
Type = PathType.PERFECT_CURVE
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(225, -75),
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(350, 50),
|
||||
Type = PathType.PERFECT_CURVE
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(500, -75),
|
||||
},
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = new Vector2(350, -120),
|
||||
},
|
||||
];
|
||||
|
||||
Vector2 oldStartPos = default;
|
||||
Vector2 oldEndPos = default;
|
||||
double oldDistance = default;
|
||||
|
||||
var oldControlPointTypes = segmentedSliderPath.Select(p => p.Type);
|
||||
|
||||
AddStep("Add slider", () =>
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
Position = new Vector2(0, 200),
|
||||
Path = new SliderPath(segmentedSliderPath)
|
||||
{
|
||||
ExpectedDistance = { Value = 1314 }
|
||||
}
|
||||
};
|
||||
|
||||
EditorBeatmap.Add(slider);
|
||||
|
||||
oldStartPos = slider.Position;
|
||||
oldEndPos = slider.EndPosition;
|
||||
oldDistance = slider.Path.Distance;
|
||||
});
|
||||
|
||||
AddStep("Select slider", () =>
|
||||
{
|
||||
var slider = (Slider)EditorBeatmap.HitObjects[0];
|
||||
EditorBeatmap.SelectedHitObjects.Add(slider);
|
||||
});
|
||||
|
||||
AddRepeatStep("Reverse slider", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.LControl);
|
||||
InputManager.Key(Key.G);
|
||||
InputManager.ReleaseKey(Key.LControl);
|
||||
}, 3);
|
||||
|
||||
AddAssert("First arc's control is not at the slider's middle", () =>
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, selectedSlider.Path.PositionAt(0.5)) > 1
|
||||
);
|
||||
|
||||
AddAssert("Last arc's control is not at the slider's middle", () =>
|
||||
Vector2.Distance(selectedSlider.Path.ControlPoints[1].Position, selectedSlider.Path.PositionAt(0.5)) > 1
|
||||
);
|
||||
|
||||
AddAssert("First arc centered middle control point", () =>
|
||||
{
|
||||
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||
float middleToStart = Vector2.Distance(pathControlPoints[1].Position, pathControlPoints[0].Position);
|
||||
float middleToEnd = Vector2.Distance(pathControlPoints[1].Position, pathControlPoints[2].Position);
|
||||
|
||||
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||
});
|
||||
|
||||
AddAssert("Last arc centered middle control point", () =>
|
||||
{
|
||||
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^3].Position);
|
||||
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||
|
||||
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||
});
|
||||
|
||||
AddAssert("Slider has correct length", () =>
|
||||
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public partial class TestSceneOsuModEasy : OsuModTestScene
|
||||
{
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
[Test]
|
||||
public void TestMultipleApplication()
|
||||
{
|
||||
bool reapplied = false;
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mods = [new OsuModEasy { Retries = { Value = 1 } }],
|
||||
Autoplay = false,
|
||||
CreateBeatmap = () =>
|
||||
{
|
||||
// do stuff to speed up fails
|
||||
var b = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||
{
|
||||
Difficulty = { DrainRate = 10 }
|
||||
};
|
||||
|
||||
foreach (var ho in b.HitObjects)
|
||||
ho.StartTime /= 4;
|
||||
|
||||
return b;
|
||||
},
|
||||
PassCondition = () =>
|
||||
{
|
||||
if (((ModEasyTestPlayer)Player).FailuresSuppressed > 0 && !reapplied)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var mod in Player.GameplayState.Mods.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(new BeatmapDifficulty());
|
||||
|
||||
foreach (var mod in Player.GameplayState.Mods.OfType<IApplicableToPlayer>())
|
||||
mod.ApplyToPlayer(Player);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// don't care if this fails. in fact a failure here is probably better than the alternative.
|
||||
}
|
||||
finally
|
||||
{
|
||||
reapplied = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Player.GameplayState.HasFailed && ((ModEasyTestPlayer)Player).FailuresSuppressed <= 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new ModEasyTestPlayer(CurrentTestData, AllowFail);
|
||||
|
||||
private partial class ModEasyTestPlayer : ModTestPlayer
|
||||
{
|
||||
public int FailuresSuppressed { get; private set; }
|
||||
|
||||
public ModEasyTestPlayer(ModTestData data, bool allowFail)
|
||||
: base(data, allowFail)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool CheckModsAllowFailure()
|
||||
{
|
||||
bool failureAllowed = GameplayState.Mods.OfType<IApplicableFailOverride>().All(m => m.PerformFail());
|
||||
|
||||
if (!failureAllowed)
|
||||
FailuresSuppressed++;
|
||||
|
||||
return failureAllowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
Debug.Assert(drawableHitObject.HitObject.HitWindows != null);
|
||||
|
||||
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.WindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
|
||||
scheduledTasks.Add(Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay));
|
||||
scheduledTasks.Add(Scheduler.AddDelayed(drawableHitObject.TriggerJudgement, delay));
|
||||
|
||||
return drawableHitObject;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Utils;
|
||||
@@ -37,13 +38,16 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
[Resolved]
|
||||
private IEditorChangeHandler? changeHandler { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap editorBeatmap { get; set; } = null!;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IDistanceSnapProvider? snapProvider { get; set; }
|
||||
|
||||
private BindableList<HitObject> selectedItems { get; } = new BindableList<HitObject>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(EditorBeatmap editorBeatmap)
|
||||
private void load()
|
||||
{
|
||||
selectedItems.BindTo(editorBeatmap.SelectedHitObjects);
|
||||
}
|
||||
@@ -53,15 +57,22 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
base.LoadComplete();
|
||||
|
||||
selectedItems.CollectionChanged += (_, __) => updateState();
|
||||
editorBeatmap.HitObjectUpdated += hitObjectUpdated;
|
||||
updateState();
|
||||
}
|
||||
|
||||
private void hitObjectUpdated(HitObject hitObject)
|
||||
{
|
||||
if (selectedMovableObjects.Contains(hitObject))
|
||||
updateState();
|
||||
}
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
var quad = GeometryUtils.GetSurroundingQuad(selectedMovableObjects);
|
||||
|
||||
CanScaleX.Value = quad.Width > 0;
|
||||
CanScaleY.Value = quad.Height > 0;
|
||||
CanScaleX.Value = Precision.DefinitelyBigger(quad.Width, 0);
|
||||
CanScaleY.Value = Precision.DefinitelyBigger(quad.Height, 0);
|
||||
CanScaleDiagonally.Value = CanScaleX.Value && CanScaleY.Value;
|
||||
CanScaleFromPlayfieldOrigin.Value = selectedMovableObjects.Any();
|
||||
IsScalingSlider.Value = selectedMovableObjects.Count() == 1 && selectedMovableObjects.First() is Slider;
|
||||
@@ -339,5 +350,13 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
PathControlPointTypes = (hitObject as IHasPath)?.Path.ControlPoints.Select(p => p.Type).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (editorBeatmap.IsNotNull())
|
||||
editorBeatmap.HitObjectUpdated -= hitObjectUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
[SettingSource(
|
||||
"Max size at combo",
|
||||
"The combo count at which the cursor reaches its maximum size",
|
||||
SettingControlType = typeof(SettingsSlider<int, RoundedSliderBar<int>>)
|
||||
SettingControlType = typeof(SettingsSlider<int, MaxSizeComboSlider>)
|
||||
)]
|
||||
public BindableInt MaxSizeComboCount { get; } = new BindableInt(50)
|
||||
{
|
||||
@@ -85,4 +85,12 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
cursor.ModScaleAdjust.Value = (float)Interpolation.Lerp(cursor.ModScaleAdjust.Value, currentSize, Math.Clamp(cursor.Time.Elapsed / TRANSITION_DURATION, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MaxSizeComboSlider : RoundedSliderBar<int>
|
||||
{
|
||||
public MaxSizeComboSlider()
|
||||
{
|
||||
KeyboardStep = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
@@ -71,6 +73,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
}
|
||||
}
|
||||
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModTargetPractice)).ToArray();
|
||||
|
||||
protected override void ApplySettings(BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplySettings(difficulty);
|
||||
|
||||
@@ -27,8 +27,10 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override LocalisableString Description => "Burn the notes into your memory.";
|
||||
|
||||
//Alters the transforms of the approach circles, breaking the effects of these mods.
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModApproachDifferent), typeof(OsuModTransform), typeof(OsuModDepth) }).ToArray();
|
||||
/// <remarks>
|
||||
/// Incompatible with all mods that directly modify or indirectly depend on <see cref="OsuHitObject.TimePreempt"/>, or alter the behaviour of approach circles.
|
||||
/// </remarks>
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModApproachDifferent), typeof(OsuModTransform), typeof(OsuModDepth), typeof(OsuModHidden) }).ToArray();
|
||||
|
||||
public override ModType Type => ModType.Fun;
|
||||
|
||||
@@ -60,14 +62,22 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
if (osuObject is not Spinner)
|
||||
osuObject.TimePreempt += osuObject.StartTime - lastNewComboTime;
|
||||
|
||||
int repeatCount = 0;
|
||||
|
||||
foreach (var nested in osuObject.NestedHitObjects.OfType<OsuHitObject>())
|
||||
{
|
||||
switch (nested)
|
||||
{
|
||||
//Freezing the SliderTicks doesnt play well with snaking sliders
|
||||
// Freezing the SliderTicks doesnt play well with snaking sliders
|
||||
case SliderTick:
|
||||
//SliderRepeat wont layer correctly if preempt is changed.
|
||||
break;
|
||||
|
||||
case SliderRepeat:
|
||||
if (repeatCount > 2)
|
||||
break;
|
||||
|
||||
applyFadeInAdjustment(nested);
|
||||
repeatCount++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override LocalisableString Description => @"Play with no approach circles and fading circles/sliders.";
|
||||
public override double ScoreMultiplier => UsesDefaultConfiguration ? 1.06 : 1;
|
||||
|
||||
public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn), typeof(OsuModDepth) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(IRequiresApproachCircles), typeof(OsuModSpinIn), typeof(OsuModDepth), typeof(OsuModFreezeFrame) };
|
||||
|
||||
public const double FADE_IN_DURATION_MULTIPLIER = 0.4;
|
||||
public const double FADE_OUT_DURATION_MULTIPLIER = 0.3;
|
||||
|
||||
@@ -48,7 +48,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
typeof(OsuModSpunOut),
|
||||
typeof(OsuModStrictTracking),
|
||||
typeof(OsuModSuddenDeath),
|
||||
typeof(OsuModDepth)
|
||||
typeof(OsuModDepth),
|
||||
typeof(OsuModDifficultyAdjust),
|
||||
}).ToArray();
|
||||
|
||||
[SettingSource("Seed", "Use a custom seed instead of a random one", SettingControlType = typeof(SettingsNumberBox))]
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override string Name => "Traceable";
|
||||
public override string Acronym => "TC";
|
||||
public override IconUsage? Icon => OsuIcon.ModTraceable;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
public override LocalisableString Description => "Put your faith in the approach circles...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModHardRock(),
|
||||
new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()),
|
||||
new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()),
|
||||
new OsuModHidden(),
|
||||
new MultiMod(new OsuModHidden(), new OsuModTraceable()),
|
||||
new MultiMod(new OsuModFlashlight(), new OsuModBlinds()),
|
||||
new OsuModStrictTracking(),
|
||||
new OsuModAccuracyChallenge(),
|
||||
@@ -209,7 +209,6 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModSpinIn(),
|
||||
new MultiMod(new OsuModGrow(), new OsuModDeflate()),
|
||||
new MultiMod(new ModWindUp(), new ModWindDown()),
|
||||
new OsuModTraceable(),
|
||||
new OsuModBarrelRoll(),
|
||||
new OsuModApproachDifferent(),
|
||||
new OsuModMuted(),
|
||||
@@ -278,19 +277,24 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new OsuRulesetConfigManager(settings, RulesetInfo);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.LargeTickMiss,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.SmallTickMiss,
|
||||
HitResult.SliderTailHit,
|
||||
HitResult.SmallBonus,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
@@ -27,32 +29,34 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.SnakingInSliders,
|
||||
Caption = RulesetSettingsStrings.SnakingInSliders,
|
||||
Current = config.GetBindable<bool>(OsuRulesetSetting.SnakingInSliders)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
}),
|
||||
new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
ClassicDefault = false,
|
||||
LabelText = RulesetSettingsStrings.SnakingOutSliders,
|
||||
Caption = RulesetSettingsStrings.SnakingOutSliders,
|
||||
Current = config.GetBindable<bool>(OsuRulesetSetting.SnakingOutSliders)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
})
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.CursorTrail,
|
||||
ApplyClassicDefault = c => ((IHasCurrentValue<bool>)c).Current.Value = false,
|
||||
},
|
||||
new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
Caption = RulesetSettingsStrings.CursorTrail,
|
||||
Current = config.GetBindable<bool>(OsuRulesetSetting.ShowCursorTrail)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
}),
|
||||
new SettingsItemV2(new FormCheckBox
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.CursorRipples,
|
||||
Caption = RulesetSettingsStrings.CursorRipples,
|
||||
Current = config.GetBindable<bool>(OsuRulesetSetting.ShowCursorRipples)
|
||||
},
|
||||
new SettingsEnumDropdown<PlayfieldBorderStyle>
|
||||
}),
|
||||
new SettingsItemV2(new FormEnumDropdown<PlayfieldBorderStyle>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.PlayfieldBorderStyle,
|
||||
Caption = RulesetSettingsStrings.PlayfieldBorderStyle,
|
||||
Current = config.GetBindable<PlayfieldBorderStyle>(OsuRulesetSetting.PlayfieldBorderStyle),
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,11 +35,9 @@
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
</plist>
|
||||
|
||||
@@ -222,15 +222,18 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
public override RulesetSettingsSubsection CreateSettings() => new TaikoSettingsSubsection(this);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.SmallBonus,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Taiko.Configuration;
|
||||
@@ -26,11 +27,11 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsEnumDropdown<TaikoTouchControlScheme>
|
||||
new SettingsItemV2(new FormEnumDropdown<TaikoTouchControlScheme>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.TouchControlScheme,
|
||||
Caption = RulesetSettingsStrings.TouchControlScheme,
|
||||
Current = config.GetBindable<TaikoTouchControlScheme>(TaikoRulesetSetting.TouchControlScheme)
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
var hitWindows = new TaikoHitWindows();
|
||||
|
||||
HitResult[] usableHitResults = Enum.GetValues<HitResult>().Where(r => hitWindows.IsHitResultAllowed(r)).ToArray();
|
||||
HitResult[] usableHitResults = Enum.GetValues<HitResult>().Where(hitWindows.IsHitResultAllowed).ToArray();
|
||||
|
||||
AddInternal(judgementPooler = new JudgementPooler<DrawableTaikoJudgement>(usableHitResults));
|
||||
|
||||
|
||||
@@ -35,8 +35,31 @@
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>CFBundleIcons~ipad</key>
|
||||
<dict>
|
||||
<key>CFBundlePrimaryIcon</key>
|
||||
<dict>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string>AppIcon60x60</string>
|
||||
</array>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>AppIcon</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>CFBundleIcons</key>
|
||||
<dict>
|
||||
<key>CFBundlePrimaryIcon</key>
|
||||
<dict>
|
||||
<key>CFBundleIconFiles</key>
|
||||
<array>
|
||||
<string>AppIcon60x60</string>
|
||||
<string>AppIcon76x76</string>
|
||||
</array>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>AppIcon</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -15,6 +16,7 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Tests.Visual;
|
||||
@@ -34,6 +36,12 @@ namespace osu.Game.Tests.Beatmaps
|
||||
|
||||
private IBindable<StarDifficulty> starDifficultyBindable;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private BeatmapDifficultyCache actualDifficultyCache { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase osu)
|
||||
{
|
||||
@@ -55,6 +63,36 @@ namespace osu.Game.Tests.Beatmaps
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS}", () => starDifficultyBindable.Value.Stars == BASE_STARS);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidationFlow()
|
||||
{
|
||||
BeatmapInfo postEditBeatmapInfo = null;
|
||||
BeatmapInfo preEditBeatmapInfo = null;
|
||||
|
||||
IBindable<StarDifficulty> bindableDifficulty = null;
|
||||
|
||||
AddStep("get bindable stars", () =>
|
||||
{
|
||||
preEditBeatmapInfo = importedSet.Beatmaps.First();
|
||||
bindableDifficulty = actualDifficultyCache.GetBindableDifficulty(preEditBeatmapInfo);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for stars retrieved", () => bindableDifficulty.Value.Stars, () => Is.GreaterThan(0));
|
||||
|
||||
AddStep("remove all hitobjects", () =>
|
||||
{
|
||||
var working = beatmapManager.GetWorkingBeatmap(preEditBeatmapInfo);
|
||||
|
||||
((IList<HitObject>)working.Beatmap.HitObjects).Clear();
|
||||
|
||||
beatmapManager.Save(working.BeatmapInfo, working.Beatmap);
|
||||
postEditBeatmapInfo = working.BeatmapInfo;
|
||||
});
|
||||
|
||||
AddAssert("stars is now zero", () => actualDifficultyCache.GetDifficultyAsync(postEditBeatmapInfo).GetResultSafely()!.Value.Stars, () => Is.Zero);
|
||||
AddUntilStep("bindable stars is now zero", () => bindableDifficulty.Value.Stars, () => Is.Zero);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStarDifficultyChangesOnModSettings()
|
||||
{
|
||||
@@ -76,6 +114,30 @@ namespace osu.Game.Tests.Beatmaps
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS + 1.75}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.75);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStarDifficultyChangesOnModSettingsCorrectlyTrackAcrossReferenceChanges()
|
||||
{
|
||||
OsuModDoubleTime dt = null;
|
||||
|
||||
AddStep("set computation function", () => difficultyCache.ComputeDifficulty = lookup =>
|
||||
{
|
||||
var modRateAdjust = (ModRateAdjust)lookup.OrderedMods.SingleOrDefault(mod => mod is ModRateAdjust);
|
||||
return new StarDifficulty(BASE_STARS + modRateAdjust?.SpeedChange.Value ?? 0, 0);
|
||||
});
|
||||
|
||||
AddStep("change selected mod to DT", () => SelectedMods.Value = new[] { dt = new OsuModDoubleTime { SpeedChange = { Value = 1.5 } } });
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS + 1.5}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.5);
|
||||
|
||||
AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 1.25);
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.25);
|
||||
|
||||
AddStep("reconstruct DT mod with same settings", () => SelectedMods.Value = new[] { dt = (OsuModDoubleTime)dt.DeepClone() });
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS + 1.25}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 1.25);
|
||||
|
||||
AddStep("change DT speed to 1.25", () => dt.SpeedChange.Value = 2);
|
||||
AddUntilStep($"star difficulty -> {BASE_STARS + 2}", () => starDifficultyBindable.Value.Stars == BASE_STARS + 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStarDifficultyAdjustHashCodeConflict()
|
||||
{
|
||||
@@ -122,8 +184,10 @@ namespace osu.Game.Tests.Beatmaps
|
||||
[Test]
|
||||
public void TestKeyDoesntEqualWithDifferentModSettings()
|
||||
{
|
||||
var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } });
|
||||
var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } });
|
||||
var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 },
|
||||
new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } });
|
||||
var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 },
|
||||
new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } });
|
||||
|
||||
Assert.That(key1, Is.Not.EqualTo(key2));
|
||||
Assert.That(key1.GetHashCode(), Is.Not.EqualTo(key2.GetHashCode()));
|
||||
@@ -132,8 +196,10 @@ namespace osu.Game.Tests.Beatmaps
|
||||
[Test]
|
||||
public void TestKeyEqualWithMatchingModSettings()
|
||||
{
|
||||
var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
|
||||
var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
|
||||
var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 },
|
||||
new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
|
||||
var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = guid }, new RulesetInfo { OnlineID = 0 },
|
||||
new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
|
||||
|
||||
Assert.That(key1, Is.EqualTo(key2));
|
||||
Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()));
|
||||
|
||||
@@ -247,7 +247,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
|
||||
AddStep("change all start times", () =>
|
||||
{
|
||||
editorBeatmap.HitObjectUpdated += h => updatedObjects.Add(h);
|
||||
editorBeatmap.HitObjectUpdated += updatedObjects.Add;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
allHitObjects[i].StartTime += 10;
|
||||
@@ -282,7 +282,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
|
||||
AddStep("change start time twice", () =>
|
||||
{
|
||||
editorBeatmap.HitObjectUpdated += h => updatedObjects.Add(h);
|
||||
editorBeatmap.HitObjectUpdated += updatedObjects.Add;
|
||||
|
||||
editorBeatmap.HitObjects[0].StartTime = 10;
|
||||
editorBeatmap.HitObjects[0].StartTime = 20;
|
||||
|
||||
@@ -104,10 +104,7 @@ namespace osu.Game.Tests.Database
|
||||
Assert.AreNotEqual(detachedBeatmapSet.Status, BeatmapOnlineStatus.Ranked);
|
||||
detachedBeatmapSet.Status = BeatmapOnlineStatus.Ranked;
|
||||
|
||||
beatmapSet.PerformWrite(s =>
|
||||
{
|
||||
detachedBeatmapSet.CopyChangesToRealm(s);
|
||||
});
|
||||
beatmapSet.PerformWrite(detachedBeatmapSet.CopyChangesToRealm);
|
||||
|
||||
beatmapSet.PerformRead(s =>
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@@ -116,6 +117,69 @@ namespace osu.Game.Tests.Database
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFakedRulesetIdIsDetected()
|
||||
{
|
||||
RunTestWithRealm((realm, storage) =>
|
||||
{
|
||||
LoadTestRuleset.HasImplementations = true;
|
||||
LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION;
|
||||
|
||||
var ruleset = new LoadTestRuleset();
|
||||
string rulesetShortName = ruleset.RulesetInfo.ShortName;
|
||||
|
||||
realm.Write(r => r.Add(new RulesetInfo(rulesetShortName, ruleset.RulesetInfo.Name, ruleset.RulesetInfo.InstantiationInfo, 0)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(rulesetShortName)!.Available), Is.True);
|
||||
|
||||
// Availability is updated on construction of a RealmRulesetStore
|
||||
using var _ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(rulesetShortName)!.Available), Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleRulesetWithSameOnlineIdsAreDetected()
|
||||
{
|
||||
RunTestWithRealm((realm, storage) =>
|
||||
{
|
||||
LoadTestRuleset.HasImplementations = true;
|
||||
LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION;
|
||||
LoadTestRuleset.OnlineID = 2;
|
||||
|
||||
var first = new LoadTestRuleset();
|
||||
var second = new CatchRuleset();
|
||||
|
||||
realm.Write(r => r.Add(new RulesetInfo(first.ShortName, first.RulesetInfo.Name, first.RulesetInfo.InstantiationInfo, first.RulesetInfo.OnlineID)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
realm.Write(r => r.Add(new RulesetInfo(second.ShortName, second.RulesetInfo.Name, second.RulesetInfo.InstantiationInfo, second.RulesetInfo.OnlineID)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(first.ShortName)!.Available), Is.True);
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.True);
|
||||
|
||||
// Availability is updated on construction of a RealmRulesetStore
|
||||
using var _ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(first.ShortName)!.Available), Is.False);
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.False);
|
||||
|
||||
realm.Write(r => r.Remove(r.Find<RulesetInfo>(first.ShortName)!));
|
||||
|
||||
using var __ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
private class LoadTestRuleset : Ruleset
|
||||
{
|
||||
public override string RulesetAPIVersionSupported => Version;
|
||||
@@ -124,6 +188,13 @@ namespace osu.Game.Tests.Database
|
||||
|
||||
public static string Version { get; set; } = CURRENT_RULESET_API_VERSION;
|
||||
|
||||
public static int OnlineID { get; set; } = -1;
|
||||
|
||||
public LoadTestRuleset()
|
||||
{
|
||||
RulesetInfo.OnlineID = OnlineID;
|
||||
}
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
if (!HasImplementations)
|
||||
|
||||
@@ -11,7 +11,6 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Filter;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
|
||||
namespace osu.Game.Tests.NonVisual.Filtering
|
||||
@@ -588,6 +587,26 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
Assert.That(visibleBeatmaps, Is.EqualTo(expectedBeatmapIndexes));
|
||||
}
|
||||
|
||||
// This is a temporary class that emulates what these tests originally used from song select v1.
|
||||
// If anyone ever ends up tidying up these test, here's a starting point:
|
||||
// https://gist.github.com/peppy/67fda38f6483fd1dd01ef845ed5bf932
|
||||
public class CarouselBeatmap
|
||||
{
|
||||
public readonly BeatmapInfo BeatmapInfo;
|
||||
|
||||
public BindableBool Filtered = new BindableBool();
|
||||
|
||||
public CarouselBeatmap(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
BeatmapInfo = beatmapInfo;
|
||||
}
|
||||
|
||||
public void Filter(FilterCriteria criteria)
|
||||
{
|
||||
Filtered.Value = !BeatmapCarouselFilterMatching.CheckCriteriaMatch(BeatmapInfo, criteria);
|
||||
}
|
||||
}
|
||||
|
||||
private class CustomCriteria : IRulesetFilterCriteria
|
||||
{
|
||||
private readonly bool match;
|
||||
|
||||
@@ -10,7 +10,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Filter;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
|
||||
namespace osu.Game.Tests.NonVisual.Filtering
|
||||
@@ -509,7 +508,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
("Another One", "diff ]with [[ brackets]]]"),
|
||||
("Diff in title", "a"),
|
||||
("a", "Diff in diff"),
|
||||
}).Select(info => new CarouselBeatmap(new BeatmapInfo
|
||||
}).Select(info => new FilterMatchingTest.CarouselBeatmap(new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -526,7 +526,7 @@ namespace osu.Game.Tests.Rulesets.Scoring
|
||||
// ReSharper disable once MemberHidesStaticFromOuterClass
|
||||
private class TestRuleset : Ruleset
|
||||
{
|
||||
protected override IEnumerable<HitResult> GetValidHitResults() => new[] { HitResult.Great };
|
||||
public override IEnumerable<HitResult> GetValidHitResults() => new[] { HitResult.Great };
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => throw new NotImplementedException();
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ using osu.Game.Screens.Backgrounds;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK;
|
||||
|
||||
@@ -15,7 +15,7 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual.Metadata;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
|
||||
@@ -1,45 +1,64 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Edit.Submission;
|
||||
using osu.Game.Screens.Footer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
public partial class TestSceneBeatmapSubmissionOverlay : OsuTestScene
|
||||
public partial class TestSceneBeatmapSubmissionOverlay : ScreenTestScene
|
||||
{
|
||||
private ScreenFooter footer = null!;
|
||||
private TestBeatmapSubmissionOverlayScreen screen = null!;
|
||||
|
||||
[Cached]
|
||||
private readonly BeatmapSubmissionSettings beatmapSubmissionSettings = new BeatmapSubmissionSettings();
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
AddStep("add overlay", () =>
|
||||
{
|
||||
var receptor = new ScreenFooter.BackReceptor();
|
||||
footer = new ScreenFooter(receptor);
|
||||
base.SetUpSteps();
|
||||
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CachedDependencies = new[]
|
||||
{
|
||||
(typeof(ScreenFooter), (object)footer),
|
||||
(typeof(BeatmapSubmissionSettings), new BeatmapSubmissionSettings()),
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
receptor,
|
||||
new BeatmapSubmissionOverlay
|
||||
{
|
||||
State = { Value = Visibility.Visible, },
|
||||
},
|
||||
footer,
|
||||
}
|
||||
};
|
||||
});
|
||||
AddStep("push screen", () => LoadScreen(screen = new TestBeatmapSubmissionOverlayScreen()));
|
||||
AddUntilStep("wait until screen is loaded", () => screen.IsLoaded, () => Is.True);
|
||||
AddStep("show overlay", () => screen.Overlay.Show());
|
||||
}
|
||||
|
||||
private partial class TestBeatmapSubmissionOverlayScreen : OsuScreen
|
||||
{
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
public BeatmapSubmissionOverlay Overlay = null!;
|
||||
|
||||
private IDisposable? overlayRegistration;
|
||||
|
||||
[Resolved]
|
||||
private IOverlayManager? overlayManager { get; set; }
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponent(Overlay = new BeatmapSubmissionOverlay());
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
overlayRegistration = overlayManager?.RegisterBlockingOverlay(Overlay);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
overlayRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName);
|
||||
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
|
||||
AddStep("add effect point", () => EditorBeatmap.ControlPointInfo.Add(500, new EffectControlPoint { KiaiMode = true }));
|
||||
AddStep("add bookmarks", () => EditorBeatmap.Bookmarks.AddRange([500, 1000]));
|
||||
AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[]
|
||||
{
|
||||
new HitCircle
|
||||
@@ -185,6 +186,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
var effectPoint = EditorBeatmap.ControlPointInfo.EffectPoints.Single();
|
||||
return effectPoint.Time == 500 && effectPoint.KiaiMode && effectPoint.ScrollSpeedBindable.IsDefault;
|
||||
});
|
||||
AddAssert("created difficulty has bookmarks", () => EditorBeatmap.Bookmarks.Count == 2);
|
||||
AddAssert("created difficulty has no objects", () => EditorBeatmap.HitObjects.Count == 0);
|
||||
|
||||
AddAssert("status is modified", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.LocallyModified);
|
||||
@@ -223,6 +225,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = previousDifficultyName = Guid.NewGuid().ToString());
|
||||
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
|
||||
AddStep("add bookmarks", () => EditorBeatmap.Bookmarks.AddRange([500, 1000]));
|
||||
AddStep("add effect points", () =>
|
||||
{
|
||||
EditorBeatmap.ControlPointInfo.Add(250, new EffectControlPoint { KiaiMode = false, ScrollSpeed = 0.05 });
|
||||
@@ -253,6 +256,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
|
||||
});
|
||||
|
||||
AddAssert("created difficulty has bookmarks", () => EditorBeatmap.Bookmarks.Count == 2);
|
||||
|
||||
AddAssert("created difficulty has effect points", () =>
|
||||
{
|
||||
return EditorBeatmap.ControlPointInfo.EffectPoints.SequenceEqual(new[]
|
||||
@@ -284,6 +289,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName);
|
||||
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
|
||||
AddStep("add bookmarks", () => EditorBeatmap.Bookmarks.AddRange([500, 1000]));
|
||||
AddStep("add effect points", () =>
|
||||
{
|
||||
EditorBeatmap.ControlPointInfo.Add(250, new EffectControlPoint { KiaiMode = false, ScrollSpeed = 0.05 });
|
||||
@@ -311,6 +317,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
|
||||
});
|
||||
|
||||
AddAssert("created difficulty has bookmarks", () => EditorBeatmap.Bookmarks.Count == 2);
|
||||
|
||||
AddAssert("created difficulty has effect points", () =>
|
||||
{
|
||||
// since this difficulty is on another ruleset, scroll speed specifications are completely reset,
|
||||
@@ -344,6 +352,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
StartTime = 1000
|
||||
}
|
||||
}));
|
||||
AddStep("add bookmarks", () => EditorBeatmap.Bookmarks.AddRange([500, 1000]));
|
||||
AddStep("set approach rate", () => EditorBeatmap.Difficulty.ApproachRate = 4);
|
||||
AddStep("set combo colours", () =>
|
||||
{
|
||||
@@ -394,6 +403,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
|
||||
});
|
||||
AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2);
|
||||
AddAssert("created difficulty has bookmarks", () => EditorBeatmap.Bookmarks.Count == 2);
|
||||
AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4);
|
||||
AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
@@ -19,6 +19,7 @@ using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||
using osu.Game.Screens.Edit.Timing;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
@@ -112,6 +113,77 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
hitObjectHasSampleBank(1, HitSampleInfo.BANK_DRUM);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAutoAdditionsBankMatchesNormalBankWhenChangedViaPopover()
|
||||
{
|
||||
clickSamplePiece(0);
|
||||
setBankViaPopover(HitSampleInfo.BANK_SOFT);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||
|
||||
toggleAdditionViaPopover(1);
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_SOFT);
|
||||
|
||||
setBankViaPopover(HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
|
||||
setAdditionBankViaPopover(HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
setAdditionBankViaPopover(EditorSelectionHandler.HIT_BANK_AUTO);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAutoAdditionsBankMatchesNormalBankWhenChangedViaHotkeys()
|
||||
{
|
||||
AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]));
|
||||
AddStep("set soft normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.E);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||
|
||||
AddStep("toggle finish", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_SOFT);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_SOFT);
|
||||
|
||||
AddStep("set drum normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
|
||||
AddStep("set normal addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.W);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set auto addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUndo()
|
||||
{
|
||||
@@ -346,7 +418,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
{
|
||||
for (int i = 0; i < h.Samples.Count; i++)
|
||||
{
|
||||
h.Samples[i] = h.Samples[i].With(newBank: HitSampleInfo.BANK_SOFT);
|
||||
h.Samples[i] = h.Samples[i].With(newBank: HitSampleInfo.BANK_SOFT, newEditorAutoBank: false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -354,7 +426,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddStep("add whistle addition", () =>
|
||||
{
|
||||
foreach (var h in EditorBeatmap.HitObjects)
|
||||
h.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, HitSampleInfo.BANK_SOFT));
|
||||
h.Samples.Add(new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, HitSampleInfo.BANK_SOFT, editorAutoBank: false));
|
||||
});
|
||||
|
||||
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||
@@ -523,6 +595,172 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name != HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(expected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonAutoBankHotkeysDuringPlacementPersistAfterPlacement()
|
||||
{
|
||||
AddStep("Clear all objects", () => EditorBeatmap.Clear());
|
||||
AddStep("Enter placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move mouse to centre", () => InputManager.MoveMouseTo(Editor.ChildrenOfType<HitObjectComposer>().First().ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddStep("Move to 3000", () => EditorClock.Seek(3000));
|
||||
|
||||
AddStep("Press drum bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample is {HitSampleInfo.BANK_DRUM}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name == HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_DRUM));
|
||||
|
||||
AddStep("Press normal addition bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.W);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
|
||||
AddStep("Press finish sample shortcut", () =>
|
||||
{
|
||||
InputManager.Key(Key.E);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample addition is {HitSampleInfo.BANK_NORMAL}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name != HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_NORMAL));
|
||||
|
||||
AddStep("Finish placement", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoNormalBankFlag(0, false);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
|
||||
clickSamplePiece(0);
|
||||
samplePopoverIsOpen();
|
||||
samplePopoverHasSingleAdditionBank(HitSampleInfo.BANK_NORMAL);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAutoAdditionBankHotkeyDuringPlacementPersistsAfterPlacement()
|
||||
{
|
||||
AddStep("Clear all objects", () => EditorBeatmap.Clear());
|
||||
AddStep("Enter placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move mouse to centre", () => InputManager.MoveMouseTo(Editor.ChildrenOfType<HitObjectComposer>().First().ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddStep("Move to 3000", () => EditorClock.Seek(3000));
|
||||
|
||||
AddStep("Press drum bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample is {HitSampleInfo.BANK_DRUM}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name == HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_DRUM));
|
||||
|
||||
AddStep("Press normal addition bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.W);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
|
||||
AddStep("Press finish sample shortcut", () =>
|
||||
{
|
||||
InputManager.Key(Key.E);
|
||||
});
|
||||
|
||||
AddStep("Press auto addition bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample addition is {HitSampleInfo.BANK_DRUM}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name != HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_DRUM));
|
||||
|
||||
AddStep("Finish placement", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoNormalBankFlag(0, false);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
clickSamplePiece(0);
|
||||
samplePopoverIsOpen();
|
||||
samplePopoverHasSingleAdditionBank(EditorSelectionHandler.HIT_BANK_AUTO);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFullAutoBankHotkeyDuringPlacementPersistsAfterPlacement()
|
||||
{
|
||||
AddStep("Clear all objects", () => EditorBeatmap.Clear());
|
||||
AddStep("Enter placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move mouse to centre", () => InputManager.MoveMouseTo(Editor.ChildrenOfType<HitObjectComposer>().First().ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddStep("Move to 3000", () => EditorClock.Seek(3000));
|
||||
|
||||
AddStep("Press auto normal bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample is {HitSampleInfo.BANK_NORMAL}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name == HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_NORMAL));
|
||||
|
||||
AddStep("Press finish sample shortcut", () =>
|
||||
{
|
||||
InputManager.Key(Key.E);
|
||||
});
|
||||
|
||||
AddStep("Press auto addition bank shortcut", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
|
||||
AddAssert($"Placement sample addition is {HitSampleInfo.BANK_NORMAL}",
|
||||
() => EditorBeatmap.PlacementObject.Value.Samples.First(s => s.Name != HitSampleInfo.HIT_NORMAL).Bank, () => Is.EqualTo(HitSampleInfo.BANK_NORMAL));
|
||||
|
||||
AddStep("Finish placement", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoNormalBankFlag(0, false); // it's the first object - nothing to inherit bank from
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
clickSamplePiece(0);
|
||||
samplePopoverIsOpen();
|
||||
samplePopoverHasSingleBank(HitSampleInfo.BANK_NORMAL);
|
||||
samplePopoverHasSingleAdditionBank(EditorSelectionHandler.HIT_BANK_AUTO);
|
||||
dismissPopover();
|
||||
|
||||
AddStep("Move to 5000", () => EditorClock.Seek(5000));
|
||||
AddStep("Enter placement mode", () => InputManager.Key(Key.Number2));
|
||||
AddStep("Move mouse to centre", () => InputManager.MoveMouseTo(Editor.ChildrenOfType<HitObjectComposer>().First().ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("Finish placement", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
hitObjectHasSamples(1, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH); // finish is still implied, continuing from first placement
|
||||
hitObjectHasSampleNormalBank(1, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(1, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoNormalBankFlag(1, true);
|
||||
hitObjectHasAutoAdditionBankFlag(1, true);
|
||||
|
||||
clickSamplePiece(1);
|
||||
samplePopoverIsOpen();
|
||||
samplePopoverHasSingleBank(HitSampleInfo.BANK_NORMAL);
|
||||
samplePopoverHasSingleAdditionBank(EditorSelectionHandler.HIT_BANK_AUTO);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PopoverForMultipleSelectionChangesAllSamples()
|
||||
{
|
||||
@@ -599,19 +837,19 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
Path = new SliderPath(new[] { new PathControlPoint(Vector2.Zero), new PathControlPoint(new Vector2(250, 0)) }),
|
||||
Samples =
|
||||
{
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL)
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL, editorAutoBank: false)
|
||||
},
|
||||
NodeSamples = new List<IList<HitSampleInfo>>
|
||||
{
|
||||
new List<HitSampleInfo>
|
||||
{
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL, bank: HitSampleInfo.BANK_DRUM),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_CLAP, bank: HitSampleInfo.BANK_DRUM),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL, bank: HitSampleInfo.BANK_DRUM, editorAutoBank: false),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_CLAP, bank: HitSampleInfo.BANK_DRUM, editorAutoBank: false),
|
||||
},
|
||||
new List<HitSampleInfo>
|
||||
{
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL, bank: HitSampleInfo.BANK_SOFT),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, bank: HitSampleInfo.BANK_SOFT),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_NORMAL, bank: HitSampleInfo.BANK_SOFT, editorAutoBank: false),
|
||||
new HitSampleInfo(HitSampleInfo.HIT_WHISTLE, bank: HitSampleInfo.BANK_SOFT, editorAutoBank: false),
|
||||
},
|
||||
}
|
||||
});
|
||||
@@ -808,6 +1046,174 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundBeforeSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundAfterSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSwitchSoundAfterSettingNonAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set drum addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
|
||||
AddStep("remove finish sound", () => InputManager.Key(Key.E));
|
||||
AddStep("add whistle sound", () => InputManager.Key(Key.W));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_WHISTLE);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundBeforeSettingAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set auto addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddSoundAfterSettingAutoAdditionBankOnSelectedObject()
|
||||
{
|
||||
AddStep("select first object", () =>
|
||||
{
|
||||
EditorBeatmap.SelectedHitObjects.Clear();
|
||||
EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects[0]);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("set auto addition bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.Key(Key.Q);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
|
||||
AddStep("add finish sound", () => InputManager.Key(Key.E));
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_NORMAL);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
|
||||
AddStep("set drum normal bank", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Key(Key.R);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
hitObjectHasSamples(0, HitSampleInfo.HIT_NORMAL, HitSampleInfo.HIT_FINISH);
|
||||
hitObjectHasSampleNormalBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasSampleAdditionBank(0, HitSampleInfo.BANK_DRUM);
|
||||
hitObjectHasAutoAdditionBankFlag(0, true);
|
||||
}
|
||||
|
||||
private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} sample piece", () =>
|
||||
{
|
||||
var samplePiece = this.ChildrenOfType<SamplePointPiece>().Single(piece => piece is not NodeSamplePointPiece && piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex));
|
||||
@@ -880,6 +1286,14 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return dropdown?.Current.Value == "(multiple)";
|
||||
});
|
||||
|
||||
private void samplePopoverHasSingleAdditionBank(string bank) => AddUntilStep($"sample popover has bank {bank}", () =>
|
||||
{
|
||||
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||
var dropdown = popover?.ChildrenOfType<LabelledDropdown<string>>().ElementAt(1);
|
||||
|
||||
return dropdown?.Current.Value == bank;
|
||||
});
|
||||
|
||||
private void dismissPopover()
|
||||
{
|
||||
AddStep("dismiss popover", () => InputManager.Key(Key.Escape));
|
||||
@@ -953,6 +1367,18 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return h.Samples.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(o => o.Bank == bank);
|
||||
});
|
||||
|
||||
private void hitObjectHasAutoNormalBankFlag(int objectIndex, bool autoBank) => AddAssert($"{objectIndex.ToOrdinalWords()} has auto normal bank {(autoBank ? "on" : "off")}", () =>
|
||||
{
|
||||
var h = EditorBeatmap.HitObjects.ElementAt(objectIndex);
|
||||
return h.Samples.Where(o => o.Name == HitSampleInfo.HIT_NORMAL).All(o => o.EditorAutoBank == autoBank);
|
||||
});
|
||||
|
||||
private void hitObjectHasAutoAdditionBankFlag(int objectIndex, bool autoBank) => AddAssert($"{objectIndex.ToOrdinalWords()} has auto addition bank {(autoBank ? "on" : "off")}", () =>
|
||||
{
|
||||
var h = EditorBeatmap.HitObjects.ElementAt(objectIndex);
|
||||
return h.Samples.Where(o => o.Name != HitSampleInfo.HIT_NORMAL).All(o => o.EditorAutoBank == autoBank);
|
||||
});
|
||||
|
||||
private void hitObjectNodeHasSamples(int objectIndex, int nodeIndex, params string[] samples) => AddAssert(
|
||||
$"{objectIndex.ToOrdinalWords()} object {nodeIndex.ToOrdinalWords()} node has samples {string.Join(',', samples)}", () =>
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Resources;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
|
||||
@@ -272,8 +272,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddAssert("circle has 2 samples", () => EditorBeatmap.HitObjects[1].Samples, () => Has.Count.EqualTo(2));
|
||||
AddAssert("normal sample has soft bank", () => EditorBeatmap.HitObjects[1].Samples.Single(s => s.Name == HitSampleInfo.HIT_NORMAL).Bank,
|
||||
() => Is.EqualTo(HitSampleInfo.BANK_SOFT));
|
||||
AddAssert("clap sample has drum bank", () => EditorBeatmap.HitObjects[1].Samples.Single(s => s.Name == HitSampleInfo.HIT_CLAP).Bank,
|
||||
() => Is.EqualTo(HitSampleInfo.BANK_DRUM));
|
||||
AddAssert("clap sample has soft bank", () => EditorBeatmap.HitObjects[1].Samples.Single(s => s.Name == HitSampleInfo.HIT_CLAP).Bank,
|
||||
() => Is.EqualTo(HitSampleInfo.BANK_SOFT));
|
||||
AddAssert("circle inherited volume", () => EditorBeatmap.HitObjects[1].Samples.All(s => s.Volume == 70));
|
||||
|
||||
AddStep("seek to 1000", () => EditorClock.Seek(1000)); // previous object is the one at time 500, which has no additions
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public partial class TestSceneBeatmapMetadataDisplay : OsuTestScene
|
||||
{
|
||||
@@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
@@ -21,7 +21,7 @@ using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
using osuTK.Graphics;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
using osu.Game.Tests.Visual.Spectator;
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
List<SkinBlueprint> blueprints = new List<SkinBlueprint>();
|
||||
|
||||
AddStep("clear list", () => blueprints.Clear());
|
||||
AddStep("clear list", blueprints.Clear);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
using osuTK.Input;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
+3
-3
@@ -6,16 +6,16 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public partial class TestSceneUserTopScoreContainer : OsuTestScene
|
||||
{
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Matchmaking;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Intro;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.Queue;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
@@ -26,7 +27,7 @@ namespace osu.Game.Tests.Visual.Matchmaking
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("load screen", () => LoadScreen(new ScreenIntro()));
|
||||
AddStep("load screen", () => LoadScreen(new ScreenIntro(MatchmakingPoolType.QuickPlay)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -21,7 +21,7 @@ using osu.Game.Online.Spectator;
|
||||
using osu.Game.Replays.Legacy;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// 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.Allocation;
|
||||
@@ -15,6 +17,7 @@ using osu.Game.Database;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Lounge;
|
||||
@@ -22,6 +25,7 @@ using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
@@ -35,7 +39,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
protected IScreen CurrentScreen => multiplayerComponents.CurrentScreen;
|
||||
protected IScreen CurrentSubScreen => multiplayerComponents.MultiplayerScreen.CurrentSubScreen;
|
||||
|
||||
private BeatmapManager beatmaps = null!;
|
||||
protected BeatmapManager Beatmaps { get; private set; } = null!;
|
||||
|
||||
private BeatmapSetInfo importedSet = null!;
|
||||
private RulesetStore rulesets = null!;
|
||||
|
||||
@@ -49,7 +54,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
BeatmapStore beatmapStore;
|
||||
|
||||
Dependencies.Cache(rulesets = new RealmRulesetStore(Realm));
|
||||
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, Realm, null, audio, Resources, host, Beatmap.Default));
|
||||
Dependencies.Cache(Beatmaps = new BeatmapManager(LocalStorage, Realm, null, audio, Resources, host, Beatmap.Default));
|
||||
Dependencies.CacheAs(beatmapStore = new RealmDetachedBeatmapStore());
|
||||
Dependencies.Cache(Realm);
|
||||
|
||||
@@ -62,13 +67,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddStep("import beatmap", () =>
|
||||
{
|
||||
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
Beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
Realm.Write(r =>
|
||||
{
|
||||
foreach (var beatmapInfo in r.All<BeatmapInfo>())
|
||||
beatmapInfo.OnlineMD5Hash = beatmapInfo.MD5Hash;
|
||||
});
|
||||
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
|
||||
importedSet = Beatmaps.GetAllUsableBeatmapSets().First();
|
||||
InitialBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
|
||||
OtherBeatmap = importedSet.Beatmaps.Last(b => b.Ruleset.OnlineID == 0);
|
||||
});
|
||||
@@ -118,6 +123,30 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("exit player", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
|
||||
}
|
||||
|
||||
protected void AddBeatmapFromSongSelect(Func<BeatmapInfo> beatmap, RulesetInfo? ruleset = null, IReadOnlyList<Mod>? mods = null)
|
||||
{
|
||||
Screens.Select.SongSelect? songSelect = null;
|
||||
|
||||
AddStep("click add button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<MultiplayerMatchSubScreen.AddItemButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => (songSelect = CurrentSubScreen as Screens.Select.SongSelect) != null);
|
||||
AddUntilStep("wait for loaded", () => songSelect.IsCurrentScreen() && !songSelect.AsNonNull().IsFiltering);
|
||||
|
||||
if (ruleset != null)
|
||||
AddStep($"set {ruleset.Name} ruleset", () => songSelect.AsNonNull().Ruleset.Value = ruleset);
|
||||
|
||||
if (mods != null)
|
||||
AddStep($"set mods to {string.Join(",", mods.Select(m => m.Acronym))}", () => songSelect.AsNonNull().Mods.Value = mods);
|
||||
|
||||
AddStep("select other beatmap", () => songSelect.AsNonNull().Beatmap.Value = Beatmaps.GetWorkingBeatmap(beatmap()));
|
||||
AddStep("confirm selection", () => InputManager.Key(Key.Enter));
|
||||
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
@@ -45,10 +37,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestItemAddedToTheEndOfQueue()
|
||||
{
|
||||
addItem(() => OtherBeatmap);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap);
|
||||
AddUntilStep("playlist has 2 items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 2);
|
||||
|
||||
addItem(() => InitialBeatmap);
|
||||
AddBeatmapFromSongSelect(() => InitialBeatmap);
|
||||
AddUntilStep("playlist has 3 items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 3);
|
||||
|
||||
AddUntilStep("first item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID);
|
||||
@@ -57,8 +49,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestNextItemSelectedAfterGameplayFinish()
|
||||
{
|
||||
addItem(() => OtherBeatmap);
|
||||
addItem(() => InitialBeatmap);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap);
|
||||
AddBeatmapFromSongSelect(() => InitialBeatmap);
|
||||
|
||||
RunGameplay();
|
||||
|
||||
@@ -74,8 +66,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestItemsNotClearedWhenSwitchToHostOnlyMode()
|
||||
{
|
||||
addItem(() => OtherBeatmap);
|
||||
addItem(() => InitialBeatmap);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap);
|
||||
AddBeatmapFromSongSelect(() => InitialBeatmap);
|
||||
|
||||
// Move to the "other" beatmap.
|
||||
RunGameplay();
|
||||
@@ -89,14 +81,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestCorrectItemSelectedAfterNewItemAdded()
|
||||
{
|
||||
addItem(() => OtherBeatmap);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap);
|
||||
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCorrectRulesetSelectedAfterNewItemAdded()
|
||||
{
|
||||
addItem(() => OtherBeatmap, new CatchRuleset().RulesetInfo);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap, new CatchRuleset().RulesetInfo);
|
||||
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
||||
|
||||
AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||
@@ -113,7 +105,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestCorrectModsSelectedAfterNewItemAdded()
|
||||
{
|
||||
addItem(() => OtherBeatmap, mods: new Mod[] { new OsuModDoubleTime() });
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap, mods: new Mod[] { new OsuModDoubleTime() });
|
||||
AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
|
||||
|
||||
AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle);
|
||||
@@ -126,28 +118,5 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("mods are correct", () => !((Player)CurrentScreen).Mods.Value.Any());
|
||||
AddStep("exit player", () => CurrentScreen.Exit());
|
||||
}
|
||||
|
||||
private void addItem(Func<BeatmapInfo> beatmap, RulesetInfo? ruleset = null, IReadOnlyList<Mod>? mods = null)
|
||||
{
|
||||
Screens.Select.SongSelect? songSelect = null;
|
||||
|
||||
AddStep("click add button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<MultiplayerMatchSubScreen.AddItemButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => (songSelect = CurrentSubScreen as Screens.Select.SongSelect) != null);
|
||||
AddUntilStep("wait for loaded", () => songSelect.AsNonNull().BeatmapSetsLoaded);
|
||||
|
||||
if (ruleset != null)
|
||||
AddStep($"set {ruleset.Name} ruleset", () => songSelect.AsNonNull().Ruleset.Value = ruleset);
|
||||
|
||||
if (mods != null)
|
||||
AddStep($"set mods to {string.Join(",", mods.Select(m => m.Acronym))}", () => songSelect.AsNonNull().Mods.Value = mods);
|
||||
|
||||
AddStep("select other beatmap", () => songSelect.AsNonNull().FinaliseSelection(beatmap()));
|
||||
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,13 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Utils;
|
||||
@@ -22,12 +21,13 @@ using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public partial class TestSceneFreeModSelectOverlay : MultiplayerTestScene
|
||||
public partial class TestSceneFreeModSelectOverlay : ScreenTestScene
|
||||
{
|
||||
private FreeModSelectOverlay freeModSelectOverlay = null!;
|
||||
private FooterButtonFreeMods footerButtonFreeMods = null!;
|
||||
private ScreenFooter footer = null!;
|
||||
private TestFreeModSelectOverlayScreen screen = null!;
|
||||
private readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> availableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>();
|
||||
private readonly Bindable<IReadOnlyList<Mod>> freeMods = new Bindable<IReadOnlyList<Mod>>([]);
|
||||
|
||||
private FreeModSelectOverlay freeModSelectOverlay => screen.Overlay;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase osuGameBase)
|
||||
@@ -35,6 +35,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
availableMods.BindTo(osuGameBase.AvailableMods);
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("reset selected mods", () => freeMods.Value = []);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFreeModSelect()
|
||||
{
|
||||
@@ -44,11 +52,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
() => this.ChildrenOfType<ModPanel>()
|
||||
.Where(panel => panel.IsPresent)
|
||||
.All(panel => panel.Mod.HasImplementation && panel.Mod.UserPlayable));
|
||||
|
||||
AddToggleStep("toggle visibility", visible =>
|
||||
{
|
||||
freeModSelectOverlay.State.Value = visible ? Visibility.Visible : Visibility.Hidden;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -72,18 +75,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
AddAssert("select all button enabled", () => this.ChildrenOfType<SelectAllModsButton>().Single().Enabled.Value);
|
||||
|
||||
AddStep("click select all button", navigateAndClick<SelectAllModsButton>);
|
||||
AddStep("click select all button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<SelectAllModsButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("select all button disabled", () => !this.ChildrenOfType<SelectAllModsButton>().Single().Enabled.Value);
|
||||
|
||||
AddStep("change search term", () => freeModSelectOverlay.SearchTerm = "e");
|
||||
|
||||
AddAssert("select all button enabled", () => this.ChildrenOfType<SelectAllModsButton>().Single().Enabled.Value);
|
||||
|
||||
void navigateAndClick<T>() where T : Drawable
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<T>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -124,55 +125,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("select all button enabled", () => this.ChildrenOfType<SelectAllModsButton>().Single().Enabled.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSelectAllViaFooterButtonThenDeselectFromOverlay()
|
||||
{
|
||||
createFreeModSelect();
|
||||
|
||||
AddAssert("overlay select all button enabled", () => this.ChildrenOfType<SelectAllModsButton>().Single().Enabled.Value);
|
||||
AddAssert("footer button displays off", () => footerButtonFreeMods.ChildrenOfType<IHasText>().Any(t => t.Text == "off"));
|
||||
|
||||
AddStep("click footer select all button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(footerButtonFreeMods);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("all mods selected", assertAllAvailableModsSelected);
|
||||
AddAssert("footer button displays all", () => footerButtonFreeMods.ChildrenOfType<IHasText>().Any(t => t.Text == "all"));
|
||||
|
||||
AddStep("click deselect all button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<DeselectAllModsButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddUntilStep("all mods deselected", () => !freeModSelectOverlay.SelectedMods.Value.Any());
|
||||
AddAssert("footer button displays off", () => footerButtonFreeMods.ChildrenOfType<IHasText>().Any(t => t.Text == "off"));
|
||||
}
|
||||
|
||||
private void createFreeModSelect()
|
||||
{
|
||||
AddStep("create free mod select screen", () => Child = new DependencyProvidingContainer
|
||||
AddStep("create free mod select screen", () => LoadScreen(screen = new TestFreeModSelectOverlayScreen
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
freeModSelectOverlay = new FreeModSelectOverlay
|
||||
{
|
||||
State = { Value = Visibility.Visible }
|
||||
},
|
||||
footerButtonFreeMods = new FooterButtonFreeMods(freeModSelectOverlay)
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Y = -ScreenFooter.HEIGHT,
|
||||
FreeMods = { BindTarget = freeModSelectOverlay.SelectedMods },
|
||||
},
|
||||
footer = new ScreenFooter(),
|
||||
},
|
||||
CachedDependencies = new (Type, object)[] { (typeof(ScreenFooter), footer) },
|
||||
});
|
||||
|
||||
FreeMods = { BindTarget = freeMods },
|
||||
}));
|
||||
AddUntilStep("wait until screen is loaded", () => screen.IsLoaded, () => Is.True);
|
||||
AddStep("show overlay", () => freeModSelectOverlay.Show());
|
||||
AddUntilStep("all column content loaded",
|
||||
() => freeModSelectOverlay.ChildrenOfType<ModColumn>().Any()
|
||||
&& freeModSelectOverlay.ChildrenOfType<ModColumn>().All(column => column.IsLoaded && column.ItemsLoaded));
|
||||
@@ -197,5 +157,50 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private partial class TestFreeModSelectOverlayScreen : OsuScreen
|
||||
{
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
public FreeModSelectOverlay Overlay = null!;
|
||||
private IDisposable? overlayRegistration;
|
||||
|
||||
public readonly Bindable<IReadOnlyList<Mod>> FreeMods = new Bindable<IReadOnlyList<Mod>>([]);
|
||||
|
||||
[Resolved]
|
||||
private IOverlayManager? overlayManager { get; set; }
|
||||
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponent(Overlay = new FreeModSelectOverlay
|
||||
{
|
||||
SelectedMods = { BindTarget = FreeMods }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
overlayRegistration = overlayManager?.RegisterBlockingOverlay(Overlay);
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() =>
|
||||
[
|
||||
new FooterButtonFreeMods(Overlay)
|
||||
{
|
||||
FreeMods = { BindTarget = FreeMods },
|
||||
},
|
||||
];
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
overlayRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
@@ -36,6 +38,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddUntilStep("second playlist item selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[1].ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestItemStillSelectedAfterChangeToSameBeatmap()
|
||||
{
|
||||
selectNewItem(() => InitialBeatmap);
|
||||
|
||||
AddUntilStep("playlist item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSettingsUpdatedWhenChangingQueueMode()
|
||||
{
|
||||
@@ -47,14 +57,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddUntilStep("api room updated", () => MultiplayerClient.ClientAPIRoom?.QueueMode == QueueMode.AllPlayers);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestItemStillSelectedAfterChangeToSameBeatmap()
|
||||
{
|
||||
selectNewItem(() => InitialBeatmap);
|
||||
|
||||
AddUntilStep("playlist item still selected", () => MultiplayerClient.ClientRoom?.Settings.PlaylistItemId == MultiplayerClient.ClientAPIRoom?.Playlist[0].ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestItemStillSelectedAfterChangeToOtherBeatmap()
|
||||
{
|
||||
@@ -80,13 +82,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
[Test]
|
||||
public void TestAddItemsAsHost()
|
||||
{
|
||||
addItem(() => OtherBeatmap);
|
||||
AddBeatmapFromSongSelect(() => OtherBeatmap);
|
||||
|
||||
AddUntilStep("playlist contains two items", () => MultiplayerClient.ClientAPIRoom?.Playlist.Count == 2);
|
||||
}
|
||||
|
||||
private void selectNewItem(Func<BeatmapInfo> beatmap)
|
||||
{
|
||||
Screens.Select.SongSelect? songSelect = null;
|
||||
|
||||
AddUntilStep("wait for playlist panels to load", () =>
|
||||
{
|
||||
var queueList = this.ChildrenOfType<MultiplayerQueueList>().Single();
|
||||
@@ -99,26 +103,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => CurrentSubScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for song select", () => (songSelect = CurrentSubScreen as Screens.Select.SongSelect) != null);
|
||||
AddUntilStep("wait for loaded", () => songSelect.IsCurrentScreen() && !songSelect.AsNonNull().IsFiltering);
|
||||
|
||||
BeatmapInfo otherBeatmap = null!;
|
||||
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap()));
|
||||
|
||||
AddStep("select other beatmap", () => songSelect.AsNonNull().Beatmap.Value = Beatmaps.GetWorkingBeatmap(otherBeatmap = beatmap()));
|
||||
AddStep("confirm selection", () => InputManager.Key(Key.Enter));
|
||||
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
||||
|
||||
AddUntilStep("selected item is new beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == otherBeatmap.OnlineID);
|
||||
}
|
||||
|
||||
private void addItem(Func<BeatmapInfo> beatmap)
|
||||
{
|
||||
AddStep("click add button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<MultiplayerMatchSubScreen.AddItemButton>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => CurrentSubScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded);
|
||||
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(beatmap()));
|
||||
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public partial class TestSceneMatchBeatmapDetailArea : OnlinePlayTestScene
|
||||
{
|
||||
private Room room = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("create area", () =>
|
||||
{
|
||||
Child = new MatchBeatmapDetailArea(room = new Room())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(500),
|
||||
CreateNewItem = createNewItem
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void createNewItem()
|
||||
{
|
||||
room.Playlist = room.Playlist.Append(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
|
||||
{
|
||||
ID = room.Playlist.Count,
|
||||
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||
RequiredMods = new[]
|
||||
{
|
||||
new APIMod(new OsuModHardRock()),
|
||||
new APIMod(new OsuModDoubleTime()),
|
||||
new APIMod(new OsuModAutoplay())
|
||||
}
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ using osu.Framework.Timing;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
|
||||
@@ -228,7 +228,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
// edit playlist item
|
||||
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||
AddUntilStep("wait for song select", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||
waitForSongSelect();
|
||||
|
||||
// select beatmap
|
||||
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||
@@ -451,7 +451,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
((MultiplayerMatchSubScreen)currentSubScreen).ShowSongSelect(item);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||
waitForSongSelect();
|
||||
|
||||
AddUntilStep("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().BeatmapID);
|
||||
|
||||
@@ -492,7 +492,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
((MultiplayerMatchSubScreen)currentSubScreen).ShowSongSelect(item);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||
waitForSongSelect();
|
||||
|
||||
AddUntilStep("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.ClientRoom?.Playlist.First().RulesetID);
|
||||
|
||||
@@ -533,7 +533,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
((MultiplayerMatchSubScreen)currentSubScreen).ShowSongSelect(item);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => this.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||
waitForSongSelect();
|
||||
|
||||
AddUntilStep("Mods match current item",
|
||||
() => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.ClientRoom.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym)));
|
||||
@@ -1051,7 +1051,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("press edit on second item", () => this.ChildrenOfType<DrawableRoomPlaylistItem>().Single(i => i.Item.RulesetID == 1)
|
||||
.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistEditButton>().Single().TriggerClick());
|
||||
|
||||
AddUntilStep("wait for song select", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault()?.BeatmapSetsLoaded == true);
|
||||
waitForSongSelect();
|
||||
AddAssert("ruleset is taiko", () => Ruleset.Value.OnlineID == 1);
|
||||
|
||||
AddStep("start match", () => multiplayerClient.StartMatch().WaitSafely());
|
||||
@@ -1249,6 +1249,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
|
||||
}
|
||||
|
||||
private void waitForSongSelect()
|
||||
{
|
||||
AddUntilStep("wait for song select", () =>
|
||||
{
|
||||
var songSelect = InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault();
|
||||
return songSelect != null && songSelect.IsCurrentScreen() && !songSelect.IsFiltering;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
@@ -9,7 +9,7 @@ using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -26,8 +27,8 @@ using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
@@ -64,7 +65,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("create room", () => room = CreateDefaultRoom());
|
||||
AddStep("create room", () =>
|
||||
{
|
||||
Ruleset.Value = new OsuRuleset().RulesetInfo;
|
||||
room = CreateDefaultRoom();
|
||||
});
|
||||
AddStep("join room", () => JoinRoom(room));
|
||||
WaitForJoined();
|
||||
}
|
||||
@@ -80,7 +85,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
LoadScreen(songSelect = new TestMultiplayerMatchSongSelect(room));
|
||||
});
|
||||
|
||||
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && !songSelect.IsFiltering);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -101,19 +106,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
setUp();
|
||||
|
||||
AddStep("change ruleset", () => Ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
|
||||
AddUntilStep("wait for filtering", () => !songSelect.IsFiltering);
|
||||
AddStep("select beatmap",
|
||||
() => songSelect.Carousel.SelectBeatmap(selectedBeatmap = beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == new TaikoRuleset().LegacyID)));
|
||||
() => songSelect.SelectBeatmap(selectedBeatmap = beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == new TaikoRuleset().LegacyID)));
|
||||
|
||||
AddUntilStep("wait for selection", () => Beatmap.Value.BeatmapInfo.Equals(selectedBeatmap));
|
||||
AddUntilStep("wait for ongoing operation to complete", () => !OnlinePlayDependencies.OngoingOperationTracker.InProgress.Value);
|
||||
|
||||
AddStep("set mods", () => SelectedMods.Value = new[] { new TaikoModDoubleTime() });
|
||||
|
||||
AddStep("confirm selection", () => songSelect.FinaliseSelection());
|
||||
AddStep("confirm selection", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddUntilStep("song select exited", () => !songSelect.IsCurrentScreen());
|
||||
|
||||
AddAssert("beatmap not changed", () => Beatmap.Value.BeatmapInfo.Equals(selectedBeatmap));
|
||||
AddAssert("beatmap not changed", () => Beatmap.Value.BeatmapInfo, () => Is.EqualTo((selectedBeatmap)));
|
||||
AddAssert("ruleset not changed", () => Ruleset.Value.Equals(new TaikoRuleset().RulesetInfo));
|
||||
AddAssert("mods not changed", () => SelectedMods.Value.Single() is TaikoModDoubleTime);
|
||||
}
|
||||
@@ -133,10 +140,42 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
// A previous test's mod overlay could still be fading out.
|
||||
AddUntilStep("wait for only one freemod overlay", () => this.ChildrenOfType<FreeModSelectOverlay>().Count() == 1);
|
||||
|
||||
AddStep("open free mod overlay", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeMods>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
assertFreeModNotShown(allowedMod);
|
||||
assertFreeModNotShown(requiredMod);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFreeModsDisplayedOnEnter()
|
||||
{
|
||||
AddStep("set room freemods", () =>
|
||||
{
|
||||
var editedItem = MultiplayerClient.ClientRoom!.CurrentPlaylistItem.Clone();
|
||||
|
||||
editedItem.AllowedMods =
|
||||
[
|
||||
new APIMod(new OsuModHardRock()),
|
||||
];
|
||||
|
||||
MultiplayerClient.EditPlaylistItem(editedItem);
|
||||
});
|
||||
|
||||
setUp();
|
||||
|
||||
AddStep("open free mod overlay", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeMods>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
assertFreeModShown(typeof(OsuModHardRock));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChangeRulesetImmediatelyAfterLoadComplete()
|
||||
{
|
||||
@@ -154,16 +193,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
songSelect.OnLoadComplete += _ => Ruleset.Value = new TaikoRuleset().RulesetInfo;
|
||||
LoadScreen(songSelect);
|
||||
});
|
||||
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && songSelect.BeatmapSetsLoaded);
|
||||
|
||||
AddStep("confirm selection", () => songSelect.FinaliseSelection());
|
||||
AddUntilStep("wait for present", () => songSelect.IsCurrentScreen() && !songSelect.IsFiltering);
|
||||
|
||||
AddStep("confirm selection", () => InputManager.Key(Key.Enter));
|
||||
AddAssert("beatmap is taiko", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID, () => Is.EqualTo(1));
|
||||
AddAssert("ruleset is taiko", () => Ruleset.Value.OnlineID, () => Is.EqualTo(1));
|
||||
}
|
||||
|
||||
private void assertFreeModShown(Type type)
|
||||
{
|
||||
AddUntilStep($"{type.ReadableName()} displayed in freemod overlay",
|
||||
() => this.ChildrenOfType<FreeModSelectOverlay>()
|
||||
.Single()
|
||||
.ChildrenOfType<ModPanel>()
|
||||
.Where(panel => panel.Visible)
|
||||
.Any(b => b.Mod.GetType() == type));
|
||||
}
|
||||
|
||||
private void assertFreeModNotShown(Type type)
|
||||
{
|
||||
AddAssert($"{type.ReadableName()} not displayed in freemod overlay",
|
||||
AddUntilStep($"{type.ReadableName()} not displayed in freemod overlay",
|
||||
() => this.ChildrenOfType<FreeModSelectOverlay>()
|
||||
.Single()
|
||||
.ChildrenOfType<ModPanel>()
|
||||
@@ -185,12 +235,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
public new Bindable<IReadOnlyList<Mod>> FreeMods => base.FreeMods;
|
||||
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
|
||||
public TestMultiplayerMatchSongSelect(Room room, PlaylistItem? itemToEdit = null)
|
||||
: base(room, itemToEdit)
|
||||
{
|
||||
}
|
||||
|
||||
public void SelectBeatmap(BeatmapInfo beatmap) => SelectAndRun(beatmap, () => { });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Tests.Gameplay;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
+5
-5
@@ -27,7 +27,7 @@ using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
public partial class TestScenePlaylistsSongSelectV2 : OnlinePlayTestScene
|
||||
public partial class TestScenePlaylistsSongSelect : OnlinePlayTestScene
|
||||
{
|
||||
private RulesetStore rulesets = null!;
|
||||
private BeatmapManager manager = null!;
|
||||
@@ -164,20 +164,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddAssert("freestyle enabled", () => songSelect.Freestyle.Value, () => Is.True);
|
||||
AddStep("click icon in free mods button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeModsV2>().Single());
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeMods>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("mod select not visible", () => this.ChildrenOfType<FreeModSelectOverlay>().Single().State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
|
||||
AddStep("toggle freestyle off", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreestyleV2>().Single());
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreestyle>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("freestyle disabled", () => songSelect.Freestyle.Value, () => Is.False);
|
||||
AddStep("click icon in free mods button", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeModsV2>().Single());
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<FooterButtonFreeMods>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("mod select visible", () => this.ChildrenOfType<FreeModSelectOverlay>().Single().State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
@@ -191,7 +191,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
rulesets.Dispose();
|
||||
}
|
||||
|
||||
private partial class TestPlaylistsSongSelect : PlaylistsSongSelectV2
|
||||
private partial class TestPlaylistsSongSelect : PlaylistsSongSelect
|
||||
{
|
||||
public new IBindable<bool> Freestyle => base.Freestyle;
|
||||
|
||||
@@ -26,8 +26,8 @@ using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.GameplayTest;
|
||||
using osu.Game.Screens.Edit.Setup;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK.Input;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
@@ -15,7 +15,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays.Settings.Sections.Input;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
|
||||
@@ -18,8 +18,8 @@ using osu.Game.Screens;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using FilterControl = osu.Game.Screens.SelectV2.FilterControl;
|
||||
using osu.Game.Screens.Select;
|
||||
using FilterControl = osu.Game.Screens.Select.FilterControl;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
|
||||
@@ -8,9 +8,13 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Footer;
|
||||
|
||||
@@ -23,10 +27,13 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestFooterButtonsOnScreenTransitions()
|
||||
{
|
||||
PushAndConfirm(() => new TestScreenOne());
|
||||
PushAndConfirm(() => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
||||
});
|
||||
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
PushAndConfirm(() => new TestScreenTwo());
|
||||
PushAndConfirm(() => new TestScreen { CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }] });
|
||||
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
||||
|
||||
AddStep("exit screen", () => Game.ScreenStack.Exit());
|
||||
@@ -40,7 +47,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
|
||||
PushAndConfirm(() => new TestScreen(true));
|
||||
PushAndConfirm(() => new TestScreen());
|
||||
AddAssert("footer shown", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
AddAssert("old back button hidden", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
|
||||
@@ -69,10 +76,16 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("footer hidden", () => screenFooter.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddAssert("old back button shown", () => Game.BackButton.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreenOne());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
||||
});
|
||||
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreenTwo());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
||||
});
|
||||
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
||||
|
||||
AddStep("exit sub screen", () => screen.ExitSubScreen());
|
||||
@@ -92,10 +105,16 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
TestScreenWithSubScreen screen = null!;
|
||||
|
||||
PushAndConfirm(() => screen = new TestScreenWithSubScreen());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreenOne());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
||||
});
|
||||
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
PushAndConfirm(() => new TestScreenTwo());
|
||||
PushAndConfirm(() => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
||||
});
|
||||
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
||||
|
||||
AddStep("exit parent screen", () => Game.ScreenStack.Exit());
|
||||
@@ -111,14 +130,23 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
TestScreenWithSubScreen screen = null!;
|
||||
|
||||
PushAndConfirm(() => screen = new TestScreenWithSubScreen());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreenOne());
|
||||
pushSubScreenAndConfirm(() => screen, () => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
||||
});
|
||||
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
PushAndConfirm(() => new TestScreenOne());
|
||||
PushAndConfirm(() => new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button One" }]
|
||||
});
|
||||
AddUntilStep("button one shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
// Can't use the helper method because the screen never loads
|
||||
AddStep("Push new sub screen", () => screen.PushSubScreen(new TestScreenTwo()));
|
||||
AddStep("Push new sub screen", () => screen.PushSubScreen(new TestScreen
|
||||
{
|
||||
CreateButtons = () => [new ScreenFooterButton { Text = "Button Two" }]
|
||||
}));
|
||||
AddWaitStep("wait for potential screen load", 5);
|
||||
AddUntilStep("button one still shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button One"));
|
||||
|
||||
@@ -126,6 +154,83 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddUntilStep("button two shown", () => screenFooter.ChildrenOfType<ScreenFooterButton>().First().Text.ToString(), () => Is.EqualTo("Button Two"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests clicking the back button while an overlay is open.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBackButtonWhenOverlayOpen()
|
||||
{
|
||||
TestScreen screen = null!;
|
||||
|
||||
PushAndConfirm(() =>
|
||||
{
|
||||
ShearedOverlayContainer overlay = new TestShearedOverlayContainer();
|
||||
|
||||
return screen = new TestScreen
|
||||
{
|
||||
Overlay = overlay,
|
||||
CreateButtons = () =>
|
||||
[
|
||||
new ScreenFooterButton(overlay)
|
||||
{
|
||||
AccentColour = Dependencies.Get<OsuColour>().Orange1,
|
||||
Icon = FontAwesome.Solid.Toolbox,
|
||||
Text = "One",
|
||||
},
|
||||
new ScreenFooterButton { Text = "Two", Action = () => { } },
|
||||
new ScreenFooterButton { Text = "Three", Action = () => { } },
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("show overlay", () => screen.Overlay.Show());
|
||||
AddAssert("overlay shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
|
||||
AddStep("press back", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
||||
AddAssert("overlay hidden", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddAssert("screen still shown", () => screen.IsCurrentScreen(), () => Is.True);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests clicking the back button on an overlay with `BackButtonPressed` being overridden.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestBackButtonWithCustomBackButtonPressed()
|
||||
{
|
||||
TestScreen screen = null!;
|
||||
TestShearedOverlayContainer overlay = null!;
|
||||
|
||||
PushAndConfirm(() =>
|
||||
{
|
||||
return screen = new TestScreen
|
||||
{
|
||||
Overlay = overlay = new TestShearedOverlayContainer(),
|
||||
CreateButtons = () =>
|
||||
[
|
||||
new ScreenFooterButton(overlay)
|
||||
{
|
||||
AccentColour = Dependencies.Get<OsuColour>().Orange1,
|
||||
Icon = FontAwesome.Solid.Toolbox,
|
||||
Text = "One",
|
||||
},
|
||||
new ScreenFooterButton { Text = "Two", Action = () => { } },
|
||||
new ScreenFooterButton { Text = "Three", Action = () => { } },
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("show overlay", () => screen.Overlay.Show());
|
||||
AddAssert("overlay shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
AddStep("set block count", () => overlay.BackButtonCount = 1);
|
||||
|
||||
AddStep("press back", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
||||
AddAssert("overlay still shown", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
|
||||
AddStep("press back again", () => screenFooter.ChildrenOfType<ScreenBackButton>().Single().TriggerClick());
|
||||
AddAssert("overlay hidden", () => screen.Overlay.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddAssert("screen still shown", () => screen.IsCurrentScreen(), () => Is.True);
|
||||
}
|
||||
|
||||
private void pushSubScreenAndConfirm(Func<TestScreenWithSubScreen> target, Func<Screen> newScreen)
|
||||
{
|
||||
Screen screen = null!;
|
||||
@@ -142,39 +247,45 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
&& (previousScreen == null || previousScreen.GetChildScreen() == screen));
|
||||
}
|
||||
|
||||
private partial class TestScreenOne : OsuScreen
|
||||
{
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => new[]
|
||||
{
|
||||
new ScreenFooterButton { Text = "Button One" },
|
||||
};
|
||||
}
|
||||
|
||||
private partial class TestScreenTwo : OsuScreen
|
||||
{
|
||||
public override bool ShowFooter => true;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => new[]
|
||||
{
|
||||
new ScreenFooterButton { Text = "Button Two" },
|
||||
};
|
||||
}
|
||||
|
||||
private partial class TestScreen : OsuScreen
|
||||
{
|
||||
public override bool ShowFooter { get; }
|
||||
|
||||
public TestScreen(bool footer)
|
||||
public Func<IReadOnlyList<ScreenFooterButton>> CreateButtons = Array.Empty<ScreenFooterButton>;
|
||||
|
||||
public ShearedOverlayContainer Overlay = new TestShearedOverlayContainer();
|
||||
|
||||
private IDisposable? overlayRegistration;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[Resolved]
|
||||
private IOverlayManager? overlayManager { get; set; }
|
||||
|
||||
public TestScreen(bool showFooter = true)
|
||||
{
|
||||
ShowFooter = footer;
|
||||
ShowFooter = showFooter;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponent(Overlay);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
overlayRegistration = overlayManager?.RegisterBlockingOverlay(Overlay);
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ScreenFooterButton> CreateFooterButtons() => CreateButtons.Invoke();
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
overlayRegistration?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,5 +307,66 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
public void ExitSubScreen() => SubScreenStack.Exit();
|
||||
}
|
||||
|
||||
private partial class TestShearedOverlayContainer : ShearedOverlayContainer
|
||||
{
|
||||
public TestShearedOverlayContainer()
|
||||
: base(OverlayColourScheme.Orange)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Header.Title = "Test overlay";
|
||||
Header.Description = "An overlay that is made purely for testing purposes.";
|
||||
}
|
||||
|
||||
public int BackButtonCount;
|
||||
|
||||
public override bool OnBackButton()
|
||||
{
|
||||
if (BackButtonCount > 0)
|
||||
{
|
||||
BackButtonCount--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override VisibilityContainer CreateFooterContent() => new TestFooterContent();
|
||||
|
||||
public partial class TestFooterContent : VisibilityContainer
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
new ShearedButton { Width = 200, Text = "Action #1", Action = () => { } },
|
||||
new ShearedButton { Width = 140, Text = "Action #2", Action = () => { } },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.MoveToY(0, 400, Easing.OutQuint)
|
||||
.FadeIn(400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
this.MoveToY(-20f, 200, Easing.OutQuint)
|
||||
.FadeOut(200, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,15 +48,16 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using CollectionDropdown = osu.Game.Screens.Select.CollectionDropdown;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
@@ -94,7 +95,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("edit playlist", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddUntilStep("wait for song select", () => playlistScreen.CurrentSubScreen is PlaylistsSongSelectV2 songSelect && songSelect.IsLoaded && !songSelect.IsFiltering);
|
||||
AddUntilStep("wait for song select", () => playlistScreen.CurrentSubScreen is PlaylistsSongSelect songSelect && songSelect.IsLoaded && !songSelect.IsFiltering);
|
||||
|
||||
AddUntilStep("wait for selection", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
@@ -109,7 +110,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for song select", () => playlistScreen.CurrentSubScreen is PlaylistsSongSelectV2 songSelect && songSelect.IsLoaded && !songSelect.IsFiltering);
|
||||
AddUntilStep("wait for song select", () => playlistScreen.CurrentSubScreen is PlaylistsSongSelect songSelect && songSelect.IsLoaded && !songSelect.IsFiltering);
|
||||
|
||||
AddStep("press home button", () =>
|
||||
{
|
||||
@@ -197,14 +198,14 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("set filter again", () => filterControlTextBox().Current.Value = "test");
|
||||
AddStep("open collections dropdown", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(songSelect.ChildrenOfType<Screens.SelectV2.CollectionDropdown>().Single());
|
||||
InputManager.MoveMouseTo(songSelect.ChildrenOfType<CollectionDropdown>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("press back once", () => InputManager.Click(MouseButton.Button1));
|
||||
AddAssert("still at song select", () => Game.ScreenStack.CurrentScreen == songSelect);
|
||||
AddAssert("collections dropdown closed", () => songSelect
|
||||
.ChildrenOfType<Screens.SelectV2.CollectionDropdown>().Single()
|
||||
.ChildrenOfType<CollectionDropdown>().Single()
|
||||
.ChildrenOfType<Dropdown<CollectionFilterMenuItem>.DropdownMenu>().Single().State == MenuState.Closed);
|
||||
|
||||
AddStep("press back a second time", () => InputManager.Click(MouseButton.Button1));
|
||||
@@ -317,7 +318,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestAttemptPlayBeatmapWrongHashFails()
|
||||
{
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
@@ -352,7 +353,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestAttemptPlayBeatmapMissingFails()
|
||||
{
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
@@ -386,7 +387,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -429,7 +430,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -483,7 +484,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -526,7 +527,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -1194,9 +1195,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("close settings sidebar", () => InputManager.Key(Key.Escape));
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
AddRepeatStep("go to solo", () => InputManager.Key(Key.P), 3);
|
||||
AddUntilStep("wait for song select", () => (songSelect = Game.ScreenStack.CurrentScreen as Screens.SelectV2.SongSelect) != null);
|
||||
AddUntilStep("wait for song select", () => (songSelect = Game.ScreenStack.CurrentScreen as Screens.Select.SongSelect) != null);
|
||||
AddUntilStep("wait for beatmap sets loaded", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("switch to osu! ruleset", () =>
|
||||
@@ -1281,7 +1282,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestExitSongSelectAndImmediatelyClickLogo()
|
||||
{
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -1312,7 +1313,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
BeatmapSetInfo beatmap = null;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
@@ -1371,7 +1372,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK;
|
||||
|
||||
@@ -24,17 +24,13 @@ using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests copied out of `TestSceneScreenNavigation` which are specific to song select.
|
||||
/// These are for SongSelectV2. Eventually, the tests in the above class should be deleted along with old song select.
|
||||
/// </summary>
|
||||
public partial class TestSceneSongSelectNavigation : OsuGameTestScene
|
||||
{
|
||||
[Test]
|
||||
@@ -277,7 +273,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
/// <summary>
|
||||
/// Note: This test was written to demonstrate the failure described at https://github.com/ppy/osu/issues/35023,
|
||||
/// but because the failure scenario there entailed a race condition, it was possible for the test to pass regardless
|
||||
/// unless <see cref="osu.Game.Screens.SelectV2.SongSelect.SELECTION_DEBOUNCE"/> was increased.
|
||||
/// unless <see cref="osu.Game.Screens.Select.SongSelect.SELECTION_DEBOUNCE"/> was increased.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPresentFromResults()
|
||||
|
||||
+2
-2
@@ -12,15 +12,15 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[System.ComponentModel.Description("Advanced beatmap statistics display")]
|
||||
public partial class TestSceneAdvancedStats : OsuTestScene
|
||||
@@ -22,7 +22,6 @@ using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.BeatmapSet.Scores;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
using APIUser = osu.Game.Online.API.Requests.Responses.APIUser;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
@@ -72,6 +71,10 @@ namespace osu.Game.Tests.Visual.Online
|
||||
Preview = @"https://b.ppy.sh/preview/12345.mp3",
|
||||
PlayCount = 123,
|
||||
FavouriteCount = 456,
|
||||
NominationStatus = new BeatmapSetNominationStatus
|
||||
{
|
||||
Current = 2,
|
||||
},
|
||||
Submitted = DateTime.Now,
|
||||
Ranked = DateTime.Now,
|
||||
BPM = 111,
|
||||
@@ -274,7 +277,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
public void TestSelectedModsDontAffectStatistics()
|
||||
{
|
||||
AddStep("show map", () => overlay.ShowBeatmapSet(getBeatmapSet()));
|
||||
AddAssert("AR displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((0, 0)));
|
||||
AddAssert("AR displayed as 7", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((7.0f, 7.0f)));
|
||||
AddStep("set AR10 diff adjust", () => SelectedMods.Value = new[]
|
||||
{
|
||||
new OsuModDifficultyAdjust
|
||||
@@ -282,7 +285,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
ApproachRate = { Value = 10 }
|
||||
}
|
||||
});
|
||||
AddAssert("AR still displayed as 0", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((0, 0)));
|
||||
AddAssert("AR still displayed as 7", () => overlay.ChildrenOfType<AdvancedStats.StatisticRow>().Single(s => s.Title == SongSelectStrings.ApproachRate).Value, () => Is.EqualTo((7.0f, 7.0f)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -12,7 +12,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Game.Screens.Select.Details;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Users.Drawables;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public partial class TestSceneClickableTeamFlag : OsuManualInputManagerTestScene
|
||||
{
|
||||
[SetUpSteps]
|
||||
public void SetUp()
|
||||
{
|
||||
AddStep("create flags", () =>
|
||||
{
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Spacing = new Vector2(10f),
|
||||
Children = new[]
|
||||
{
|
||||
new ClickableTeamFlag(
|
||||
new APITeam
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Collective Wangs",
|
||||
ShortName = "WANG",
|
||||
}, showTooltipOnHover: false) { Width = 300, Height = 150 },
|
||||
new ClickableTeamFlag(
|
||||
new APITeam
|
||||
{
|
||||
Id = 2,
|
||||
Name = "mom?",
|
||||
ShortName = "MOM",
|
||||
FlagUrl = "https://assets.ppy.sh/teams/flag/1/b46fb10dbfd8a35dc50e6c00296c0dc6172dffc3ed3d3a4b379277ba498399fe.png",
|
||||
}, showTooltipOnHover: true) { Width = 300, Height = 150 },
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHover()
|
||||
{
|
||||
AddStep("hover flag with no tooltip", () => InputManager.MoveMouseTo(this.ChildrenOfType<ClickableTeamFlag>().ElementAt(0)));
|
||||
AddWaitStep("wait", 3);
|
||||
AddAssert("tooltip is not visible", () => this.ChildrenOfType<OsuTooltipContainer.OsuTooltip>().FirstOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddStep("hover flag with tooltip", () => InputManager.MoveMouseTo(this.ChildrenOfType<ClickableTeamFlag>().ElementAt(1)));
|
||||
AddUntilStep("wait for tooltip to show", () => this.ChildrenOfType<OsuTooltipContainer.OsuTooltip>().FirstOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,16 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Metadata;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Dashboard;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Overlays.Dashboard.CurrentlyOnline;
|
||||
using osu.Game.Tests.Visual.Metadata;
|
||||
using osu.Game.Tests.Visual.Spectator;
|
||||
using osu.Game.Users;
|
||||
@@ -23,6 +21,26 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public partial class TestSceneCurrentlyOnlineDisplay : OsuTestScene
|
||||
{
|
||||
private static readonly string[] usernames =
|
||||
{
|
||||
"fieryrage",
|
||||
"Kerensa",
|
||||
"MillhioreF",
|
||||
"Player01",
|
||||
"smoogipoo",
|
||||
"Ephemeral",
|
||||
"BTMC",
|
||||
"Cilvery",
|
||||
"m980",
|
||||
"HappyStick",
|
||||
"LittleEndu",
|
||||
"frenzibyte",
|
||||
"Zallius",
|
||||
"BanchoBot",
|
||||
"rocketminer210",
|
||||
"pishifat"
|
||||
};
|
||||
|
||||
private readonly APIUser streamingUser = new APIUser { Id = 2, Username = "Test user" };
|
||||
|
||||
private TestSpectatorClient spectatorClient = null!;
|
||||
@@ -36,11 +54,34 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
spectatorClient = new TestSpectatorClient();
|
||||
metadataClient = new TestMetadataClient();
|
||||
var lookupCache = new TestUserLookupCache();
|
||||
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
{
|
||||
case LookupUsersRequest lookupUsersRequest:
|
||||
var users = lookupUsersRequest.UserIds.Select(id =>
|
||||
{
|
||||
// tests against failed lookups
|
||||
if (id == 13)
|
||||
return null;
|
||||
|
||||
return new APIUser
|
||||
{
|
||||
Id = id,
|
||||
Username = usernames[id % usernames.Length],
|
||||
};
|
||||
}).ToList();
|
||||
lookupUsersRequest.TriggerSuccess(new GetUsersResponse { Users = users });
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
lookupCache,
|
||||
spectatorClient,
|
||||
metadataClient,
|
||||
new DependencyProvidingContainer
|
||||
@@ -50,13 +91,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
(typeof(SpectatorClient), spectatorClient),
|
||||
(typeof(MetadataClient), metadataClient),
|
||||
(typeof(UserLookupCache), lookupCache),
|
||||
(typeof(OverlayColourProvider), new OverlayColourProvider(OverlayColourScheme.Purple)),
|
||||
},
|
||||
Child = currentlyOnline = new CurrentlyOnlineDisplay
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
Child = currentlyOnline = new CurrentlyOnlineDisplay()
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -69,17 +106,18 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddStep("Begin watching user presence", () => token = metadataClient.BeginWatchingUserPresence());
|
||||
AddStep("Add online user", () => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.ChoosingBeatmap() }));
|
||||
AddUntilStep("Panel loaded", () => currentlyOnline.ChildrenOfType<UserGridPanel>().FirstOrDefault()?.User.Id == 2);
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<PurpleRoundedButton>().First().Enabled.Value, () => Is.False);
|
||||
AddUntilStep("Panel loaded", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().FirstOrDefault()?.User.Id == 2);
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().First().CanSpectate.Value, () => Is.False);
|
||||
|
||||
AddStep("User began playing", () => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.InSoloGame() }));
|
||||
AddAssert("Spectate button enabled", () => currentlyOnline.ChildrenOfType<PurpleRoundedButton>().First().Enabled.Value, () => Is.True);
|
||||
AddAssert("Spectate button enabled", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().First().CanSpectate.Value, () => Is.True);
|
||||
|
||||
AddStep("User finished playing", () => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.ChoosingBeatmap() }));
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<PurpleRoundedButton>().First().Enabled.Value, () => Is.False);
|
||||
AddStep("User finished playing",
|
||||
() => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.ChoosingBeatmap() }));
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().First().CanSpectate.Value, () => Is.False);
|
||||
|
||||
AddStep("Remove playing user", () => metadataClient.UserPresenceUpdated(streamingUser.Id, null));
|
||||
AddUntilStep("Panel no longer present", () => !currentlyOnline.ChildrenOfType<UserGridPanel>().Any());
|
||||
AddUntilStep("Panel no longer present", () => !currentlyOnline.ChildrenOfType<OnlineUserPanel>().Any());
|
||||
AddStep("End watching user presence", () => token.Dispose());
|
||||
}
|
||||
|
||||
@@ -90,49 +128,14 @@ namespace osu.Game.Tests.Visual.Online
|
||||
|
||||
AddStep("Begin watching user presence", () => token = metadataClient.BeginWatchingUserPresence());
|
||||
AddStep("Add online user", () => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.InSoloGame() }));
|
||||
AddUntilStep("Panel loaded", () => currentlyOnline.ChildrenOfType<UserGridPanel>().FirstOrDefault()?.User.Id == streamingUser.Id);
|
||||
AddAssert("Spectate button enabled", () => currentlyOnline.ChildrenOfType<PurpleRoundedButton>().First().Enabled.Value, () => Is.True);
|
||||
AddUntilStep("Panel loaded", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().FirstOrDefault()?.User.Id == streamingUser.Id);
|
||||
AddAssert("Spectate button enabled", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().First().CanSpectate.Value, () => Is.True);
|
||||
|
||||
AddStep("User finished playing", () => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.ChoosingBeatmap() }));
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<PurpleRoundedButton>().First().Enabled.Value, () => Is.False);
|
||||
AddStep("User finished playing",
|
||||
() => metadataClient.UserPresenceUpdated(streamingUser.Id, new UserPresence { Status = UserStatus.Online, Activity = new UserActivity.ChoosingBeatmap() }));
|
||||
AddAssert("Spectate button disabled", () => currentlyOnline.ChildrenOfType<OnlineUserPanel>().First().CanSpectate.Value, () => Is.False);
|
||||
AddStep("Remove playing user", () => metadataClient.UserPresenceUpdated(streamingUser.Id, null));
|
||||
AddStep("End watching user presence", () => token.Dispose());
|
||||
}
|
||||
|
||||
internal partial class TestUserLookupCache : UserLookupCache
|
||||
{
|
||||
private static readonly string[] usernames =
|
||||
{
|
||||
"fieryrage",
|
||||
"Kerensa",
|
||||
"MillhioreF",
|
||||
"Player01",
|
||||
"smoogipoo",
|
||||
"Ephemeral",
|
||||
"BTMC",
|
||||
"Cilvery",
|
||||
"m980",
|
||||
"HappyStick",
|
||||
"LittleEndu",
|
||||
"frenzibyte",
|
||||
"Zallius",
|
||||
"BanchoBot",
|
||||
"rocketminer210",
|
||||
"pishifat"
|
||||
};
|
||||
|
||||
protected override Task<APIUser?> ComputeValueAsync(int lookup, CancellationToken token = default)
|
||||
{
|
||||
// tests against failed lookups
|
||||
if (lookup == 13)
|
||||
return Task.FromResult<APIUser?>(null);
|
||||
|
||||
return Task.FromResult<APIUser?>(new APIUser
|
||||
{
|
||||
Id = lookup,
|
||||
Username = usernames[lookup % usernames.Length],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.Play.Leaderboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Metadata;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Dashboard.CurrentlyOnline;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Tests.Visual.Metadata;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public partial class TestSceneOnlineUserPanel : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
[Resolved]
|
||||
private IRulesetStore rulesetStore { get; set; } = null!;
|
||||
|
||||
private TestMetadataClient metadataClient = null!;
|
||||
private OnlineUserListPanel panel = null!;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Child = new DependencyProvidingContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CachedDependencies =
|
||||
[
|
||||
(typeof(MetadataClient), metadataClient = new TestMetadataClient())
|
||||
],
|
||||
Children = new Drawable[]
|
||||
{
|
||||
metadataClient,
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Spacing = new Vector2(10f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OnlineUserGridPanel(new APIUser
|
||||
{
|
||||
Username = @"flyte",
|
||||
Id = 3103765,
|
||||
CountryCode = CountryCode.JP,
|
||||
CoverUrl = @"https://assets.ppy.sh/user-cover-presets/1/df28696b58541a9e67f6755918951d542d93bdf1da41720fcca2fd2c1ea8cf51.jpeg",
|
||||
WasRecentlyOnline = true
|
||||
}),
|
||||
new OnlineUserGridPanel(new APIUser
|
||||
{
|
||||
Username = @"peppy",
|
||||
Id = 2,
|
||||
CountryCode = CountryCode.AU,
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg",
|
||||
IsSupporter = true,
|
||||
SupportLevel = 3,
|
||||
}),
|
||||
new OnlineUserListPanel(new APIUser
|
||||
{
|
||||
Username = @"flyte",
|
||||
Id = 3103765,
|
||||
CountryCode = CountryCode.JP,
|
||||
CoverUrl = @"https://assets.ppy.sh/user-cover-presets/1/df28696b58541a9e67f6755918951d542d93bdf1da41720fcca2fd2c1ea8cf51.jpeg",
|
||||
WasRecentlyOnline = true
|
||||
}),
|
||||
panel = new OnlineUserListPanel(new APIUser
|
||||
{
|
||||
Username = @"peppy",
|
||||
Id = 2,
|
||||
CountryCode = CountryCode.AU,
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg",
|
||||
LastVisit = DateTimeOffset.Now
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
metadataClient.BeginWatchingUserPresence();
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestUserActivity()
|
||||
{
|
||||
AddStep("idle", () => setPresence(UserStatus.Online, null));
|
||||
AddStep("in game", () => setPresence(UserStatus.Online, new UserActivity.InSoloGame(new BeatmapInfo(), rulesetStore.GetRuleset(0)!)));
|
||||
}
|
||||
|
||||
private void setPresence(UserStatus status, UserActivity? activity, int? userId = null)
|
||||
{
|
||||
if (status == UserStatus.Offline)
|
||||
metadataClient.UserPresenceUpdated(userId ?? panel.User.OnlineID, null);
|
||||
else
|
||||
metadataClient.UserPresenceUpdated(userId ?? panel.User.OnlineID, new UserPresence { Status = status, Activity = activity });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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.Online.API.Requests.Responses;
|
||||
using osu.Game.Users.Drawables;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public partial class TestSceneUpdateableTeamFlag : OsuTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestHideOnNull()
|
||||
{
|
||||
UpdateableTeamFlag flag = null!;
|
||||
|
||||
AddStep("create flag with team", () => Child = flag = new UpdateableTeamFlag(createTeam(), hideOnNull: true) { Width = 300, Height = 150 });
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
AddStep("set team to null", () => flag.Team = null);
|
||||
AddAssert("flag is not present", () => flag.IsPresent, () => Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DontHideOnNull()
|
||||
{
|
||||
UpdateableTeamFlag flag = null!;
|
||||
|
||||
AddStep("create flag with team", () => Child = flag = new UpdateableTeamFlag(createTeam(), hideOnNull: false) { Width = 300, Height = 150 });
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
AddStep("set team to null", () => flag.Team = null);
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
}
|
||||
|
||||
private static APITeam createTeam() => new APITeam
|
||||
{
|
||||
Id = 2,
|
||||
Name = "mom?",
|
||||
ShortName = "MOM",
|
||||
FlagUrl = @"https://assets.ppy.sh/teams/flag/1/b46fb10dbfd8a35dc50e6c00296c0dc6172dffc3ed3d3a4b379277ba498399fe.png",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -240,6 +240,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
CoverUrl = TestResources.COVER_IMAGE_1,
|
||||
JoinDate = DateTimeOffset.Now.AddDays(-1),
|
||||
LastVisit = DateTimeOffset.Now,
|
||||
PreviousUsernames = ["ForgetMe", "MySpaceLover", "i once was a man named enis", "mr anderson"],
|
||||
Groups = new[]
|
||||
{
|
||||
new APIUserGroup { Colour = "#EB47D0", ShortName = "DEV", Name = "Developers" },
|
||||
|
||||
@@ -116,6 +116,33 @@ needs_cleanup: true
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOutdatedNoticeBoxWithSuffixComments()
|
||||
{
|
||||
AddStep("Add outdated yaml with comments", () =>
|
||||
{
|
||||
markdownContainer.Text = @"---
|
||||
outdated: true # not sure about the format for ""list of mods"".
|
||||
---";
|
||||
});
|
||||
|
||||
AddAssert("Outdated notice box visible", () => markdownContainer.ChildrenOfType<Container>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCommentedOutFrontMatter()
|
||||
{
|
||||
AddStep("Add commented out front matter", () =>
|
||||
{
|
||||
markdownContainer.Text = @"---
|
||||
#outdated: true
|
||||
# outdated: true
|
||||
---";
|
||||
});
|
||||
|
||||
AddAssert("No notice box visible", () => !markdownContainer.ChildrenOfType<Container>().Any());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAbsoluteImage()
|
||||
{
|
||||
|
||||
@@ -17,13 +17,13 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
[Cached]
|
||||
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
|
||||
|
||||
private readonly FooterButtonFreeModsV2 button;
|
||||
private readonly FooterButtonFreeMods button;
|
||||
|
||||
public TestSceneFooterButtonFreeModsV2()
|
||||
{
|
||||
ModSelectOverlay modSelectOverlay;
|
||||
Add(modSelectOverlay = new TestModSelectOverlay());
|
||||
Add(button = new FooterButtonFreeModsV2(modSelectOverlay)
|
||||
Add(button = new FooterButtonFreeMods(modSelectOverlay)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreLeft,
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
public TestSceneFooterButtonFreestyleV2()
|
||||
{
|
||||
Add(new FooterButtonFreestyleV2
|
||||
Add(new FooterButtonFreestyle
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreLeft,
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("add tray", () => Child = new PlaylistsSongSelectV2.PlaylistTray(room = new Room())
|
||||
AddStep("add tray", () => Child = new PlaylistsSongSelect.PlaylistTray(room = new Room())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
|
||||
@@ -13,11 +13,11 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -34,6 +34,7 @@ using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual.OnlinePlay;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
@@ -215,6 +216,85 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
AddUntilStep("second beatmap selected", () => Beatmap.Value.BeatmapInfo.Equals(importedSet.Beatmaps[0]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFreestyleSelectAbort()
|
||||
{
|
||||
Room room = null!;
|
||||
|
||||
AddStep("add room", () =>
|
||||
{
|
||||
room = new Room
|
||||
{
|
||||
RoomID = 1,
|
||||
Playlist =
|
||||
[
|
||||
new PlaylistItem(importedSet.Beatmaps[0])
|
||||
{
|
||||
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||
Freestyle = true
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
API.Perform(new CreateRoomRequest(room));
|
||||
});
|
||||
|
||||
TestPlaylistsScreen playlistsScreen = null!;
|
||||
|
||||
AddStep("load screen", () => LoadScreen(playlistsScreen = new TestPlaylistsScreen(new TestPlaylistsRoomSubScreen(room))));
|
||||
AddUntilStep("wait for playlist room screen", () => playlistsScreen.Stack.CurrentScreen is PlaylistsRoomSubScreen roomSubScreen && roomSubScreen.IsLoaded);
|
||||
|
||||
AddUntilStep("original beatmap", () => Beatmap.Value.BeatmapInfo.Equals(importedSet.Beatmaps[0]));
|
||||
|
||||
AddStep("enter freestyle select", () => playlistsScreen.Stack.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistEditButton>().Single(b => b.IsPresent).TriggerClick());
|
||||
AddUntilStep("wait for select screen", () => playlistsScreen.Stack.CurrentScreen is PlaylistsRoomFreestyleSelect selectScreen && selectScreen.CarouselItemsPresented);
|
||||
|
||||
AddStep("select next beatmap", () => InputManager.Key(Key.Down));
|
||||
AddStep("abort", () => playlistsScreen.Stack.CurrentScreen.Exit());
|
||||
|
||||
AddUntilStep("beatmap not changed", () => Beatmap.Value.BeatmapInfo.Equals(importedSet.Beatmaps[0]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFreestyleSelect()
|
||||
{
|
||||
Room room = null!;
|
||||
|
||||
AddStep("add room", () =>
|
||||
{
|
||||
room = new Room
|
||||
{
|
||||
RoomID = 1,
|
||||
Playlist =
|
||||
[
|
||||
new PlaylistItem(importedSet.Beatmaps[0])
|
||||
{
|
||||
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
|
||||
Freestyle = true
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
API.Perform(new CreateRoomRequest(room));
|
||||
});
|
||||
|
||||
TestPlaylistsScreen playlistsScreen = null!;
|
||||
|
||||
AddStep("load screen", () => LoadScreen(playlistsScreen = new TestPlaylistsScreen(new TestPlaylistsRoomSubScreen(room))));
|
||||
AddUntilStep("wait for playlist room screen", () => playlistsScreen.Stack.CurrentScreen is PlaylistsRoomSubScreen roomSubScreen && roomSubScreen.IsLoaded);
|
||||
|
||||
AddUntilStep("original beatmap", () => Beatmap.Value.BeatmapInfo.Equals(importedSet.Beatmaps[0]));
|
||||
|
||||
AddStep("enter freestyle select", () => playlistsScreen.Stack.ChildrenOfType<DrawableRoomPlaylistItem.PlaylistEditButton>().Single(b => b.IsPresent).TriggerClick());
|
||||
AddUntilStep("wait for select screen", () => playlistsScreen.Stack.CurrentScreen is PlaylistsRoomFreestyleSelect selectScreen && selectScreen.CarouselItemsPresented);
|
||||
|
||||
AddStep("select next beatmap", () => InputManager.Key(Key.Down));
|
||||
AddStep("select (beatmap)", () => InputManager.Key(Key.Enter));
|
||||
AddStep("select (exit screen)", () => InputManager.Key(Key.Enter));
|
||||
|
||||
AddUntilStep("beatmap changed", () => Beatmap.Value.BeatmapInfo.Equals(importedSet.Beatmaps[1]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that the ruleset style is reset when the selected item is changed and it's no longer valid.
|
||||
/// </summary>
|
||||
@@ -591,30 +671,16 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
|
||||
private partial class TestPlaylistsScreen : OsuScreen
|
||||
{
|
||||
public readonly OnlinePlaySubScreenStack Stack;
|
||||
|
||||
public TestPlaylistsScreen(PlaylistsRoomSubScreen screen)
|
||||
{
|
||||
OnlinePlaySubScreenStack stack;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
InternalChild = Stack = new OnlinePlaySubScreenStack
|
||||
{
|
||||
stack = new OnlinePlaySubScreenStack
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
new BackButton
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
State = { Value = Visibility.Visible },
|
||||
Action = () =>
|
||||
{
|
||||
if (stack.CurrentScreen is not PlaylistsRoomSubScreen)
|
||||
stack.Exit();
|
||||
}
|
||||
}
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
|
||||
stack.Push(screen);
|
||||
Stack.Push(screen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public abstract partial class RankedPlayTestScene : MultiplayerTestScene
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns 5 sample <see cref="APIBeatmap"/>s.
|
||||
/// </summary>
|
||||
protected static APIBeatmap[] GetSampleBeatmaps()
|
||||
{
|
||||
using var resourceStream = TestResources.OpenResource("Requests/api-beatmaps-rankedplay.json");
|
||||
using var reader = new StreamReader(resourceStream);
|
||||
|
||||
return JsonConvert.DeserializeObject<APIBeatmap[]>(reader.ReadToEnd())!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A request handler that will resolve api requests to any beatmaps provided by <see cref="GetSampleBeatmaps"/>.
|
||||
/// </summary>
|
||||
public class BeatmapRequestHandler
|
||||
{
|
||||
public readonly APIBeatmap[] Beatmaps = GetSampleBeatmaps();
|
||||
|
||||
public bool HandleRequest(APIRequest request)
|
||||
{
|
||||
switch (request)
|
||||
{
|
||||
case GetBeatmapRequest beatmapRequest:
|
||||
var beatmap = Beatmaps.FirstOrDefault(it => it.OnlineID == beatmapRequest.OnlineID);
|
||||
|
||||
if (beatmap != null)
|
||||
{
|
||||
beatmapRequest.TriggerSuccess(beatmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GetBeatmapsRequest beatmapsRequest:
|
||||
beatmapsRequest.TriggerSuccess(new GetBeatmapsResponse
|
||||
{
|
||||
Beatmaps = beatmapsRequest
|
||||
.BeatmapIds
|
||||
.Select(id => Beatmaps.FirstOrDefault(it => it.OnlineID == id))
|
||||
.ToList()
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class RevealedRankedPlayCardWithPlaylistItem : RankedPlayCardWithPlaylistItem
|
||||
{
|
||||
public RevealedRankedPlayCardWithPlaylistItem(APIBeatmap beatmap, RankedPlayCardItem? card = null)
|
||||
: base(card ?? new RankedPlayCardItem())
|
||||
{
|
||||
PlaylistItem.Value = new MultiplayerPlaylistItem(new PlaylistItem(beatmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneDiscardScreen : MultiplayerTestScene
|
||||
{
|
||||
private RankedPlayScreen screen = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add other user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)));
|
||||
|
||||
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
|
||||
AddUntilStep("screen loaded", () => screen.IsLoaded);
|
||||
|
||||
AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardDiscard).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneEndedScreen : MultiplayerTestScene
|
||||
{
|
||||
private RankedPlayScreen screen = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add other user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)));
|
||||
|
||||
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
|
||||
AddUntilStep("screen loaded", () => screen.IsLoaded);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVictory()
|
||||
{
|
||||
AddStep("set results state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.Ended, s =>
|
||||
{
|
||||
s.WinningUserId = API.LocalUser.Value.OnlineID;
|
||||
s.Users[API.LocalUser.Value.OnlineID].RatingAfter = 1520;
|
||||
s.Users[2].RatingAfter = 1480;
|
||||
}).WaitSafely());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDefeat()
|
||||
{
|
||||
AddStep("set results state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.Ended, s =>
|
||||
{
|
||||
s.WinningUserId = 2;
|
||||
s.Users[API.LocalUser.Value.OnlineID].RatingAfter = 1480;
|
||||
s.Users[2].RatingAfter = 1520;
|
||||
}).WaitSafely());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDraw()
|
||||
{
|
||||
AddStep("set results state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.Ended, s =>
|
||||
{
|
||||
s.Users[API.LocalUser.Value.OnlineID].RatingAfter = 1480;
|
||||
s.Users[2].RatingAfter = 1520;
|
||||
}).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneGameplayWarmupScreen : MultiplayerTestScene
|
||||
{
|
||||
private RankedPlayScreen screen = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () =>
|
||||
{
|
||||
var beatmap = new TestBeatmap(Ruleset.Value).BeatmapInfo;
|
||||
beatmap.StarRating = 2;
|
||||
|
||||
var room = CreateDefaultRoom(MatchType.RankedPlay);
|
||||
room.Playlist =
|
||||
[
|
||||
new PlaylistItem(beatmap)
|
||||
{
|
||||
RulesetID = Ruleset.Value.OnlineID
|
||||
}
|
||||
];
|
||||
|
||||
JoinRoom(room);
|
||||
});
|
||||
|
||||
WaitForJoined();
|
||||
AddStep("add other user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)));
|
||||
|
||||
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
|
||||
AddUntilStep("screen loaded", () => screen.IsLoaded);
|
||||
AddStep("play card", () => MultiplayerClient.PlayCard(new RankedPlayCardItem()));
|
||||
|
||||
AddStep("set warmup state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.GameplayWarmup).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Hand;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneHandReplay : MultiplayerTestScene
|
||||
{
|
||||
private PlayerHandOfCards playerHand = null!;
|
||||
private OpponentHandOfCards opponentHand = null!;
|
||||
private TestHandReplayRecorder recorder = null!;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Pink);
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("setup", () =>
|
||||
{
|
||||
var cards = Enumerable.Range(0, 5)
|
||||
.Select(_ => new RankedPlayCardWithPlaylistItem(new RankedPlayCardItem()))
|
||||
.ToArray();
|
||||
|
||||
Children =
|
||||
[
|
||||
playerHand = new PlayerHandOfCards
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.5f),
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
SelectionMode = HandSelectionMode.Multiple
|
||||
},
|
||||
opponentHand = new OpponentHandOfCards
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.5f),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
},
|
||||
new HandReplayPlayer(API.LocalUser.Value.OnlineID, opponentHand),
|
||||
recorder = new TestHandReplayRecorder(playerHand)
|
||||
{
|
||||
FlushInterval = flushInterval,
|
||||
RecordInterval = recordInterval,
|
||||
}
|
||||
];
|
||||
|
||||
foreach (var card in cards)
|
||||
{
|
||||
playerHand.AddCard(card);
|
||||
opponentHand.AddCard(card);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private double flushInterval = 1000;
|
||||
private double recordInterval = 25;
|
||||
private double fixedLatency;
|
||||
private double maxLatency;
|
||||
|
||||
[Test]
|
||||
public void TestCardHandReplay()
|
||||
{
|
||||
AddSliderStep("record interval", 0.0, 1000.0, 25.0, value =>
|
||||
{
|
||||
recordInterval = value;
|
||||
recreateRecorder();
|
||||
});
|
||||
AddSliderStep("flush interval", 0.0, 5000.0, 1000.0, value =>
|
||||
{
|
||||
flushInterval = value;
|
||||
recreateRecorder();
|
||||
});
|
||||
AddSliderStep("latency", 0.0, 5000.0, 0.0, value =>
|
||||
{
|
||||
fixedLatency = value;
|
||||
recreateRecorder();
|
||||
});
|
||||
AddSliderStep("randomize latency", 0.0, 5000.0, 0.0, value =>
|
||||
{
|
||||
maxLatency = value;
|
||||
recreateRecorder();
|
||||
});
|
||||
}
|
||||
|
||||
private void recreateRecorder()
|
||||
{
|
||||
if (recorder.IsNotNull())
|
||||
{
|
||||
Remove(recorder, true);
|
||||
Add(recorder = new TestHandReplayRecorder(playerHand)
|
||||
{
|
||||
FlushInterval = flushInterval,
|
||||
RecordInterval = recordInterval,
|
||||
FixedLatency = fixedLatency,
|
||||
RandomLatency = maxLatency,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private partial class TestHandReplayRecorder(PlayerHandOfCards handOfCards) : HandReplayRecorder(handOfCards)
|
||||
{
|
||||
private double lastSendTime;
|
||||
|
||||
public double FixedLatency;
|
||||
|
||||
public double RandomLatency;
|
||||
|
||||
protected override void Flush(RankedPlayCardHandReplayFrame[] frames)
|
||||
{
|
||||
double sendTime = Math.Max(lastSendTime, Time.Current + FixedLatency + RNG.NextDouble(RandomLatency));
|
||||
|
||||
lastSendTime = sendTime;
|
||||
|
||||
Scheduler.AddDelayed(() => base.Flush(frames), sendTime - Time.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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.Online.API.Requests.Responses;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro;
|
||||
using osu.Game.Tests.Visual.Matchmaking;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneIntroScreen : MatchmakingTestScene
|
||||
{
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
IntroScreen introScreen = null!;
|
||||
|
||||
AddStep("Add screen", () => Child = introScreen = new IntroScreen());
|
||||
|
||||
AddStep("play animation", () => introScreen.PlayIntroSequence(
|
||||
new UserWithRating(new APIUser
|
||||
{
|
||||
Id = 2,
|
||||
Username = "User 1",
|
||||
CoverUrl = "https://assets.ppy.sh/user-profile-covers/13845312/53e4eda7ad3ce41f0990c041179d8ab5d553fef988835f346a8d8da0482506ec.png"
|
||||
}, 1234),
|
||||
new UserWithRating(new APIUser
|
||||
{
|
||||
Id = 3,
|
||||
Username = "User 2",
|
||||
CoverUrl = "https://assets.ppy.sh/user-profile-covers/14102976/10144df2f1c6fb2101726e0f89087a6061bc75755d88e59a9faf2c84034f2c71.jpeg"
|
||||
}, 1234),
|
||||
6.3f
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestSceneOpponentPickScreen : MultiplayerTestScene
|
||||
{
|
||||
private RankedPlayScreen screen = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add other user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)));
|
||||
|
||||
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
|
||||
AddUntilStep("screen loaded", () => screen.IsLoaded);
|
||||
|
||||
AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = 2).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.RankedPlay;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay;
|
||||
using osu.Game.Tests.Visual.Multiplayer;
|
||||
|
||||
namespace osu.Game.Tests.Visual.RankedPlay
|
||||
{
|
||||
public partial class TestScenePickScreen : MultiplayerTestScene
|
||||
{
|
||||
private RankedPlayScreen screen = null!;
|
||||
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("join room", () => JoinRoom(CreateDefaultRoom(MatchType.RankedPlay)));
|
||||
WaitForJoined();
|
||||
|
||||
AddStep("add other user", () => MultiplayerClient.AddUser(new MultiplayerRoomUser(2)));
|
||||
|
||||
AddStep("load screen", () => LoadScreen(screen = new RankedPlayScreen(MultiplayerClient.ClientRoom!)));
|
||||
AddUntilStep("screen loaded", () => screen.IsLoaded);
|
||||
|
||||
AddStep("set pick state", () => MultiplayerClient.RankedPlayChangeStage(RankedPlayStage.CardPlay, state => state.ActiveUserId = API.LocalUser.Value.OnlineID).WaitSafely());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user