mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
同步更新,Ez设置大优化,增强兼容官方数据库
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.625.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.704.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
{
|
||||
"solution": {
|
||||
"path": "osu.sln",
|
||||
"projects": [
|
||||
"..\\osu-resources\\osu.Game.Resources\\osu.Game.Resources.csproj",
|
||||
"osu.Desktop\\osu.Desktop.csproj",
|
||||
"osu.Game.Benchmarks\\osu.Game.Benchmarks.csproj",
|
||||
"osu.Game.Rulesets.Catch.Tests\\osu.Game.Rulesets.Catch.Tests.csproj",
|
||||
"osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj",
|
||||
"osu.Game.Rulesets.Mania.Tests\\osu.Game.Rulesets.Mania.Tests.csproj",
|
||||
"osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj",
|
||||
"osu.Game.Rulesets.Osu.Tests\\osu.Game.Rulesets.Osu.Tests.csproj",
|
||||
"osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj",
|
||||
"osu.Game.Rulesets.Taiko.Tests\\osu.Game.Rulesets.Taiko.Tests.csproj",
|
||||
"osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj",
|
||||
"osu.Game.Tests\\osu.Game.Tests.csproj",
|
||||
"osu.Game.Tournament.Tests\\osu.Game.Tournament.Tests.csproj",
|
||||
"osu.Game.Tournament\\osu.Game.Tournament.csproj",
|
||||
"osu.Game\\osu.Game.csproj",
|
||||
"Templates\\Rulesets\\ruleset-empty\\osu.Game.Rulesets.EmptyFreeform.Tests\\osu.Game.Rulesets.EmptyFreeform.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-empty\\osu.Game.Rulesets.EmptyFreeform\\osu.Game.Rulesets.EmptyFreeform.csproj",
|
||||
"Templates\\Rulesets\\ruleset-example\\osu.Game.Rulesets.Pippidon.Tests\\osu.Game.Rulesets.Pippidon.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling.Tests\\osu.Game.Rulesets.EmptyScrolling.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling\\osu.Game.Rulesets.EmptyScrolling.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon.Tests\\osu.Game.Rulesets.Pippidon.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
"solution": {
|
||||
"path": "osu.sln",
|
||||
"projects": [
|
||||
"..\\osu-resources\\osu.Game.Resources\\osu.Game.Resources.csproj",
|
||||
"osu.Desktop\\osu.Desktop.csproj",
|
||||
"osu.Game.Benchmarks\\osu.Game.Benchmarks.csproj",
|
||||
"osu.Game.Rulesets.Catch.Tests\\osu.Game.Rulesets.Catch.Tests.csproj",
|
||||
"osu.Game.Rulesets.Catch\\osu.Game.Rulesets.Catch.csproj",
|
||||
"osu.Game.Rulesets.Mania.Tests\\osu.Game.Rulesets.Mania.Tests.csproj",
|
||||
"osu.Game.Rulesets.Mania\\osu.Game.Rulesets.Mania.csproj",
|
||||
"osu.Game.Rulesets.Osu.Tests\\osu.Game.Rulesets.Osu.Tests.csproj",
|
||||
"osu.Game.Rulesets.Osu\\osu.Game.Rulesets.Osu.csproj",
|
||||
"osu.Game.Rulesets.Taiko.Tests\\osu.Game.Rulesets.Taiko.Tests.csproj",
|
||||
"osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj",
|
||||
"osu.Game.Tests\\osu.Game.Tests.csproj",
|
||||
"osu.Game.Tournament.Tests\\osu.Game.Tournament.Tests.csproj",
|
||||
"osu.Game.Tournament\\osu.Game.Tournament.csproj",
|
||||
"osu.Game\\osu.Game.csproj",
|
||||
"Templates\\Rulesets\\ruleset-empty\\osu.Game.Rulesets.EmptyFreeform.Tests\\osu.Game.Rulesets.EmptyFreeform.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-empty\\osu.Game.Rulesets.EmptyFreeform\\osu.Game.Rulesets.EmptyFreeform.csproj",
|
||||
"Templates\\Rulesets\\ruleset-example\\osu.Game.Rulesets.Pippidon.Tests\\osu.Game.Rulesets.Pippidon.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling.Tests\\osu.Game.Rulesets.EmptyScrolling.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling\\osu.Game.Rulesets.EmptyScrolling.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon.Tests\\osu.Game.Rulesets.Pippidon.Tests.csproj",
|
||||
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj",
|
||||
"../osu-framework/osu.Framework/osu.Framework.csproj",
|
||||
"../osu-framework/osu.Framework.NativeLibs/osu.Framework.NativeLibs.csproj"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||
<AssemblyName>osu!</AssemblyName>
|
||||
<AssemblyTitle>osu!(lazer)</AssemblyTitle>
|
||||
<Title>osu!</Title>
|
||||
<Product>osu!(lazer)</Product>
|
||||
<AssemblyName>Ez2osu!</AssemblyName>
|
||||
<AssemblyTitle>osu!(Ez2lazer)</AssemblyTitle>
|
||||
<Title>Ez2lazer!</Title>
|
||||
<Product>osu!(Ez2lazer)</Product>
|
||||
<ApplicationIcon>lazer.ico</ApplicationIcon>
|
||||
<Version>0.0.0</Version>
|
||||
<FileVersion>0.0.0</FileVersion>
|
||||
@@ -15,6 +15,11 @@
|
||||
<PropertyGroup>
|
||||
<StartupObject>osu.Desktop.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<!-- <PropertyGroup Condition="'$(Configuration)'=='Release' OR '$(Configuration)'=='Debug'">-->
|
||||
<PropertyGroup>
|
||||
<PublishDir>F:\MUG OSU\Ez2Lazer_Publish\$(Configuration)</PublishDir>
|
||||
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -219,5 +220,40 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
distanceSnapGrid.StartTime = sourceHitObject.GetEndTime();
|
||||
distanceSnapGrid.StartX = sourceHitObject.EffectiveX;
|
||||
}
|
||||
|
||||
#region Clipboard handling
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
||||
|
||||
// 1,2,3,4 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||
|
||||
public override void SelectFromTimestamp(double timestamp, string objectDescription)
|
||||
{
|
||||
if (!selection_regex.IsMatch(objectDescription))
|
||||
return;
|
||||
|
||||
List<CatchHitObject> remainingHitObjects = EditorBeatmap.HitObjects.Cast<CatchHitObject>().Where(h => h.StartTime >= timestamp).ToList();
|
||||
string[] splitDescription = objectDescription.Split(',');
|
||||
|
||||
for (int i = 0; i < splitDescription.Length; i++)
|
||||
{
|
||||
if (!int.TryParse(splitDescription[i], out int combo) || combo < 1)
|
||||
continue;
|
||||
|
||||
CatchHitObject? current = remainingHitObjects.FirstOrDefault(h => h.IndexInCurrentCombo + 1 == combo);
|
||||
|
||||
if (current == null)
|
||||
continue;
|
||||
|
||||
EditorBeatmap.SelectedHitObjects.Add(current);
|
||||
|
||||
if (i < splitDescription.Length - 1)
|
||||
remainingHitObjects = remainingHitObjects.Where(h => h != current && h.StartTime >= current.StartTime).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UserAdjustedSettingsCount != 1)
|
||||
if (!IsExactlyOneSettingChanged(CircleSize, ApproachRate, OverallDifficulty, DrainRate))
|
||||
return string.Empty;
|
||||
|
||||
if (!CircleSize.IsDefault) return format("CS", CircleSize);
|
||||
|
||||
@@ -19,7 +19,6 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneLegacyReplayPlayback : LegacyReplayPlaybackTestScene
|
||||
{
|
||||
protected override Ruleset CreateRuleset() => new ManiaRuleset();
|
||||
@@ -72,13 +71,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -137d, HitResult.Miss },
|
||||
new object[] { 5f, -138d, HitResult.Miss },
|
||||
new object[] { 5f, 111d, HitResult.Ok },
|
||||
new object[] { 5f, 112d, HitResult.Miss },
|
||||
new object[] { 5f, 113d, HitResult.Miss },
|
||||
new object[] { 5f, 114d, HitResult.Miss },
|
||||
new object[] { 5f, 135d, HitResult.Miss },
|
||||
new object[] { 5f, 136d, HitResult.Miss },
|
||||
new object[] { 5f, 137d, HitResult.Miss },
|
||||
new object[] { 5f, 138d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 112d, HitResult.Miss },
|
||||
// new object[] { 5f, 113d, HitResult.Miss },
|
||||
// new object[] { 5f, 114d, HitResult.Miss },
|
||||
// new object[] { 5f, 135d, HitResult.Miss },
|
||||
// new object[] { 5f, 136d, HitResult.Miss },
|
||||
// new object[] { 5f, 137d, HitResult.Miss },
|
||||
// new object[] { 5f, 138d, HitResult.Miss },
|
||||
|
||||
// OD = 9.3 test cases.
|
||||
// PERFECT hit window is [ -14ms, 14ms]
|
||||
@@ -99,13 +99,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 9.3f, 70d, HitResult.Ok },
|
||||
new object[] { 9.3f, 71d, HitResult.Ok },
|
||||
new object[] { 9.3f, 98d, HitResult.Ok },
|
||||
new object[] { 9.3f, 99d, HitResult.Miss },
|
||||
new object[] { 9.3f, 100d, HitResult.Miss },
|
||||
new object[] { 9.3f, 101d, HitResult.Miss },
|
||||
new object[] { 9.3f, 122d, HitResult.Miss },
|
||||
new object[] { 9.3f, 123d, HitResult.Miss },
|
||||
new object[] { 9.3f, 124d, HitResult.Miss },
|
||||
new object[] { 9.3f, 125d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 9.3f, 99d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 100d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 101d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 122d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 123d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 124d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 125d, HitResult.Miss },
|
||||
new object[] { 9.3f, -98d, HitResult.Ok },
|
||||
new object[] { 9.3f, -99d, HitResult.Ok },
|
||||
new object[] { 9.3f, -100d, HitResult.Meh },
|
||||
@@ -145,13 +146,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -137d, HitResult.Miss },
|
||||
new object[] { 5f, -138d, HitResult.Miss },
|
||||
new object[] { 5f, 111d, HitResult.Ok },
|
||||
new object[] { 5f, 112d, HitResult.Miss },
|
||||
new object[] { 5f, 113d, HitResult.Miss },
|
||||
new object[] { 5f, 114d, HitResult.Miss },
|
||||
new object[] { 5f, 135d, HitResult.Miss },
|
||||
new object[] { 5f, 136d, HitResult.Miss },
|
||||
new object[] { 5f, 137d, HitResult.Miss },
|
||||
new object[] { 5f, 138d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 112d, HitResult.Miss },
|
||||
// new object[] { 5f, 113d, HitResult.Miss },
|
||||
// new object[] { 5f, 114d, HitResult.Miss },
|
||||
// new object[] { 5f, 135d, HitResult.Miss },
|
||||
// new object[] { 5f, 136d, HitResult.Miss },
|
||||
// new object[] { 5f, 137d, HitResult.Miss },
|
||||
// new object[] { 5f, 138d, HitResult.Miss },
|
||||
|
||||
// OD = 9.3 test cases.
|
||||
// PERFECT hit window is [ -16ms, 16ms]
|
||||
@@ -172,13 +174,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 9.3f, 70d, HitResult.Ok },
|
||||
new object[] { 9.3f, 71d, HitResult.Ok },
|
||||
new object[] { 9.3f, 98d, HitResult.Ok },
|
||||
new object[] { 9.3f, 99d, HitResult.Miss },
|
||||
new object[] { 9.3f, 100d, HitResult.Miss },
|
||||
new object[] { 9.3f, 101d, HitResult.Miss },
|
||||
new object[] { 9.3f, 122d, HitResult.Miss },
|
||||
new object[] { 9.3f, 123d, HitResult.Miss },
|
||||
new object[] { 9.3f, 124d, HitResult.Miss },
|
||||
new object[] { 9.3f, 125d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 9.3f, 99d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 100d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 101d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 122d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 123d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 124d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 125d, HitResult.Miss },
|
||||
new object[] { 9.3f, -98d, HitResult.Ok },
|
||||
new object[] { 9.3f, -99d, HitResult.Ok },
|
||||
new object[] { 9.3f, -100d, HitResult.Meh },
|
||||
@@ -207,13 +210,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 3.1f, 88d, HitResult.Ok },
|
||||
new object[] { 3.1f, 89d, HitResult.Ok },
|
||||
new object[] { 3.1f, 116d, HitResult.Ok },
|
||||
new object[] { 3.1f, 117d, HitResult.Miss },
|
||||
new object[] { 3.1f, 118d, HitResult.Miss },
|
||||
new object[] { 3.1f, 119d, HitResult.Miss },
|
||||
new object[] { 3.1f, 140d, HitResult.Miss },
|
||||
new object[] { 3.1f, 141d, HitResult.Miss },
|
||||
new object[] { 3.1f, 142d, HitResult.Miss },
|
||||
new object[] { 3.1f, 143d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 3.1f, 117d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 118d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 119d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 140d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 141d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 142d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 143d, HitResult.Miss },
|
||||
new object[] { 3.1f, -116d, HitResult.Ok },
|
||||
new object[] { 3.1f, -117d, HitResult.Ok },
|
||||
new object[] { 3.1f, -118d, HitResult.Meh },
|
||||
@@ -253,13 +257,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -122d, HitResult.Miss },
|
||||
new object[] { 5f, -123d, HitResult.Miss },
|
||||
new object[] { 5f, 96d, HitResult.Ok },
|
||||
new object[] { 5f, 97d, HitResult.Miss },
|
||||
new object[] { 5f, 98d, HitResult.Miss },
|
||||
new object[] { 5f, 99d, HitResult.Miss },
|
||||
new object[] { 5f, 120d, HitResult.Miss },
|
||||
new object[] { 5f, 121d, HitResult.Miss },
|
||||
new object[] { 5f, 122d, HitResult.Miss },
|
||||
new object[] { 5f, 123d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 97d, HitResult.Miss },
|
||||
// new object[] { 5f, 98d, HitResult.Miss },
|
||||
// new object[] { 5f, 99d, HitResult.Miss },
|
||||
// new object[] { 5f, 120d, HitResult.Miss },
|
||||
// new object[] { 5f, 121d, HitResult.Miss },
|
||||
// new object[] { 5f, 122d, HitResult.Miss },
|
||||
// new object[] { 5f, 123d, HitResult.Miss },
|
||||
|
||||
// OD = 3.1 test cases.
|
||||
// PERFECT hit window is [ -16ms, 16ms]
|
||||
@@ -280,13 +285,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 3.1f, 78d, HitResult.Ok },
|
||||
new object[] { 3.1f, 79d, HitResult.Ok },
|
||||
new object[] { 3.1f, 96d, HitResult.Ok },
|
||||
new object[] { 3.1f, 97d, HitResult.Miss },
|
||||
new object[] { 3.1f, 98d, HitResult.Miss },
|
||||
new object[] { 3.1f, 99d, HitResult.Miss },
|
||||
new object[] { 3.1f, 120d, HitResult.Miss },
|
||||
new object[] { 3.1f, 121d, HitResult.Miss },
|
||||
new object[] { 3.1f, 122d, HitResult.Miss },
|
||||
new object[] { 3.1f, 123d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 3.1f, 97d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 98d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 99d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 120d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 121d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 122d, HitResult.Miss },
|
||||
// new object[] { 3.1f, 123d, HitResult.Miss },
|
||||
new object[] { 3.1f, -96d, HitResult.Ok },
|
||||
new object[] { 3.1f, -97d, HitResult.Ok },
|
||||
new object[] { 3.1f, -98d, HitResult.Meh },
|
||||
@@ -327,13 +333,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -98d, HitResult.Miss },
|
||||
new object[] { 5f, -99d, HitResult.Miss },
|
||||
new object[] { 5f, 79d, HitResult.Ok },
|
||||
new object[] { 5f, 80d, HitResult.Miss },
|
||||
new object[] { 5f, 81d, HitResult.Miss },
|
||||
new object[] { 5f, 82d, HitResult.Miss },
|
||||
new object[] { 5f, 96d, HitResult.Miss },
|
||||
new object[] { 5f, 97d, HitResult.Miss },
|
||||
new object[] { 5f, 98d, HitResult.Miss },
|
||||
new object[] { 5f, 99d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 80d, HitResult.Miss },
|
||||
// new object[] { 5f, 81d, HitResult.Miss },
|
||||
// new object[] { 5f, 82d, HitResult.Miss },
|
||||
// new object[] { 5f, 96d, HitResult.Miss },
|
||||
// new object[] { 5f, 97d, HitResult.Miss },
|
||||
// new object[] { 5f, 98d, HitResult.Miss },
|
||||
// new object[] { 5f, 99d, HitResult.Miss },
|
||||
|
||||
// OD = 9.3 test cases.
|
||||
// This leads to "effective" OD of 13.02.
|
||||
@@ -356,13 +363,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 9.3f, 50d, HitResult.Ok },
|
||||
new object[] { 9.3f, 51d, HitResult.Ok },
|
||||
new object[] { 9.3f, 69d, HitResult.Ok },
|
||||
new object[] { 9.3f, 70d, HitResult.Miss },
|
||||
new object[] { 9.3f, 71d, HitResult.Miss },
|
||||
new object[] { 9.3f, 72d, HitResult.Miss },
|
||||
new object[] { 9.3f, 86d, HitResult.Miss },
|
||||
new object[] { 9.3f, 87d, HitResult.Miss },
|
||||
new object[] { 9.3f, 88d, HitResult.Miss },
|
||||
new object[] { 9.3f, 89d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 9.3f, 70d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 71d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 72d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 86d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 87d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 88d, HitResult.Miss },
|
||||
// new object[] { 9.3f, 89d, HitResult.Miss },
|
||||
new object[] { 9.3f, -69d, HitResult.Ok },
|
||||
new object[] { 9.3f, -70d, HitResult.Ok },
|
||||
new object[] { 9.3f, -71d, HitResult.Meh },
|
||||
@@ -402,13 +410,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -191d, HitResult.Miss },
|
||||
new object[] { 5f, -192d, HitResult.Miss },
|
||||
new object[] { 5f, 155d, HitResult.Ok },
|
||||
new object[] { 5f, 156d, HitResult.Miss },
|
||||
new object[] { 5f, 157d, HitResult.Miss },
|
||||
new object[] { 5f, 158d, HitResult.Miss },
|
||||
new object[] { 5f, 189d, HitResult.Miss },
|
||||
new object[] { 5f, 190d, HitResult.Miss },
|
||||
new object[] { 5f, 191d, HitResult.Miss },
|
||||
new object[] { 5f, 192d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 156d, HitResult.Miss },
|
||||
// new object[] { 5f, 157d, HitResult.Miss },
|
||||
// new object[] { 5f, 158d, HitResult.Miss },
|
||||
// new object[] { 5f, 189d, HitResult.Miss },
|
||||
// new object[] { 5f, 190d, HitResult.Miss },
|
||||
// new object[] { 5f, 191d, HitResult.Miss },
|
||||
// new object[] { 5f, 192d, HitResult.Miss },
|
||||
};
|
||||
|
||||
private static readonly object[][] score_v1_non_convert_double_time_test_cases =
|
||||
@@ -440,13 +449,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -205d, HitResult.Miss },
|
||||
new object[] { 5f, -206d, HitResult.Miss },
|
||||
new object[] { 5f, 167d, HitResult.Ok },
|
||||
new object[] { 5f, 168d, HitResult.Miss },
|
||||
new object[] { 5f, 169d, HitResult.Miss },
|
||||
new object[] { 5f, 170d, HitResult.Miss },
|
||||
new object[] { 5f, 203d, HitResult.Miss },
|
||||
new object[] { 5f, 204d, HitResult.Miss },
|
||||
new object[] { 5f, 205d, HitResult.Miss },
|
||||
new object[] { 5f, 206d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 168d, HitResult.Miss },
|
||||
// new object[] { 5f, 169d, HitResult.Miss },
|
||||
// new object[] { 5f, 170d, HitResult.Miss },
|
||||
// new object[] { 5f, 203d, HitResult.Miss },
|
||||
// new object[] { 5f, 204d, HitResult.Miss },
|
||||
// new object[] { 5f, 205d, HitResult.Miss },
|
||||
// new object[] { 5f, 206d, HitResult.Miss },
|
||||
};
|
||||
|
||||
private static readonly object[][] score_v1_non_convert_half_time_test_cases =
|
||||
@@ -478,13 +488,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
new object[] { 5f, -103d, HitResult.Miss },
|
||||
new object[] { 5f, -104d, HitResult.Miss },
|
||||
new object[] { 5f, 83d, HitResult.Ok },
|
||||
new object[] { 5f, 84d, HitResult.Miss },
|
||||
new object[] { 5f, 85d, HitResult.Miss },
|
||||
new object[] { 5f, 86d, HitResult.Miss },
|
||||
new object[] { 5f, 101d, HitResult.Miss },
|
||||
new object[] { 5f, 102d, HitResult.Miss },
|
||||
new object[] { 5f, 103d, HitResult.Miss },
|
||||
new object[] { 5f, 104d, HitResult.Miss },
|
||||
// coverage of broken "can't hit meh late" behaviour, which is intentionally not being reproduced
|
||||
// new object[] { 5f, 84d, HitResult.Miss },
|
||||
// new object[] { 5f, 85d, HitResult.Miss },
|
||||
// new object[] { 5f, 86d, HitResult.Miss },
|
||||
// new object[] { 5f, 101d, HitResult.Miss },
|
||||
// new object[] { 5f, 102d, HitResult.Miss },
|
||||
// new object[] { 5f, 103d, HitResult.Miss },
|
||||
// new object[] { 5f, 104d, HitResult.Miss },
|
||||
};
|
||||
|
||||
private const double note_time = 300;
|
||||
@@ -517,6 +528,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV2 single note @ OD{overallDifficulty}", beatmap, $@"SV2 {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_non_convert_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1NonConvert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
@@ -544,6 +556,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV1 single note @ OD{overallDifficulty}", beatmap, $@"SV1 {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_convert_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1Convert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
@@ -572,6 +585,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV1 convert single note @ OD{overallDifficulty}", beatmap, $@"SV1 convert {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_non_convert_hard_rock_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1AndHardRockNonConvert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
@@ -600,6 +614,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV1+HR single note @ OD{overallDifficulty}", beatmap, $@"SV1+HR {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_non_convert_easy_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1AndEasyNonConvert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
@@ -628,6 +643,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV1+EZ single note @ OD{overallDifficulty}", beatmap, $@"SV1+EZ {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_non_convert_double_time_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1AndDoubleTimeNonConvert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
@@ -656,6 +672,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
RunTest($@"SV1+DT single note @ OD{overallDifficulty}", beatmap, $@"SV1+DT {hitOffset}ms @ OD{overallDifficulty} = {expectedResult}", score, [expectedResult]);
|
||||
}
|
||||
|
||||
[Ignore("Tests expected to fail until stable's detailed treatment of hit windows in mania is reproduced.")]
|
||||
[TestCaseSource(nameof(score_v1_non_convert_half_time_test_cases))]
|
||||
public void TestHitWindowTreatmentWithScoreV1AndHalfTimeNonConvert(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneReplayStability : ReplayStabilityTestScene
|
||||
{
|
||||
private static readonly object[][] test_cases =
|
||||
@@ -22,87 +21,79 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
// while round brackets `()` represent *open* or *exclusive* bounds.
|
||||
|
||||
// OD = 5 test cases.
|
||||
// PERFECT hit window is [ -19.4ms, 19.4ms]
|
||||
// GREAT hit window is [ -49.0ms, 49.0ms]
|
||||
// GOOD hit window is [ -82.0ms, 82.0ms]
|
||||
// OK hit window is [-112.0ms, 112.0ms]
|
||||
// MEH hit window is [-136.0ms, 136.0ms]
|
||||
// MISS hit window is [-173.0ms, 173.0ms]
|
||||
// PERFECT hit window is [ -19.5ms, 19.5ms]
|
||||
// GREAT hit window is [ -49.5ms, 49.5ms]
|
||||
// GOOD hit window is [ -82.5ms, 82.5ms]
|
||||
// OK hit window is [-112.5ms, 112.5ms]
|
||||
// MEH hit window is [-136.5ms, 136.5ms]
|
||||
// MISS hit window is [-173.5ms, 173.5ms]
|
||||
new object[] { 5f, -19d, HitResult.Perfect },
|
||||
new object[] { 5f, -19.2d, HitResult.Perfect },
|
||||
new object[] { 5f, -19.38d, HitResult.Perfect },
|
||||
// new object[] { 5f, -19.4d, HitResult.Perfect }, <- in theory this should work, in practice it does not (fails even before encode & rounding due to floating point precision issues)
|
||||
new object[] { 5f, -19.44d, HitResult.Great },
|
||||
new object[] { 5f, -19.7d, HitResult.Great },
|
||||
new object[] { 5f, -20d, HitResult.Great },
|
||||
new object[] { 5f, -48d, HitResult.Great },
|
||||
new object[] { 5f, -48.4d, HitResult.Great },
|
||||
new object[] { 5f, -48.7d, HitResult.Great },
|
||||
new object[] { 5f, -49d, HitResult.Great },
|
||||
new object[] { 5f, -49.2d, HitResult.Good },
|
||||
new object[] { 5f, -49.2d, HitResult.Great },
|
||||
new object[] { 5f, -49.7d, HitResult.Good },
|
||||
new object[] { 5f, -50d, HitResult.Good },
|
||||
new object[] { 5f, -81d, HitResult.Good },
|
||||
new object[] { 5f, -81.2d, HitResult.Good },
|
||||
new object[] { 5f, -81.7d, HitResult.Good },
|
||||
new object[] { 5f, -82d, HitResult.Good },
|
||||
new object[] { 5f, -82.2d, HitResult.Ok },
|
||||
new object[] { 5f, -82.2d, HitResult.Good },
|
||||
new object[] { 5f, -82.7d, HitResult.Ok },
|
||||
new object[] { 5f, -83d, HitResult.Ok },
|
||||
new object[] { 5f, -111d, HitResult.Ok },
|
||||
new object[] { 5f, -111.2d, HitResult.Ok },
|
||||
new object[] { 5f, -111.7d, HitResult.Ok },
|
||||
new object[] { 5f, -112d, HitResult.Ok },
|
||||
new object[] { 5f, -112.2d, HitResult.Meh },
|
||||
new object[] { 5f, -112.2d, HitResult.Ok },
|
||||
new object[] { 5f, -112.7d, HitResult.Meh },
|
||||
new object[] { 5f, -113d, HitResult.Meh },
|
||||
new object[] { 5f, -135d, HitResult.Meh },
|
||||
new object[] { 5f, -135.2d, HitResult.Meh },
|
||||
new object[] { 5f, -135.8d, HitResult.Meh },
|
||||
new object[] { 5f, -136d, HitResult.Meh },
|
||||
new object[] { 5f, -136.2d, HitResult.Miss },
|
||||
new object[] { 5f, -136.2d, HitResult.Meh },
|
||||
new object[] { 5f, -136.7d, HitResult.Miss },
|
||||
new object[] { 5f, -137d, HitResult.Miss },
|
||||
|
||||
// OD = 9.3 test cases.
|
||||
// PERFECT hit window is [ -14.67ms, 14.67ms]
|
||||
// GREAT hit window is [ -36.10ms, 36.10ms]
|
||||
// GOOD hit window is [ -69.10ms, 69.10ms]
|
||||
// OK hit window is [ -99.10ms, 99.10ms]
|
||||
// MEH hit window is [-123.10ms, 123.10ms]
|
||||
// MISS hit window is [-160.10ms, 160.10ms]
|
||||
// PERFECT hit window is [ -14.5ms, 14.5ms]
|
||||
// GREAT hit window is [ -36.5ms, 36.5ms]
|
||||
// GOOD hit window is [ -69.5ms, 69.5ms]
|
||||
// OK hit window is [ -99.5ms, 99.5ms]
|
||||
// MEH hit window is [-123.5ms, 123.5ms]
|
||||
// MISS hit window is [-160.5ms, 160.5ms]
|
||||
new object[] { 9.3f, 14d, HitResult.Perfect },
|
||||
new object[] { 9.3f, 14.2d, HitResult.Perfect },
|
||||
new object[] { 9.3f, 14.6d, HitResult.Perfect },
|
||||
// new object[] { 9.3f, 14.67d, HitResult.Perfect }, <- in theory this should work, in practice it does not (fails even before encode & rounding due to floating point precision issues)
|
||||
new object[] { 9.3f, 14.7d, HitResult.Great },
|
||||
new object[] { 9.3f, 15d, HitResult.Great },
|
||||
new object[] { 9.3f, 35d, HitResult.Great },
|
||||
new object[] { 9.3f, 35.3d, HitResult.Great },
|
||||
new object[] { 9.3f, 35.8d, HitResult.Great },
|
||||
new object[] { 9.3f, 36.05d, HitResult.Great },
|
||||
new object[] { 9.3f, 36.3d, HitResult.Good },
|
||||
new object[] { 9.3f, 36.3d, HitResult.Great },
|
||||
new object[] { 9.3f, 36.7d, HitResult.Good },
|
||||
new object[] { 9.3f, 37d, HitResult.Good },
|
||||
new object[] { 9.3f, 68d, HitResult.Good },
|
||||
new object[] { 9.3f, 68.4d, HitResult.Good },
|
||||
new object[] { 9.3f, 68.9d, HitResult.Good },
|
||||
new object[] { 9.3f, 69.07d, HitResult.Good },
|
||||
new object[] { 9.3f, 69.25d, HitResult.Ok },
|
||||
new object[] { 9.3f, 69.25d, HitResult.Good },
|
||||
new object[] { 9.3f, 69.85d, HitResult.Ok },
|
||||
new object[] { 9.3f, 70d, HitResult.Ok },
|
||||
new object[] { 9.3f, 98d, HitResult.Ok },
|
||||
new object[] { 9.3f, 98.3d, HitResult.Ok },
|
||||
new object[] { 9.3f, 98.6d, HitResult.Ok },
|
||||
new object[] { 9.3f, 99d, HitResult.Ok },
|
||||
new object[] { 9.3f, 99.3d, HitResult.Meh },
|
||||
new object[] { 9.3f, 99.3d, HitResult.Ok },
|
||||
new object[] { 9.3f, 99.7d, HitResult.Meh },
|
||||
new object[] { 9.3f, 100d, HitResult.Meh },
|
||||
new object[] { 9.3f, 122d, HitResult.Meh },
|
||||
new object[] { 9.3f, 122.34d, HitResult.Meh },
|
||||
new object[] { 9.3f, 122.57d, HitResult.Meh },
|
||||
new object[] { 9.3f, 123.04d, HitResult.Meh },
|
||||
new object[] { 9.3f, 123.45d, HitResult.Miss },
|
||||
new object[] { 9.3f, 123.45d, HitResult.Meh },
|
||||
new object[] { 9.3f, 123.95d, HitResult.Miss },
|
||||
new object[] { 9.3f, 124d, HitResult.Miss },
|
||||
};
|
||||
@@ -110,7 +101,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
[TestCaseSource(nameof(test_cases))]
|
||||
public void TestHitWindowStability(float overallDifficulty, double hitOffset, HitResult expectedResult)
|
||||
{
|
||||
const double note_time = 100;
|
||||
const double note_time = 300;
|
||||
|
||||
var beatmap = new ManiaBeatmap(new StageDefinition(1))
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Configuration.Tracking;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Configuration
|
||||
@@ -24,16 +23,14 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
{
|
||||
base.InitialiseDefaults();
|
||||
|
||||
SetDefault(ManiaRulesetSetting.ColumnWidth, 46, 9, 90, 1.0);
|
||||
SetDefault(ManiaRulesetSetting.SpecialFactor, 1, 0.1, 4, 0.1);
|
||||
// SetDefault(ManiaRulesetSetting.HitMode, MUGHitMode.EZ2AC);
|
||||
SetDefault(ManiaRulesetSetting.ScrollSpeed, 200, 1.0, 401.0, current_scroll_speed_precision);
|
||||
SetDefault(ManiaRulesetSetting.ScrollBaseSpeed, 500, 100, 1000, 1.0);
|
||||
SetDefault(ManiaRulesetSetting.ScrollTimePerSpeed, 5, 1.0, 40, 1.0);
|
||||
SetDefault(ManiaRulesetSetting.ScrollStyle, EzManiaScrollingStyle.ScrollTimeStyleFixed);
|
||||
|
||||
SetDefault(ManiaRulesetSetting.ScrollPerKeyMode, false);
|
||||
SetDefault(ManiaRulesetSetting.PerspectiveAngle, 90.0f, 30.0f, 90.0f);
|
||||
SetDefault(ManiaRulesetSetting.ScrollSpeed, 200, 1.0, 401.0, current_scroll_speed_precision);
|
||||
SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down);
|
||||
SetDefault(ManiaRulesetSetting.TimingBasedNoteColouring, false);
|
||||
SetDefault(ManiaRulesetSetting.MobileLayout, ManiaMobileLayout.Portrait);
|
||||
@@ -56,34 +53,20 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
|
||||
public enum ManiaRulesetSetting
|
||||
{
|
||||
[Obsolete("Use ScrollSpeed instead.")] // Can be removed 2023-11-30
|
||||
ScrollStyle,
|
||||
ScrollTime,
|
||||
ScrollBaseSpeed,
|
||||
ScrollTimePerSpeed,
|
||||
ScrollStyle,
|
||||
// HitMode,
|
||||
|
||||
// HitMode,
|
||||
//暂时无用
|
||||
PerspectiveAngle,
|
||||
ColumnWidth,
|
||||
SpecialFactor,
|
||||
ScrollPerKeyMode,
|
||||
|
||||
//官方设置
|
||||
ScrollSpeed,
|
||||
ScrollDirection,
|
||||
TimingBasedNoteColouring,
|
||||
MobileLayout,
|
||||
}
|
||||
|
||||
public enum EzManiaScrollingStyle
|
||||
{
|
||||
// [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionUp))]
|
||||
[Description("40速 通配速度风格(不可用)")]
|
||||
ScrollSpeedStyle,
|
||||
|
||||
// [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionDown))]
|
||||
[Description("ms值 恒定速度")]
|
||||
ScrollTimeStyle,
|
||||
|
||||
[Description("ms值 恒定时间")]
|
||||
ScrollTimeStyleFixed,
|
||||
}
|
||||
}
|
||||
|
||||
21
osu.Game.Rulesets.Mania/LAsEZMania/EzManiaEnums.cs
Normal file
21
osu.Game.Rulesets.Mania/LAsEZMania/EzManiaEnums.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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.ComponentModel;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.LAsEZMania
|
||||
{
|
||||
public enum EzManiaScrollingStyle
|
||||
{
|
||||
// [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionUp))]
|
||||
[Description("40速 通配速度风格(不可用)")]
|
||||
ScrollSpeedStyle,
|
||||
|
||||
// [LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.ScrollingDirectionDown))]
|
||||
[Description("ms值 相对默认判定线")]
|
||||
ScrollTimeStyle,
|
||||
|
||||
[Description("ms值 相对屏幕底部")]
|
||||
ScrollTimeStyleFixed,
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays.Settings.Sections.Gameplay;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
|
||||
@@ -64,7 +65,7 @@ namespace osu.Game.Rulesets.Mania.LAsEZMania
|
||||
float width = (float)columnWidth.Value;
|
||||
int index = KeyFlow.IndexOf(counter);
|
||||
|
||||
if (StageDefinition.EzIsSpecialColumn(index))
|
||||
if (EzColumnTypeManager.GetColumnType(StageDefinition.Columns, index) == "S1")
|
||||
width *= (float)specialFactor.Value;
|
||||
|
||||
counter.Width = width;
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
@@ -86,13 +87,19 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
case Ez2Skin:
|
||||
if (GlobalConfigStore.EzConfig == null)
|
||||
throw new ArgumentNullException(nameof(GlobalConfigStore.Config));
|
||||
{
|
||||
Logger.Log("!EGlobalConfigStore.EzConfig", LoggingTarget.Runtime, LogLevel.Important);
|
||||
break;
|
||||
}
|
||||
|
||||
return new ManiaEz2SkinTransformer(skin, beatmap, GlobalConfigStore.EzConfig);
|
||||
|
||||
case EzStyleProSkin:
|
||||
if (GlobalConfigStore.EzConfig == null)
|
||||
throw new ArgumentNullException(nameof(GlobalConfigStore.Config));
|
||||
{
|
||||
Logger.Log("!GlobalConfigStore.EzConfig", LoggingTarget.Runtime, LogLevel.Important);
|
||||
break;
|
||||
}
|
||||
|
||||
return new ManiaEzStyleProSkinTransformer(skin, beatmap, GlobalConfigStore.EzConfig);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
@@ -45,17 +46,19 @@ namespace osu.Game.Rulesets.Mania
|
||||
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollSpeed),
|
||||
KeyboardStep = 1,
|
||||
},
|
||||
new SettingsSlider<double, ManiaScrollBaseSpeedSlider>
|
||||
new SettingsSlider<double, ManiaScrollBaseSlider>
|
||||
{
|
||||
LabelText = "Scroll Base MS (when 200 Speed)",
|
||||
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollBaseSpeed),
|
||||
KeyboardStep = 1,
|
||||
Keywords = new[] { "base" }
|
||||
},
|
||||
new SettingsSlider<double, ManiaScrollTimePerSpeedSlider>
|
||||
new SettingsSlider<double, ManiaScrollMsPerSpeedSlider>
|
||||
{
|
||||
LabelText = "MS / Scroll Speed",
|
||||
LabelText = "MS / Speed",
|
||||
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollTimePerSpeed),
|
||||
KeyboardStep = 1,
|
||||
Keywords = new[] { "mps" }
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
@@ -85,20 +88,63 @@ namespace osu.Game.Rulesets.Mania
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(
|
||||
(int)DrawableManiaRuleset.ComputeScrollTime(Current.Value, config.Get<double>(ManiaRulesetSetting.ScrollBaseSpeed), config.Get<double>(ManiaRulesetSetting.ScrollTimePerSpeed)),
|
||||
Current.Value
|
||||
);
|
||||
public override LocalisableString TooltipText
|
||||
{
|
||||
get
|
||||
{
|
||||
double baseSpeed = config.Get<double>(ManiaRulesetSetting.ScrollBaseSpeed);
|
||||
double timePerSpeed = config.Get<double>(ManiaRulesetSetting.ScrollTimePerSpeed);
|
||||
int computedTime = (int)DrawableManiaRuleset.ComputeScrollTime(Current.Value, baseSpeed, timePerSpeed);
|
||||
LocalisableString speedInfo = RulesetSettingsStrings.ScrollSpeedTooltip(computedTime, Current.Value);
|
||||
return $"{baseSpeed}base - ( {Current.Value} - 200) * {timePerSpeed}mps\n = {speedInfo}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private partial class ManiaScrollBaseSpeedSlider : RoundedSliderBar<double>
|
||||
private partial class ManiaScrollBaseSlider : RoundedSliderBar<double>
|
||||
{
|
||||
public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip(
|
||||
(int)Current.Value, 200);
|
||||
private ManiaRulesetConfigManager config = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ManiaRulesetConfigManager config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override LocalisableString TooltipText
|
||||
{
|
||||
get
|
||||
{
|
||||
double speed = config.Get<double>(ManiaRulesetSetting.ScrollSpeed);
|
||||
double timePerSpeed = config.Get<double>(ManiaRulesetSetting.ScrollTimePerSpeed);
|
||||
int computedTime = (int)DrawableManiaRuleset.ComputeScrollTime(speed, Current.Value, timePerSpeed);
|
||||
LocalisableString speedInfo = RulesetSettingsStrings.ScrollSpeedTooltip(computedTime, speed);
|
||||
return $"{Current.Value}base - ( {speed} - 200) * {timePerSpeed}mps\n = {speedInfo}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private partial class ManiaScrollTimePerSpeedSlider : RoundedSliderBar<double>
|
||||
private partial class ManiaScrollMsPerSpeedSlider : RoundedSliderBar<double>
|
||||
{
|
||||
private ManiaRulesetConfigManager config = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ManiaRulesetConfigManager config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override LocalisableString TooltipText
|
||||
{
|
||||
get
|
||||
{
|
||||
double speed = config.Get<double>(ManiaRulesetSetting.ScrollSpeed);
|
||||
double baseSpeed = config.Get<double>(ManiaRulesetSetting.ScrollBaseSpeed);
|
||||
int computedTime = (int)DrawableManiaRuleset.ComputeScrollTime(speed, baseSpeed, Current.Value);
|
||||
LocalisableString speedInfo = RulesetSettingsStrings.ScrollSpeedTooltip(computedTime, speed);
|
||||
return $"{baseSpeed}base - ( {speed} - 200) * {Current.Value}mps\n = {speedInfo}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace osu.Game.Rulesets.Mania.Mods.LAsMods
|
||||
hitWindows.SetDifficulty(difficulty.OverallDifficulty);
|
||||
}
|
||||
|
||||
public override void ResetHitWindows()
|
||||
public override void ResetSettingsToDefaults()
|
||||
{
|
||||
hitWindows.ResetHitWindows();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Mania.Mods.YuLiangSSSMods
|
||||
HitWindows.SetDifficulty(difficulty.OverallDifficulty);
|
||||
}
|
||||
|
||||
public override void ResetHitWindows()
|
||||
public override void ResetSettingsToDefaults()
|
||||
{
|
||||
HitWindows.ResetHitWindows();
|
||||
}
|
||||
|
||||
@@ -55,12 +55,12 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
|
||||
public override void SetDifficulty(double difficulty)
|
||||
{
|
||||
perfect = IBeatmapDifficultyInfo.DifficultyRange(difficulty, perfect_window_range) * multiplier;
|
||||
great = IBeatmapDifficultyInfo.DifficultyRange(difficulty, great_window_range) * multiplier;
|
||||
good = IBeatmapDifficultyInfo.DifficultyRange(difficulty, good_window_range) * multiplier;
|
||||
ok = IBeatmapDifficultyInfo.DifficultyRange(difficulty, ok_window_range) * multiplier;
|
||||
meh = IBeatmapDifficultyInfo.DifficultyRange(difficulty, meh_window_range) * multiplier;
|
||||
miss = IBeatmapDifficultyInfo.DifficultyRange(difficulty, miss_window_range) * multiplier;
|
||||
perfect = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, perfect_window_range) * multiplier) + 0.5;
|
||||
great = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, great_window_range) * multiplier) + 0.5;
|
||||
good = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, good_window_range) * multiplier) + 0.5;
|
||||
ok = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, ok_window_range) * multiplier) + 0.5;
|
||||
meh = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, meh_window_range) * multiplier) + 0.5;
|
||||
miss = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, miss_window_range) * multiplier) + 0.5;
|
||||
}
|
||||
|
||||
public override double WindowFor(HitResult result)
|
||||
|
||||
@@ -13,7 +13,6 @@ using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -22,14 +21,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
public partial class Ez2ColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly Bindable<float> overlayHeight = new Bindable<float>();
|
||||
private readonly Bindable<double> hitPosition = new Bindable<double>();
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private Bindable<double> hitPosition = new Bindable<double>();
|
||||
private Color4 brightColour;
|
||||
private Color4 dimColour;
|
||||
|
||||
private Box background = null!;
|
||||
private Box backgroundOverlay = null!;
|
||||
private Box? separator;
|
||||
private Box separator = new Box();
|
||||
private Bindable<Color4> accentColour = null!;
|
||||
|
||||
[Resolved]
|
||||
@@ -43,12 +41,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
|
||||
public Ez2ColumnBackground()
|
||||
{
|
||||
Anchor = Anchor.BottomLeft;
|
||||
Origin = Anchor.BottomLeft;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
// Masking = true;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new Container
|
||||
{
|
||||
@@ -99,46 +99,27 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
brightColour = colour.NewValue.Opacity(0.6f);
|
||||
dimColour = colour.NewValue.Opacity(0);
|
||||
}, true);
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
ezSkinConfig.BindWith(EzSkinSetting.HitPosition, hitPosition);
|
||||
hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPosition.BindValueChanged(_ => OnConfigChanged(), true);
|
||||
OnConfigChanged();
|
||||
}
|
||||
|
||||
private void OnConfigChanged()
|
||||
{
|
||||
if (separator != null)
|
||||
{
|
||||
separator.Height = DrawHeight - (float)hitPosition.Value;
|
||||
separator.Height = DrawHeight - (float)hitPosition.Value;
|
||||
|
||||
if (drawSeparator(column.Index, stageDefinition))
|
||||
{
|
||||
separator.Alpha = 0.2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
separator.Alpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
if (drawSeparator(column.Index, stageDefinition))
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.TopLeft;
|
||||
separator.Alpha = 0.2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.BottomLeft;
|
||||
separator.Alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +131,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
brightColour = noteColour.Opacity(0.9f);
|
||||
dimColour = noteColour.Opacity(0);
|
||||
|
||||
backgroundOverlay.Colour = direction.Value == ScrollingDirection.Up
|
||||
? ColourInfo.GradientVertical(brightColour, dimColour)
|
||||
: ColourInfo.GradientVertical(dimColour, brightColour);
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(dimColour, brightColour);
|
||||
|
||||
overlayHeight.Value = 0.5f;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ using osu.Framework.Input.Events;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens;
|
||||
@@ -46,9 +45,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
[Resolved]
|
||||
private IGameplayClock gameplayClock { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private StageDefinition stageDefinition { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
@@ -60,9 +56,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
if (stageDefinition.Columns == 14 && column.Index == 13)
|
||||
return;
|
||||
|
||||
hitPosition.Value = (float)ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition).Value;
|
||||
|
||||
InternalChild = directionContainer = new Container
|
||||
|
||||
@@ -15,16 +15,15 @@ using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Ez2;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
{
|
||||
public partial class Ez2KeyAreaPro : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
public partial class Ez2KeyAreaPlus : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
@@ -46,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
[Resolved]
|
||||
private IGameplayClock gameplayClock { get; set; } = null!;
|
||||
|
||||
public Ez2KeyAreaPro()
|
||||
public Ez2KeyAreaPlus()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Ez2HUD;
|
||||
using osu.Game.Rulesets.Mania.Skinning.EzStylePro;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
@@ -183,7 +184,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
// if (Skin is Ez2Skin && resultComponent.Component >= HitResult.Perfect)
|
||||
// return Drawable.Empty();
|
||||
|
||||
return new Ez2ColumnBackground();
|
||||
return new EzColumnBackground();
|
||||
|
||||
case ManiaSkinComponents.KeyArea:
|
||||
return new Ez2KeyArea();
|
||||
@@ -224,7 +225,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
bool isSpecialColumn = stage.EzIsSpecialColumn(columnIndex);
|
||||
|
||||
float width = (float)columnWidthBindable.Value * (isSpecialColumn ? (float)specialFactorBindable.Value : 1f);
|
||||
float hitPositionValue = (float)hitPosition.Value; // + (float)virtualHitPosition.Value - 110f;
|
||||
// float hitPositionValue = (float)hitPosition.Value; // + (float)virtualHitPosition.Value - 110f;
|
||||
|
||||
if (stage.Columns == 14 && columnIndex == 13)
|
||||
width = 0f;
|
||||
@@ -234,8 +235,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2
|
||||
case LegacyManiaSkinConfigurationLookups.ColumnWidth:
|
||||
return SkinUtils.As<TValue>(new Bindable<float>(width));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.HitPosition:
|
||||
return SkinUtils.As<TValue>(new Bindable<float>(hitPositionValue));
|
||||
// case LegacyManiaSkinConfigurationLookups.HitPosition:
|
||||
// return SkinUtils.As<TValue>(new Bindable<float>(hitPositionValue));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.UseRelativeSize))]
|
||||
public BindableBool UseRelativeSize { get; } = new BindableBool(true);
|
||||
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour), nameof(SkinnableComponentStrings.ColourDescription))]
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour))]
|
||||
public BindableColour4 AccentColour { get; } = new BindableColour4(Colour4.White);
|
||||
|
||||
[Resolved]
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
public Bindable<EzSelectorNameSet> NameDropdown { get; } = new Bindable<EzSelectorNameSet>((EzSelectorNameSet)4);
|
||||
|
||||
[SettingSource("Effect Type", "Effect Type")]
|
||||
public Bindable<EffectType> Effect { get; } = new Bindable<EffectType>(EffectType.Scale);
|
||||
public Bindable<EzComEffectType> Effect { get; } = new Bindable<EzComEffectType>(EzComEffectType.Scale);
|
||||
|
||||
// [SettingSource("Effect Origin", "Effect Origin", SettingControlType = typeof(AnchorDropdown))]
|
||||
// public Bindable<Anchor> EffectOrigin { get; } = new Bindable<Anchor>(Anchor.TopCentre)
|
||||
@@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
Precision = 0.01f,
|
||||
};
|
||||
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour), nameof(SkinnableComponentStrings.ColourDescription))]
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour))]
|
||||
public BindableColour4 AccentColour { get; } = new BindableColour4(Colour4.White);
|
||||
|
||||
public EzComboText Text = null!;
|
||||
@@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
{
|
||||
switch (Effect.Value)
|
||||
{
|
||||
case EffectType.Scale:
|
||||
case EzComEffectType.Scale:
|
||||
EzEffectHelper.ApplyScaleAnimation(
|
||||
Text.TextContainer,
|
||||
wasIncrease,
|
||||
@@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
EffectEndDuration.Value);
|
||||
break;
|
||||
|
||||
case EffectType.Bounce:
|
||||
case EzComEffectType.Bounce:
|
||||
EzEffectHelper.ApplyBounceAnimation(
|
||||
Text.TextContainer,
|
||||
wasIncrease,
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
public Bindable<EzSelectorNameSet> NameDropdown { get; } = new Bindable<EzSelectorNameSet>((EzSelectorNameSet)4);
|
||||
|
||||
[SettingSource("Effect Type", "Effect Type")]
|
||||
public Bindable<EffectType> Effect { get; } = new Bindable<EffectType>(EffectType.Scale);
|
||||
public Bindable<EzComEffectType> Effect { get; } = new Bindable<EzComEffectType>(EzComEffectType.Scale);
|
||||
|
||||
[SettingSource("Effect Origin", "Effect Origin", SettingControlType = typeof(AnchorDropdown))]
|
||||
public Bindable<Anchor> EffectOrigin { get; } = new Bindable<Anchor>(Anchor.TopCentre)
|
||||
@@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
Precision = 0.01f,
|
||||
};
|
||||
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour), nameof(SkinnableComponentStrings.ColourDescription))]
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour))]
|
||||
public BindableColour4 AccentColour { get; } = new BindableColour4(Colour4.White);
|
||||
|
||||
public EzComboText Text = null!;
|
||||
@@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
{
|
||||
switch (Effect.Value)
|
||||
{
|
||||
case EffectType.Scale:
|
||||
case EzComEffectType.Scale:
|
||||
EzEffectHelper.ApplyScaleAnimation(
|
||||
Text.TextContainer,
|
||||
wasIncrease,
|
||||
@@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
EffectEndDuration.Value);
|
||||
break;
|
||||
|
||||
case EffectType.Bounce:
|
||||
case EzComEffectType.Bounce:
|
||||
EzEffectHelper.ApplyBounceAnimation(
|
||||
Text.TextContainer,
|
||||
wasIncrease,
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
Precision = 0.01f,
|
||||
};
|
||||
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour), nameof(SkinnableComponentStrings.ColourDescription))]
|
||||
[SettingSource(typeof(SkinnableComponentStrings), nameof(SkinnableComponentStrings.Colour))]
|
||||
public BindableColour4 AccentColour { get; } = new BindableColour4(Colour4.White);
|
||||
|
||||
private Container timingContainer = null!;
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.Ez2HUD
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateWidths();
|
||||
triggers.BindTo(controller.Triggers);
|
||||
triggers.BindCollectionChanged(triggersChanged, true);
|
||||
columnWidth.BindValueChanged(_ => updateWidths(), true);
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
public partial class EzColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private Bindable<double> hitPosition = new Bindable<double>();
|
||||
private Color4 brightColour;
|
||||
private Color4 dimColour;
|
||||
|
||||
private Box backgroundOverlay = null!;
|
||||
|
||||
private readonly Box separator = new Box
|
||||
{
|
||||
Name = "Separator",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopCentre,
|
||||
Width = 2,
|
||||
Colour = Color4.White.Opacity(0.5f),
|
||||
Alpha = 0,
|
||||
};
|
||||
|
||||
private Bindable<Color4> accentColour = null!;
|
||||
|
||||
[Resolved]
|
||||
protected Column Column { get; private set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private StageDefinition stageDefinition { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
public EzColumnBackground()
|
||||
{
|
||||
Anchor = Anchor.BottomLeft;
|
||||
Origin = Anchor.BottomLeft;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
// Masking = true;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.8f).Darken(3),
|
||||
},
|
||||
backgroundOverlay = new Box
|
||||
{
|
||||
Name = "Background Gradient Overlay",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
accentColour = new Bindable<Color4>(ezSkinConfig.GetColumnColor(stageDefinition.Columns, Column.Index));
|
||||
accentColour.BindValueChanged(colour =>
|
||||
{
|
||||
var newColour = colour.NewValue.Darken(3);
|
||||
|
||||
if (newColour.A != 0)
|
||||
{
|
||||
newColour = newColour.Opacity(0.8f);
|
||||
}
|
||||
|
||||
backgroundOverlay.Colour = newColour;
|
||||
brightColour = colour.NewValue.Opacity(0.6f);
|
||||
dimColour = colour.NewValue.Opacity(0);
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
bool hasSeparator = Column.TopLevelContainer.Children
|
||||
.OfType<Box>()
|
||||
.Any(b => b.Name == "Separator");
|
||||
|
||||
if (!hasSeparator)
|
||||
Column.TopLevelContainer.Add(separator);
|
||||
|
||||
hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPosition.BindValueChanged(_ => OnConfigChanged(), true);
|
||||
}
|
||||
|
||||
protected virtual Color4 NoteColor
|
||||
{
|
||||
get
|
||||
{
|
||||
int keyMode = stageDefinition.Columns;
|
||||
int columnIndex = Column.Index;
|
||||
return ezSkinConfig.GetColumnColor(keyMode, columnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConfigChanged()
|
||||
{
|
||||
separator.Height = DrawHeight - (float)hitPosition.Value;
|
||||
|
||||
if (drawSeparator(Column.Index, stageDefinition))
|
||||
separator.Alpha = 0.25f;
|
||||
else
|
||||
separator.Alpha = 0;
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||
{
|
||||
if (e.Action == Column.Action.Value)
|
||||
{
|
||||
var noteColour = NoteColor;
|
||||
brightColour = noteColour.Opacity(0.9f);
|
||||
dimColour = noteColour.Opacity(0);
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(dimColour, brightColour);
|
||||
backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
||||
{
|
||||
if (e.Action == Column.Action.Value)
|
||||
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
||||
}
|
||||
|
||||
//TODO: 这里的逻辑可以优化,避免重复计算
|
||||
private bool drawSeparator(int columnIndex, StageDefinition stage)
|
||||
{
|
||||
return stage.Columns switch
|
||||
{
|
||||
12 => columnIndex is 0 or 10,
|
||||
14 => columnIndex is 0 or 5 or 6 or 11,
|
||||
16 => columnIndex is 0 or 5 or 9 or 14,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -9,10 +8,8 @@ using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osuTK;
|
||||
@@ -21,22 +18,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
public partial class EzHitExplosion : CompositeDrawable, IHitExplosion
|
||||
{
|
||||
// public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly Bindable<double> columnWidth = new Bindable<double>();
|
||||
|
||||
private IBindable<double> noteHeightBindable = new Bindable<double>();
|
||||
private IBindable<double> columnWidthBindable = new Bindable<double>();
|
||||
private IBindable<double> specialFactorBindable = new Bindable<double>();
|
||||
private IBindable<double> hitPosition = new Bindable<double>();
|
||||
|
||||
private TextureAnimation? animation;
|
||||
private TextureAnimation? animationP;
|
||||
private Container container = null!;
|
||||
|
||||
[UsedImplicitly]
|
||||
private float baseYPosition;
|
||||
private IBindable<double> noteHeightBindable = new Bindable<double>();
|
||||
private IBindable<double> columnWidthBindable = new Bindable<double>();
|
||||
private IBindable<double> specialFactorBindable = new Bindable<double>();
|
||||
|
||||
// public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; } = null!;
|
||||
@@ -45,10 +35,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
private StageDefinition stageDefinition { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzLocalTextureFactory factory { get; set; } = null!;
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
private EzLocalTextureFactory factory { get; set; } = null!;
|
||||
|
||||
public EzHitExplosion()
|
||||
{
|
||||
@@ -57,27 +47,24 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
private void load()
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
|
||||
noteHeightBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight);
|
||||
columnWidthBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.ColumnWidth);
|
||||
specialFactorBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.SpecialFactor);
|
||||
hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
|
||||
noteHeightBindable.BindValueChanged(_ => updateY(), true);
|
||||
columnWidthBindable.BindValueChanged(_ => updateY(), true);
|
||||
specialFactorBindable.BindValueChanged(_ => updateY(), true);
|
||||
hitPosition.BindValueChanged(_ => updateY(), true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
onSkinChanged();
|
||||
|
||||
factory.OnNoteChanged += onSkinChanged;
|
||||
}
|
||||
|
||||
@@ -85,10 +72,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (isDisposing)
|
||||
{
|
||||
factory.OnNoteChanged -= onSkinChanged;
|
||||
}
|
||||
if (isDisposing) { factory.OnNoteChanged -= onSkinChanged; }
|
||||
}
|
||||
|
||||
private void loadAnimation()
|
||||
@@ -98,9 +82,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
animation = factory.CreateAnimation("noteflare");
|
||||
animationP = factory.CreateAnimation("noteflaregood");
|
||||
|
||||
animation.Loop = false;
|
||||
animationP.Loop = false;
|
||||
|
||||
container = new Container
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
@@ -116,18 +97,18 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
private void updateY()
|
||||
{
|
||||
bool isSpecialColumn = stageDefinition.EzIsSpecialColumn(column.Index);
|
||||
columnWidth.Value = columnWidthBindable.Value * (isSpecialColumn ? specialFactorBindable.Value : 1);
|
||||
bool isSpecialColumn = EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1";
|
||||
double columnWidth = columnWidthBindable.Value * (isSpecialColumn ? specialFactorBindable.Value : 1);
|
||||
|
||||
bool isSquare = factory.IsSquareNote("whitenote");
|
||||
float aspectRatio = factory.GetRatio("whitenote");
|
||||
|
||||
float moveY = isSquare
|
||||
? (float)columnWidth.Value / 2 * aspectRatio
|
||||
? (float)columnWidth / 2 * aspectRatio
|
||||
: (float)noteHeightBindable.Value / 2 * aspectRatio;
|
||||
|
||||
baseYPosition = 110f - (float)hitPosition.Value - moveY;
|
||||
Position = new Vector2(0, baseYPosition);
|
||||
// baseYPosition = LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION - (float)hitPosition.Value - moveY;
|
||||
Position = new Vector2(0, -moveY);
|
||||
}
|
||||
|
||||
private void onSkinChanged()
|
||||
@@ -135,12 +116,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
loadAnimation();
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
Rotation = direction.NewValue == ScrollingDirection.Up ? 90f : 0;
|
||||
Anchor = Origin = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
public void Animate(JudgementResult result)
|
||||
{
|
||||
loadAnimation();
|
||||
|
||||
@@ -3,20 +3,15 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
internal partial class EzHitTarget : EzNote
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private IBindable<double> hitPosition = new Bindable<double>();
|
||||
// private IBindable<double> hitPosition = new Bindable<double>();
|
||||
|
||||
protected override bool ShowSeparators => false;
|
||||
protected override bool UseColorization => false;
|
||||
@@ -28,8 +23,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
[Resolved]
|
||||
private IGameplayClock gameplayClock { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
// [Resolved]
|
||||
// private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
public EzHitTarget()
|
||||
{
|
||||
@@ -39,16 +34,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
private void load()
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPosition.BindValueChanged(_ => updateY(), true);
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
// hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
// hitPosition.BindValueChanged(_ => updateY(), true);
|
||||
}
|
||||
|
||||
private float baseYPosition;
|
||||
// private float baseYPosition = 0f;
|
||||
private double beatInterval;
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -65,18 +59,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
double progress = (gameplayClock.CurrentTime % beatInterval) / beatInterval;
|
||||
// 平滑正弦波效果
|
||||
double smoothValue = 0.3 * Math.Sin(progress * 2 * Math.PI);
|
||||
Y = baseYPosition + (float)(smoothValue * 6);
|
||||
Y = (float)(smoothValue * 6);
|
||||
}
|
||||
|
||||
private void updateY()
|
||||
{
|
||||
baseYPosition = 110f - (float)hitPosition.Value;
|
||||
Position = new Vector2(0, baseYPosition);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
Anchor = Origin = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||
}
|
||||
//DrawableManiaRuleset中关联设置后,此处不必设置
|
||||
// private void updateY()
|
||||
// {
|
||||
// baseYPosition = LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION - (float)hitPosition.Value;
|
||||
// Position = new Vector2(0, baseYPosition);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
@@ -21,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
private Bindable<double> nonSquareNoteHeight = null!;
|
||||
|
||||
private TextureAnimation animation = null!;
|
||||
private Container? container;
|
||||
private Container container = null!;
|
||||
private EzNoteSideLine? noteSeparatorsL;
|
||||
private EzNoteSideLine? noteSeparatorsR;
|
||||
|
||||
@@ -45,13 +44,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
nonSquareNoteHeight = ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight);
|
||||
enabledColor = ezSkinConfig.GetBindable<bool>(EzSkinSetting.ColorSettingsEnabled);
|
||||
OnSkinChanged();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
OnSkinChanged();
|
||||
nonSquareNoteHeight.ValueChanged += _ => updateSizes();
|
||||
|
||||
nonSquareNoteHeight.BindValueChanged(_ => updateSizes(), true);
|
||||
ezSkinConfig.OnSettingsChanged += OnConfigChanged;
|
||||
factory.OnNoteChanged += OnSkinChanged;
|
||||
}
|
||||
@@ -84,14 +84,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
if (enabledColor.Value)
|
||||
return "white";
|
||||
|
||||
if (stageDefinition.EzIsSpecialColumn(column.Index))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1")
|
||||
return "green";
|
||||
|
||||
int logicalIndex = 0;
|
||||
|
||||
for (int i = 0; i < column.Index; i++)
|
||||
{
|
||||
if (!stageDefinition.EzIsSpecialColumn(i))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, i) != "S1")
|
||||
logicalIndex++;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
AddInternal(animation);
|
||||
}
|
||||
|
||||
Schedule(updateSizes);
|
||||
OnConfigChanged();
|
||||
}
|
||||
|
||||
private void updateSizes()
|
||||
@@ -176,11 +176,10 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
Height = noteHeight;
|
||||
|
||||
if (container != null)
|
||||
if (container.Children.Count > 0 && container.Child is Container c)
|
||||
{
|
||||
container.Height = noteHeight / 2;
|
||||
if (container.Child is Container containerA)
|
||||
containerA.Height = noteHeight;
|
||||
c.Height = noteHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +190,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
noteColor = NoteColor;
|
||||
|
||||
animation.Colour = noteColor;
|
||||
|
||||
container.Colour = noteColor;
|
||||
noteSeparatorsL?.UpdateGlowEffect(noteColor);
|
||||
noteSeparatorsR?.UpdateGlowEffect(noteColor);
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
@@ -19,17 +19,16 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
public partial class EzHoldNoteHittingLayer : CompositeDrawable
|
||||
{
|
||||
public readonly Bindable<bool> IsHitting = new Bindable<bool>();
|
||||
private readonly IBindable<double> noteHeightBindable = new Bindable<double>();
|
||||
private readonly IBindable<double> columnWidthBindable = new Bindable<double>();
|
||||
private readonly IBindable<double> specialFactorBindable = new Bindable<double>();
|
||||
private readonly IBindable<double> hitPosition = new Bindable<double>();
|
||||
|
||||
private TextureAnimation? animation;
|
||||
|
||||
// [UsedImplicitly]
|
||||
private readonly Bindable<Vector2> noteSize = new Bindable<Vector2>();
|
||||
private IBindable<double> noteHeightBindable = new Bindable<double>();
|
||||
private IBindable<double> columnWidthBindable = new Bindable<double>();
|
||||
private IBindable<double> specialFactorBindable = new Bindable<double>();
|
||||
|
||||
private float baseYPosition;
|
||||
public IBindable<double> HitPosition { get; set; } = new Bindable<double>();
|
||||
|
||||
// private IBindable<double> hitPosition = new Bindable<double>();
|
||||
// private float baseYPosition;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; } = null!;
|
||||
@@ -38,50 +37,30 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
private StageDefinition stageDefinition { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzLocalTextureFactory factory { get; set; } = null!;
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
private EzLocalTextureFactory factory { get; set; } = null!;
|
||||
|
||||
public EzHoldNoteHittingLayer()
|
||||
{
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.Centre;
|
||||
AutoSizeAxes = Axes.Both;
|
||||
// AutoSizeAxes = Axes.Both;
|
||||
Blending = BlendingParameters.Additive;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
noteHeightBindable.BindTo(ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight));
|
||||
columnWidthBindable.BindTo(ezSkinConfig.GetBindable<double>(EzSkinSetting.ColumnWidth));
|
||||
specialFactorBindable.BindTo(ezSkinConfig.GetBindable<double>(EzSkinSetting.SpecialFactor));
|
||||
hitPosition.BindTo(ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition));
|
||||
|
||||
hitPosition.BindValueChanged(_ => updateY(), true);
|
||||
noteHeightBindable.BindValueChanged(_ => updateY(), true);
|
||||
columnWidthBindable.BindValueChanged(_ => updateY());
|
||||
specialFactorBindable.BindValueChanged(_ => updateY());
|
||||
|
||||
noteSize.BindValueChanged(_ => updateY(), true);
|
||||
IsHitting.BindValueChanged(hitting =>
|
||||
{
|
||||
ClearTransforms();
|
||||
// Logger.Log($"IsHitting changed to: {hitting.NewValue}", LoggingTarget.Runtime, LogLevel.Debug);
|
||||
// animation.IsPlaying = hitting.NewValue;
|
||||
|
||||
if (hitting.NewValue && animation.IsNotNull())
|
||||
{
|
||||
Alpha = 1;
|
||||
|
||||
animation.Restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = 0;
|
||||
}
|
||||
}, true);
|
||||
noteHeightBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight);
|
||||
columnWidthBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.ColumnWidth);
|
||||
specialFactorBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.SpecialFactor);
|
||||
HitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
noteHeightBindable.BindValueChanged(_ => UpdateLNsLight(), true);
|
||||
columnWidthBindable.BindValueChanged(_ => UpdateLNsLight(), true);
|
||||
specialFactorBindable.BindValueChanged(_ => UpdateLNsLight(), true);
|
||||
// hitPosition.BindValueChanged(_ => updateY(), true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -89,6 +68,25 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
base.LoadComplete();
|
||||
onSkinChanged();
|
||||
factory.OnNoteChanged += onSkinChanged;
|
||||
HitPosition.BindValueChanged(pos => Y =
|
||||
LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION - (float)pos.NewValue, true);
|
||||
|
||||
IsHitting.BindValueChanged(hitting =>
|
||||
{
|
||||
ClearTransforms();
|
||||
// Logger.Log($"IsHitting changed to: {hitting.NewValue}", LoggingTarget.Runtime, LogLevel.Debug);
|
||||
// animation.IsPlaying = hitting.NewValue;
|
||||
|
||||
if (hitting.NewValue && animation.IsNotNull() && animation.FrameCount > 0)
|
||||
{
|
||||
Alpha = 1;
|
||||
animation.Restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = 0;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@@ -126,32 +124,22 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
animation.Loop = true;
|
||||
AddInternal(animation);
|
||||
updateY();
|
||||
UpdateLNsLight();
|
||||
}
|
||||
|
||||
private void updateY()
|
||||
public void UpdateLNsLight()
|
||||
{
|
||||
bool isSpecialColumn = stageDefinition.EzIsSpecialColumn(column.Index);
|
||||
bool isSpecialColumn = EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1";
|
||||
double columnWidth = columnWidthBindable.Value * (isSpecialColumn ? specialFactorBindable.Value : 1);
|
||||
|
||||
bool isSquare = factory.IsSquareNote("whitenote");
|
||||
var tempContainer = factory.CreateAnimation("whitenote");
|
||||
float aspectRatio = 1f;
|
||||
float aspectRatio = factory.GetRatio("whitenote");
|
||||
|
||||
if (tempContainer.FrameCount > 0)
|
||||
{
|
||||
aspectRatio = tempContainer.CurrentFrame.Height / (float)tempContainer.CurrentFrame.Width;
|
||||
}
|
||||
|
||||
tempContainer.Dispose();
|
||||
float moveY = isSquare
|
||||
? (float)columnWidth / 2 * aspectRatio
|
||||
: (float)noteHeightBindable.Value * aspectRatio;
|
||||
|
||||
baseYPosition = 110f - (float)hitPosition.Value - moveY;
|
||||
Position = new Vector2(0, baseYPosition);
|
||||
|
||||
Invalidate();
|
||||
Position = new Vector2(0, moveY);
|
||||
}
|
||||
|
||||
private void onSkinChanged()
|
||||
|
||||
@@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Default;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Legacy;
|
||||
@@ -34,7 +33,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
private Container middleScaleContainer = null!;
|
||||
private Container middleInnerContainer = null!;
|
||||
|
||||
private EzSkinSettingsManager ezSkinConfig = null!;
|
||||
private IBindable<double> noteHeight = new Bindable<double>();
|
||||
private IBindable<double> hitPosition = new Bindable<double>();
|
||||
private Bindable<bool> enabledColor = null!;
|
||||
private Drawable? container;
|
||||
private Drawable? lightContainer;
|
||||
@@ -46,6 +46,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
[Resolved]
|
||||
private StageDefinition stageDefinition { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzLocalTextureFactory factory { get; set; } = null!;
|
||||
|
||||
@@ -60,12 +63,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(EzSkinSettingsManager ezSkinConfig, DrawableHitObject drawableObject)
|
||||
private void load(DrawableHitObject drawableObject)
|
||||
{
|
||||
this.ezSkinConfig = ezSkinConfig;
|
||||
holdNote = (DrawableHoldNote)drawableObject;
|
||||
isHitting.BindTo(holdNote.IsHolding);
|
||||
|
||||
noteHeight = ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight);
|
||||
hitPosition = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
enabledColor = ezSkinConfig.GetBindable<bool>(EzSkinSetting.ColorSettingsEnabled);
|
||||
}
|
||||
|
||||
@@ -85,6 +89,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
base.LoadComplete();
|
||||
OnSkinChanged();
|
||||
noteHeight.BindValueChanged(_ => OnSettingsChanged(), true);
|
||||
factory.OnNoteChanged += OnSkinChanged;
|
||||
ezSkinConfig.OnSettingsChanged += OnSettingsChanged;
|
||||
isHitting.BindValueChanged(onIsHittingChanged, true);
|
||||
@@ -104,6 +109,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
private void OnSkinChanged()
|
||||
{
|
||||
if (lightContainer != null)
|
||||
{
|
||||
column.TopLevelContainer.Remove(lightContainer, false);
|
||||
lightContainer.Expire();
|
||||
lightContainer = null;
|
||||
}
|
||||
|
||||
loadAnimation();
|
||||
hittingLayer = new EzHoldNoteHittingLayer
|
||||
{
|
||||
@@ -115,6 +127,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
Alpha = 0,
|
||||
Child = hittingLayer
|
||||
};
|
||||
hittingLayer.HitPosition.BindTo(hitPosition);
|
||||
}
|
||||
|
||||
private void onIsHittingChanged(ValueChangedEvent<bool> isHitting)
|
||||
@@ -157,14 +170,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
if (enabledColor.Value)
|
||||
return "white";
|
||||
|
||||
if (stageDefinition.EzIsSpecialColumn(column.Index))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1")
|
||||
return "green";
|
||||
|
||||
int logicalIndex = 0;
|
||||
|
||||
for (int i = 0; i < column.Index; i++)
|
||||
{
|
||||
if (!stageDefinition.EzIsSpecialColumn(i))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) != "S1")
|
||||
logicalIndex++;
|
||||
}
|
||||
|
||||
@@ -172,15 +185,12 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string ComponentName => $"{ColorPrefix}longnote/middle";
|
||||
protected virtual string ComponentName2 => $"{ColorPrefix}longnote/tail";
|
||||
|
||||
private void loadAnimation()
|
||||
{
|
||||
ClearInternal();
|
||||
string backupComponentName = $"{ColorPrefix}note";
|
||||
middleAnimation = factory.CreateAnimation(ComponentName);
|
||||
tailAnimation = factory.CreateAnimation(ComponentName2);
|
||||
middleAnimation = factory.CreateAnimation($"{ColorPrefix}longnote/middle");
|
||||
tailAnimation = factory.CreateAnimation($"{ColorPrefix}longnote/tail");
|
||||
|
||||
if (middleAnimation.FrameCount == 0)
|
||||
{
|
||||
|
||||
@@ -3,21 +3,22 @@
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Legacy;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
public partial class EzStageKeys : CompositeDrawable
|
||||
public partial class EzKeyArea : LegacyManiaColumnElement, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private TextureAnimation animation = null!;
|
||||
private Drawable container = null!;
|
||||
|
||||
private Drawable upSprite = null!;
|
||||
private Drawable downSprite = null!;
|
||||
protected virtual bool IsKeyPress => true;
|
||||
protected virtual bool UseColorization => true;
|
||||
|
||||
@@ -33,18 +34,21 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
public EzKeyArea()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
FillMode = FillMode.Fill;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
OnSkinChanged();
|
||||
factory.OnNoteChanged += OnSkinChanged;
|
||||
factory.OnStageChanged += OnSkinChanged;
|
||||
ezSkinConfig.OnSettingsChanged += OnConfigChanged;
|
||||
}
|
||||
|
||||
@@ -54,11 +58,55 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
if (isDisposing)
|
||||
{
|
||||
factory.OnNoteChanged -= OnSkinChanged;
|
||||
factory.OnStageChanged -= OnSkinChanged;
|
||||
ezSkinConfig.OnSettingsChanged -= OnConfigChanged;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string KeyBasicSuffix
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1")
|
||||
return "02";
|
||||
|
||||
int logicalIndex = 0;
|
||||
|
||||
for (int i = 0; i < column.Index; i++)
|
||||
{
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, i) == "S1")
|
||||
logicalIndex++;
|
||||
}
|
||||
|
||||
return logicalIndex % 2 == 0 ? "00" : "01";
|
||||
}
|
||||
}
|
||||
|
||||
private void loadAnimation()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
upSprite = factory.CreateStage("keybase");
|
||||
downSprite = factory.CreateStage("keypress");
|
||||
downSprite.Alpha = 0;
|
||||
|
||||
container = new Container
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new[]
|
||||
{
|
||||
upSprite,
|
||||
downSprite,
|
||||
}
|
||||
};
|
||||
|
||||
OnConfigChanged();
|
||||
AddInternal(container);
|
||||
}
|
||||
|
||||
private void updateSizes()
|
||||
{
|
||||
bool isSquare = factory.IsSquareNote("whitenote");
|
||||
@@ -67,25 +115,6 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
: (float)(ezSkinConfig.GetBindable<double>(EzSkinSetting.NonSquareNoteHeight).Value);
|
||||
}
|
||||
|
||||
private void loadAnimation()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
animation = factory.CreateAnimation(ComponentName);
|
||||
container = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Child = animation
|
||||
};
|
||||
|
||||
OnConfigChanged();
|
||||
AddInternal(container);
|
||||
}
|
||||
|
||||
private void OnSkinChanged() => loadAnimation();
|
||||
|
||||
private void OnConfigChanged()
|
||||
{
|
||||
Schedule(() =>
|
||||
@@ -95,32 +124,26 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual string KeyPressPrefix => IsKeyPress switch
|
||||
{
|
||||
true => "keypress/KeyBasicPress_",
|
||||
_ => "keybase/KeyBasicBase_",
|
||||
};
|
||||
private void OnSkinChanged() => loadAnimation();
|
||||
|
||||
protected virtual string KeyBasicSuffix
|
||||
public bool OnPressed(KeyBindingPressEvent<ManiaAction> e)
|
||||
{
|
||||
get
|
||||
if (e.Action == column.Action.Value)
|
||||
{
|
||||
if (stageDefinition.EzIsSpecialColumn(column.Index))
|
||||
return "02";
|
||||
|
||||
int logicalIndex = 0;
|
||||
|
||||
for (int i = 0; i < column.Index; i++)
|
||||
{
|
||||
if (!stageDefinition.EzIsSpecialColumn(i))
|
||||
logicalIndex++;
|
||||
}
|
||||
|
||||
return logicalIndex % 2 == 0 ? "00" : "01";
|
||||
upSprite.FadeTo(0);
|
||||
downSprite.FadeTo(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual string StagePrefix => EzStageBottom.StagePrefix;
|
||||
protected virtual string ComponentName => $"{StagePrefix}/{KeyPressPrefix}{KeyBasicSuffix}";
|
||||
public void OnReleased(KeyBindingReleaseEvent<ManiaAction> e)
|
||||
{
|
||||
if (e.Action == column.Action.Value)
|
||||
{
|
||||
upSprite.Delay(LegacyHitExplosion.FADE_IN_DURATION).FadeTo(1);
|
||||
downSprite.Delay(LegacyHitExplosion.FADE_IN_DURATION).FadeTo(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
@@ -88,14 +87,14 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
if (enabledColor.Value)
|
||||
return "white";
|
||||
|
||||
if (stageDefinition.EzIsSpecialColumn(column.Index))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, column.Index) == "S1")
|
||||
return "green";
|
||||
|
||||
int logicalIndex = 0;
|
||||
|
||||
for (int i = 0; i < column.Index; i++)
|
||||
{
|
||||
if (!stageDefinition.EzIsSpecialColumn(i))
|
||||
if (EzColumnTypeManager.GetColumnType(stageDefinition.Columns, i) != "S1")
|
||||
logicalIndex++;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
@@ -29,20 +30,21 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
hitPositon = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
columnWidth = ezSkinConfig.GetBindable<double>(EzSkinSetting.ColumnWidth);
|
||||
hitPositon.BindValueChanged(_ => OnConfigChanged());
|
||||
columnWidth.BindValueChanged(_ => OnConfigChanged());
|
||||
OnSkinChanged();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
OnSkinChanged();
|
||||
factory.OnNoteChanged += OnSkinChanged;
|
||||
|
||||
factory.OnStageChanged += OnSkinChanged;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@@ -51,24 +53,27 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
|
||||
if (isDisposing)
|
||||
{
|
||||
factory.OnNoteChanged -= OnSkinChanged;
|
||||
factory.OnStageChanged -= OnSkinChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public static string StagePrefix => "Stage/fivekey";
|
||||
protected static string ComponentName => $"{StagePrefix}/Body";
|
||||
// protected override void Update()
|
||||
// {
|
||||
// base.Update();
|
||||
// updateSizes();
|
||||
// }
|
||||
|
||||
private void loadAnimation()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
var stageBottom = factory.CreateStage(ComponentName);
|
||||
var stageBottom = factory.CreateStage("Body");
|
||||
sprite = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
// Masking = true,
|
||||
|
||||
Child = stageBottom
|
||||
};
|
||||
// sprite.Depth = float.MinValue;
|
||||
@@ -76,23 +81,17 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
AddInternal(sprite);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
updateSizes();
|
||||
}
|
||||
|
||||
private void updateSizes()
|
||||
{
|
||||
if (sprite == null)
|
||||
return;
|
||||
|
||||
float actualPanelWidth = DrawWidth;
|
||||
double scale = actualPanelWidth / 410.0;
|
||||
sprite.Scale = new Vector2((float)scale);
|
||||
float scale = actualPanelWidth / 410.0f;
|
||||
sprite.Scale = new Vector2(scale);
|
||||
|
||||
Y = 274;
|
||||
Position = new Vector2(0, 660 + 110 - (float)hitPositon.Value);
|
||||
sprite.Y = LegacyManiaSkinConfiguration.DEFAULT_HIT_POSITION - (float)hitPositon.Value - DrawHeight * 0.865f;
|
||||
// Position = new Vector2(0, 415 + 110 - (float)hitPositon.Value);
|
||||
}
|
||||
|
||||
private void OnConfigChanged()
|
||||
|
||||
@@ -7,16 +7,15 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Ez2;
|
||||
using osu.Game.Rulesets.Mania.Skinning.Ez2HUD;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osu.Game.Screens.Play.HUD.HitErrorMeters;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Skinning.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
@@ -180,7 +179,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
// if (Skin is Ez2Skin && resultComponent.Component >= HitResult.Perfect)
|
||||
// return Drawable.Empty();
|
||||
|
||||
return new Ez2ColumnBackground();
|
||||
return new EzColumnBackground();
|
||||
|
||||
case ManiaSkinComponents.KeyArea:
|
||||
return new Ez2KeyArea();
|
||||
@@ -227,7 +226,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
{
|
||||
int columnIndex = maniaLookup.ColumnIndex ?? 0;
|
||||
var stage = beatmap.GetStageForColumnIndex(columnIndex);
|
||||
bool isSpecialColumn = stage.EzIsSpecialColumn(columnIndex);
|
||||
bool isSpecialColumn = EzColumnTypeManager.GetColumnType(stage.Columns, columnIndex) == "S1";
|
||||
float width = (float)columnWidthBindable.Value * (isSpecialColumn ? (float)specialFactorBindable.Value : 1f);
|
||||
// float hitPositionValue = (float)hitPosition.Value; // + (float)virtualHitPosition.Value - 110f;
|
||||
|
||||
@@ -242,9 +241,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.EzStylePro
|
||||
// case LegacyManiaSkinConfigurationLookups.HitPosition:
|
||||
// return SkinUtils.As<TValue>(new Bindable<float>(hitPositionValue));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||
var colour = stage.GetColourForLayout(columnIndex);
|
||||
return SkinUtils.As<TValue>(new Bindable<Color4>(colour));
|
||||
// case LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour:
|
||||
// var colour = stage.GetColourForLayout(columnIndex);
|
||||
// return SkinUtils.As<TValue>(new Bindable<Color4>(colour));
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.BarLineHeight:
|
||||
return SkinUtils.As<TValue>(new Bindable<float>(1));
|
||||
|
||||
@@ -5,8 +5,8 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
public partial class HitTargetInsetContainer : Container
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Bindable<double> hitPositonBindable = new Bindable<double>();
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container content;
|
||||
|
||||
@@ -28,14 +28,21 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
private void load(ISkinSource skin, EzSkinSettingsManager ezSkinConfig, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
hitPosition = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.HitPosition)?.Value ?? Stage.HIT_TARGET_POSITION;
|
||||
hitPositonBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPositonBindable.BindValueChanged(_ => UpdateHitPosition(), true);
|
||||
hitPosition = skin.GetManiaSkinConfig<float>(LegacyManiaSkinConfigurationLookups.HitPosition)?.Value ?? (float)hitPositonBindable.Value;
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected virtual void UpdateHitPosition()
|
||||
{
|
||||
hitPosition = (float)hitPositonBindable.Value;
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
content.Padding = direction.NewValue == ScrollingDirection.Up
|
||||
|
||||
@@ -14,7 +14,6 @@ using osu.Game.Skinning;
|
||||
using osu.Game.Skinning.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using EffectType = osu.Game.Skinning.Components.EffectType;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning.SbI
|
||||
{
|
||||
@@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.SbI
|
||||
combo1.Anchor = Anchor.TopCentre;
|
||||
combo1.Origin = Anchor.Centre;
|
||||
combo1.Y = 200;
|
||||
combo1.Effect.Value = EffectType.None;
|
||||
combo1.Effect.Value = EzComEffectType.None;
|
||||
combo1.NameDropdown.Value = (EzSelectorNameSet)43;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
@@ -68,28 +68,28 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
[Resolved]
|
||||
private ISkinSource skin { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private SkinManager skinManager { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
private readonly Bindable<ManiaMobileLayout> mobileLayout = new Bindable<ManiaMobileLayout>();
|
||||
private readonly Bindable<double> columnWidthBindable = new Bindable<double>();
|
||||
private readonly Bindable<double> specialFactorBindable = new Bindable<double>();
|
||||
private readonly Bindable<EzColumnWidthStyle> ezColumnWidthStyle = new Bindable<EzColumnWidthStyle>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ManiaRulesetConfigManager? rulesetConfig)
|
||||
{
|
||||
rulesetConfig?.BindWith(ManiaRulesetSetting.MobileLayout, mobileLayout);
|
||||
|
||||
ezSkinConfig.BindWith(EzSkinSetting.ColumnWidthStyle, ezColumnWidthStyle);
|
||||
ezSkinConfig.BindWith(EzSkinSetting.ColumnWidth, columnWidthBindable);
|
||||
ezSkinConfig.BindWith(EzSkinSetting.SpecialFactor, specialFactorBindable);
|
||||
columnWidthBindable.BindValueChanged(v =>
|
||||
{
|
||||
updateColumnSize();
|
||||
});
|
||||
specialFactorBindable.BindValueChanged(v =>
|
||||
{
|
||||
updateColumnSize();
|
||||
});
|
||||
ezColumnWidthStyle.BindValueChanged(v => updateColumnSize());
|
||||
columnWidthBindable.BindValueChanged(v => updateColumnSize());
|
||||
specialFactorBindable.BindValueChanged(v => updateColumnSize());
|
||||
|
||||
mobileLayout.BindValueChanged(_ => invalidateLayout());
|
||||
skin.SourceChanged += invalidateLayout;
|
||||
@@ -156,8 +156,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.ColumnWidth, i))
|
||||
?.Value;
|
||||
|
||||
bool isSpecialColumn = stageDefinition.EzIsSpecialColumn(i);
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
columns[i].Width = 0;
|
||||
@@ -165,7 +163,26 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
continue;
|
||||
}
|
||||
|
||||
width = (float)columnWidthBindable.Value * (isSpecialColumn ? (float)specialFactorBindable.Value : 1);
|
||||
bool isSpecialColumn =
|
||||
EzColumnTypeManager.GetColumnType(stageDefinition.Columns, i) == "S1";
|
||||
float ezWidth = (float)columnWidthBindable.Value * (isSpecialColumn ? (float)specialFactorBindable.Value : 1);
|
||||
|
||||
switch (ezColumnWidthStyle.Value)
|
||||
{
|
||||
case EzColumnWidthStyle.EzStyleProOnly:
|
||||
var skinInfo = skinManager.CurrentSkinInfo.Value;
|
||||
if (skinInfo.Value.Name.Contains("Ez Style Pro"))
|
||||
width = ezWidth;
|
||||
break;
|
||||
|
||||
case EzColumnWidthStyle.GlobalWidth:
|
||||
width = ezWidth;
|
||||
break;
|
||||
|
||||
case EzColumnWidthStyle.GlobalTotalWidth:
|
||||
width = ezWidth * 10 / stageDefinition.Columns;
|
||||
break;
|
||||
}
|
||||
|
||||
// only used by default skin (legacy skins get defaults set in LegacyManiaSkinConfiguration)
|
||||
width ??= isSpecialColumn ? Column.SPECIAL_COLUMN_WIDTH : Column.COLUMN_WIDTH;
|
||||
|
||||
@@ -23,12 +23,16 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
private Bindable<double> hitPositonBindable = new Bindable<double>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
Direction.BindTo(scrollingInfo.Direction);
|
||||
Direction.BindValueChanged(_ => UpdateHitPosition(), true);
|
||||
|
||||
hitPositonBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPositonBindable.BindValueChanged(_ => UpdateHitPosition(), true);
|
||||
skin.SourceChanged += onSkinChanged;
|
||||
}
|
||||
|
||||
@@ -38,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
float hitPosition = skin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value
|
||||
?? Stage.HIT_TARGET_POSITION;
|
||||
?? (float)hitPositonBindable.Value;
|
||||
|
||||
Padding = Direction.Value == ScrollingDirection.Up
|
||||
? new MarginPadding { Top = hitPosition }
|
||||
|
||||
@@ -18,6 +18,7 @@ using osu.Game.Input.Handlers;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
using osu.Game.Rulesets.Mania.LAsEZMania;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
@@ -27,6 +28,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@@ -79,6 +81,12 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
[Resolved]
|
||||
private GameHost gameHost { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private EzSkinSettingsManager ezSkinConfig { get; set; } = null!;
|
||||
|
||||
private Bindable<double> hitPositonBindable = new Bindable<double>();
|
||||
private readonly Bindable<bool> globalHitPosition = new Bindable<bool>();
|
||||
|
||||
public DrawableManiaRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod>? mods = null)
|
||||
: base(ruleset, beatmap, mods)
|
||||
{
|
||||
@@ -125,6 +133,11 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
Config.BindWith(ManiaRulesetSetting.MobileLayout, mobileLayout);
|
||||
mobileLayout.BindValueChanged(_ => updateMobileLayout(), true);
|
||||
|
||||
hitPositonBindable = ezSkinConfig.GetBindable<double>(EzSkinSetting.HitPosition);
|
||||
hitPositonBindable.BindValueChanged(_ => skinChanged(), true);
|
||||
ezSkinConfig.BindWith(EzSkinSetting.GlobalHitPosition, globalHitPosition);
|
||||
globalHitPosition.BindValueChanged(_ => skinChanged(), true);
|
||||
}
|
||||
|
||||
private ManiaTouchInputArea? touchInputArea;
|
||||
@@ -167,9 +180,14 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
private void skinChanged()
|
||||
{
|
||||
hitPosition = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value
|
||||
?? Stage.HIT_TARGET_POSITION;
|
||||
if (globalHitPosition.Value)
|
||||
hitPosition = (float)hitPositonBindable.Value;
|
||||
else
|
||||
{
|
||||
hitPosition = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value
|
||||
?? (float)hitPositonBindable.Value;
|
||||
}
|
||||
|
||||
pendingSkinChange = null;
|
||||
}
|
||||
@@ -192,7 +210,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
case EzManiaScrollingStyle.ScrollTimeStyleFixed:
|
||||
// Ensure the travel time from the top of the screen to the hit position remains constant.
|
||||
scale = length_to_default_hit_position / lengthToHitPosition;
|
||||
scale = lengthToHitPosition / 768;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
@@ -36,22 +35,21 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[Test]
|
||||
public void TestPlayfieldBasedSize()
|
||||
{
|
||||
ModFlashlight mod = new OsuModFlashlight();
|
||||
OsuModFlashlight flashlight;
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = mod,
|
||||
Mods = [flashlight = new OsuModFlashlight(), new OsuModBarrelRoll()],
|
||||
PassCondition = () =>
|
||||
{
|
||||
var flashlightOverlay = Player.DrawableRuleset.Overlays
|
||||
.ChildrenOfType<ModFlashlight<OsuHitObject>.Flashlight>()
|
||||
.First();
|
||||
|
||||
return Precision.AlmostEquals(mod.DefaultFlashlightSize * .5f, flashlightOverlay.GetSize());
|
||||
// the combo check is here because the flashlight radius decreases for the first time at 100 combo
|
||||
// and hardcoding it here eliminates the need to meddle in flashlight internals further by e.g. exposing `GetComboScaleFor()`
|
||||
return flashlightOverlay.GetSize() < flashlight.DefaultFlashlightSize && Player.GameplayState.ScoreProcessor.Combo.Value < 100;
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("adjust playfield scale", () =>
|
||||
Player.DrawableRuleset.Playfield.Scale = new Vector2(.5f));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -13,7 +13,6 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
@@ -22,21 +21,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public partial class TestSceneOsuModRelax : OsuModTestScene
|
||||
{
|
||||
private readonly HitCircle hitObject;
|
||||
private readonly HitWindows hitWindows = new OsuHitWindows();
|
||||
|
||||
public TestSceneOsuModRelax()
|
||||
{
|
||||
hitWindows.SetDifficulty(9);
|
||||
|
||||
hitObject = new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(100, 100),
|
||||
HitWindows = hitWindows
|
||||
};
|
||||
}
|
||||
|
||||
protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new ModRelaxTestPlayer(CurrentTestData, AllowFail);
|
||||
|
||||
[Test]
|
||||
@@ -46,12 +30,21 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
Autoplay = false,
|
||||
CreateBeatmap = () => new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject> { hitObject }
|
||||
Difficulty = { OverallDifficulty = 9 },
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(100, 100),
|
||||
HitWindows = new OsuHitWindows()
|
||||
}
|
||||
}
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(0, new Vector2()),
|
||||
new OsuReplayFrame(hitObject.StartTime, hitObject.Position),
|
||||
new OsuReplayFrame(100, new Vector2(100)),
|
||||
},
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 1
|
||||
});
|
||||
@@ -63,13 +56,22 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
Autoplay = false,
|
||||
CreateBeatmap = () => new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject> { hitObject }
|
||||
Difficulty = { OverallDifficulty = 9 },
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(100, 100),
|
||||
HitWindows = new OsuHitWindows()
|
||||
}
|
||||
}
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(0, new Vector2(hitObject.X - 22, hitObject.Y - 22)), // must be an edge hit for the cursor to not stay on the object for too long
|
||||
new OsuReplayFrame(hitObject.StartTime - OsuModRelax.RELAX_LENIENCY, new Vector2(hitObject.X - 22, hitObject.Y - 22)),
|
||||
new OsuReplayFrame(hitObject.StartTime, new Vector2(0)),
|
||||
new OsuReplayFrame(0, new Vector2(78, 78)), // must be an edge hit for the cursor to not stay on the object for too long
|
||||
new OsuReplayFrame(1000 - OsuModRelax.RELAX_LENIENCY, new Vector2(78, 78)),
|
||||
new OsuReplayFrame(1000, new Vector2(0)),
|
||||
},
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 1
|
||||
});
|
||||
|
||||
@@ -17,7 +17,6 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneLegacyReplayPlayback : LegacyReplayPlaybackTestScene
|
||||
{
|
||||
protected override Ruleset CreateRuleset() => new OsuRuleset();
|
||||
|
||||
@@ -14,26 +14,27 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
protected override IResourceStore<byte[]> RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneOsuHitObjectSamples)));
|
||||
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string expectedSample)
|
||||
[TestCase("normal-hitnormal2", "normal-hitnormal")]
|
||||
[TestCase("hitnormal", "hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string beatmapSkinSampleName, string userSkinSampleName)
|
||||
{
|
||||
SetupSkins(expectedSample, expectedSample);
|
||||
SetupSkins(beatmapSkinSampleName, userSkinSampleName);
|
||||
|
||||
CreateTestWithBeatmap("osu-hitobject-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertBeatmapLookup(expectedSample);
|
||||
AssertBeatmapLookup(beatmapSkinSampleName);
|
||||
}
|
||||
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromUserSkinFallback(string expectedSample)
|
||||
[TestCase("", "normal-hitnormal")]
|
||||
[TestCase("normal-hitnormal", "normal-hitnormal")]
|
||||
[TestCase("", "hitnormal")]
|
||||
public void TestDefaultCustomSampleFromUserSkinFallback(string beatmapSkinSampleName, string userSkinSampleName)
|
||||
{
|
||||
SetupSkins(string.Empty, expectedSample);
|
||||
SetupSkins(beatmapSkinSampleName, userSkinSampleName);
|
||||
|
||||
CreateTestWithBeatmap("osu-hitobject-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertUserLookup(expectedSample);
|
||||
AssertUserLookup(userSkinSampleName);
|
||||
}
|
||||
|
||||
[TestCase("normal-hitnormal2")]
|
||||
|
||||
@@ -13,7 +13,6 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneReplayStability : ReplayStabilityTestScene
|
||||
{
|
||||
private static readonly object[][] test_cases =
|
||||
@@ -23,53 +22,49 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
// while round brackets `()` represent *open* or *exclusive* bounds.
|
||||
|
||||
// OD = 5 test cases.
|
||||
// GREAT hit window is [ -50ms, 50ms]
|
||||
// OK hit window is [-100ms, 100ms]
|
||||
// MEH hit window is [-150ms, 150ms]
|
||||
// MISS hit window is [-400ms, 400ms]
|
||||
// GREAT hit window is [ -49.5ms, 49.5ms]
|
||||
// OK hit window is [ -99.5ms, 99.5ms]
|
||||
// MEH hit window is [-149.5ms, 149.5ms]
|
||||
new object[] { 5f, 49d, HitResult.Great },
|
||||
new object[] { 5f, 49.2d, HitResult.Great },
|
||||
new object[] { 5f, 49.7d, HitResult.Great },
|
||||
new object[] { 5f, 50d, HitResult.Great },
|
||||
new object[] { 5f, 49.7d, HitResult.Ok },
|
||||
new object[] { 5f, 50d, HitResult.Ok },
|
||||
new object[] { 5f, 50.4d, HitResult.Ok },
|
||||
new object[] { 5f, 50.9d, HitResult.Ok },
|
||||
new object[] { 5f, 51d, HitResult.Ok },
|
||||
new object[] { 5f, 99d, HitResult.Ok },
|
||||
new object[] { 5f, 99.2d, HitResult.Ok },
|
||||
new object[] { 5f, 99.7d, HitResult.Ok },
|
||||
new object[] { 5f, 100d, HitResult.Ok },
|
||||
new object[] { 5f, 99.7d, HitResult.Meh },
|
||||
new object[] { 5f, 100d, HitResult.Meh },
|
||||
new object[] { 5f, 100.4d, HitResult.Meh },
|
||||
new object[] { 5f, 100.9d, HitResult.Meh },
|
||||
new object[] { 5f, 101d, HitResult.Meh },
|
||||
new object[] { 5f, 149d, HitResult.Meh },
|
||||
new object[] { 5f, 149.2d, HitResult.Meh },
|
||||
new object[] { 5f, 149.7d, HitResult.Meh },
|
||||
new object[] { 5f, 150d, HitResult.Meh },
|
||||
new object[] { 5f, 149.7d, HitResult.Miss },
|
||||
new object[] { 5f, 150d, HitResult.Miss },
|
||||
new object[] { 5f, 150.4d, HitResult.Miss },
|
||||
new object[] { 5f, 150.9d, HitResult.Miss },
|
||||
new object[] { 5f, 151d, HitResult.Miss },
|
||||
|
||||
// OD = 5.7 test cases.
|
||||
// GREAT hit window is [ -45.8ms, 45.8ms]
|
||||
// OK hit window is [ -94.4ms, 94.4ms]
|
||||
// MEH hit window is [-143.0ms, 143.0ms]
|
||||
// MISS hit window is [-400.0ms, 400.0ms]
|
||||
new object[] { 5.7f, 45d, HitResult.Great },
|
||||
new object[] { 5.7f, 45.2d, HitResult.Great },
|
||||
new object[] { 5.7f, 45.8d, HitResult.Great },
|
||||
new object[] { 5.7f, 45.9d, HitResult.Ok },
|
||||
new object[] { 5.7f, 46d, HitResult.Ok },
|
||||
new object[] { 5.7f, 46.4d, HitResult.Ok },
|
||||
new object[] { 5.7f, 94d, HitResult.Ok },
|
||||
new object[] { 5.7f, 94.2d, HitResult.Ok },
|
||||
new object[] { 5.7f, 94.4d, HitResult.Ok },
|
||||
new object[] { 5.7f, 94.48d, HitResult.Ok },
|
||||
new object[] { 5.7f, 94.9d, HitResult.Meh },
|
||||
new object[] { 5.7f, 95d, HitResult.Meh },
|
||||
new object[] { 5.7f, 95.4d, HitResult.Meh },
|
||||
// GREAT hit window is [ -44.5ms, 44.5ms]
|
||||
// OK hit window is [ -93.5ms, 93.5ms]
|
||||
// MEH hit window is [-142.5ms, 142.5ms]
|
||||
new object[] { 5.7f, 44d, HitResult.Great },
|
||||
new object[] { 5.7f, 44.2d, HitResult.Great },
|
||||
new object[] { 5.7f, 44.8d, HitResult.Ok },
|
||||
new object[] { 5.7f, 45d, HitResult.Ok },
|
||||
new object[] { 5.7f, 45.4d, HitResult.Ok },
|
||||
new object[] { 5.7f, 93d, HitResult.Ok },
|
||||
new object[] { 5.7f, 93.4d, HitResult.Ok },
|
||||
new object[] { 5.7f, 93.9d, HitResult.Meh },
|
||||
new object[] { 5.7f, 94d, HitResult.Meh },
|
||||
new object[] { 5.7f, 94.4d, HitResult.Meh },
|
||||
new object[] { 5.7f, 142d, HitResult.Meh },
|
||||
new object[] { 5.7f, 142.7d, HitResult.Meh },
|
||||
new object[] { 5.7f, 143d, HitResult.Meh },
|
||||
new object[] { 5.7f, 142.2d, HitResult.Meh },
|
||||
new object[] { 5.7f, 142.7d, HitResult.Miss },
|
||||
new object[] { 5.7f, 143d, HitResult.Miss },
|
||||
new object[] { 5.7f, 143.4d, HitResult.Miss },
|
||||
new object[] { 5.7f, 143.9d, HitResult.Miss },
|
||||
new object[] { 5.7f, 144d, HitResult.Miss },
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 100, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 100, slider_end_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 99, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 99, slider_end_position, OsuAction.LeftButton),
|
||||
});
|
||||
|
||||
assertHeadJudgement(HitResult.Ok);
|
||||
@@ -70,8 +70,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 100, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 100, slider_end_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 99, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 99, slider_end_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.SliderVelocityMultiplier = 2;
|
||||
@@ -91,8 +91,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_end_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_end_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.TickDistanceMultiplier = 0.2f;
|
||||
@@ -116,8 +116,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_end_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_end_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.SliderVelocityMultiplier = 2;
|
||||
@@ -165,8 +165,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.LINEAR, new[]
|
||||
@@ -195,8 +195,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.LINEAR, new[]
|
||||
@@ -224,8 +224,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.PERFECT_CURVE, new[]
|
||||
@@ -259,8 +259,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.PERFECT_CURVE, new[]
|
||||
@@ -289,8 +289,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position, OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position, OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.PERFECT_CURVE, new[]
|
||||
@@ -320,8 +320,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
performTest(new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(time_slider_start + 150, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 150, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_start + 149, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(time_slider_end + 149, slider_start_position - new Vector2(20), OsuAction.LeftButton),
|
||||
}, s =>
|
||||
{
|
||||
s.Path = new SliderPath(PathType.PERFECT_CURVE, new[]
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UserAdjustedSettingsCount != 1)
|
||||
if (!IsExactlyOneSettingChanged(CircleSize, ApproachRate, OverallDifficulty, DrainRate))
|
||||
return string.Empty;
|
||||
|
||||
if (!CircleSize.IsDefault) return format("CS", CircleSize);
|
||||
|
||||
@@ -38,9 +38,9 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
public override void SetDifficulty(double difficulty)
|
||||
{
|
||||
great = IBeatmapDifficultyInfo.DifficultyRange(difficulty, GREAT_WINDOW_RANGE);
|
||||
ok = IBeatmapDifficultyInfo.DifficultyRange(difficulty, OK_WINDOW_RANGE);
|
||||
meh = IBeatmapDifficultyInfo.DifficultyRange(difficulty, MEH_WINDOW_RANGE);
|
||||
great = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, GREAT_WINDOW_RANGE)) - 0.5;
|
||||
ok = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, OK_WINDOW_RANGE)) - 0.5;
|
||||
meh = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, MEH_WINDOW_RANGE)) - 0.5;
|
||||
}
|
||||
|
||||
public override double WindowFor(HitResult result)
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Judgements
|
||||
PerformTest(new List<ReplayFrame>
|
||||
{
|
||||
new TaikoReplayFrame(0),
|
||||
new TaikoReplayFrame(hit_time - hitWindows.WindowFor(HitResult.Great), TaikoAction.LeftCentre),
|
||||
new TaikoReplayFrame(hit_time - (hitWindows.WindowFor(HitResult.Great) + 0.1), TaikoAction.LeftCentre),
|
||||
}, beatmap);
|
||||
|
||||
AssertJudgementCount(1);
|
||||
|
||||
@@ -15,7 +15,6 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneLegacyReplayPlayback : LegacyReplayPlaybackTestScene
|
||||
{
|
||||
protected override string? ExportLocation => null;
|
||||
@@ -177,7 +176,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
ScoreInfo = new ScoreInfo
|
||||
{
|
||||
Ruleset = CreateRuleset().RulesetInfo,
|
||||
Mods = [new TaikoModHardRock()]
|
||||
Mods = [new TaikoModEasy()]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
[Ignore("These tests are expected to fail until an acceptable solution for various replay playback issues concerning rounding of replay frame times & hit windows is found.")]
|
||||
public partial class TestSceneReplayStability : ReplayStabilityTestScene
|
||||
{
|
||||
private static readonly object[][] test_cases =
|
||||
@@ -22,40 +21,38 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
// while round brackets `()` represent *open* or *exclusive* bounds.
|
||||
|
||||
// OD = 5 test cases.
|
||||
// GREAT hit window is [-35ms, 35ms]
|
||||
// OK hit window is [-80ms, 80ms]
|
||||
// MISS hit window is [-95ms, 95ms]
|
||||
// GREAT hit window is [-34.5ms, 34.5ms]
|
||||
// OK hit window is [-79.5ms, 79.5ms]
|
||||
// MISS hit window is [-94.5ms, 94.5ms]
|
||||
new object[] { 5f, -34d, HitResult.Great },
|
||||
new object[] { 5f, -34.2d, HitResult.Great },
|
||||
new object[] { 5f, -34.7d, HitResult.Great },
|
||||
new object[] { 5f, -35d, HitResult.Great },
|
||||
new object[] { 5f, -34.7d, HitResult.Ok },
|
||||
new object[] { 5f, -35d, HitResult.Ok },
|
||||
new object[] { 5f, -35.2d, HitResult.Ok },
|
||||
new object[] { 5f, -35.8d, HitResult.Ok },
|
||||
new object[] { 5f, -36d, HitResult.Ok },
|
||||
new object[] { 5f, -79d, HitResult.Ok },
|
||||
new object[] { 5f, -79.3d, HitResult.Ok },
|
||||
new object[] { 5f, -79.7d, HitResult.Ok },
|
||||
new object[] { 5f, -80d, HitResult.Ok },
|
||||
new object[] { 5f, -79.7d, HitResult.Miss },
|
||||
new object[] { 5f, -80d, HitResult.Miss },
|
||||
new object[] { 5f, -80.2d, HitResult.Miss },
|
||||
new object[] { 5f, -80.8d, HitResult.Miss },
|
||||
new object[] { 5f, -81d, HitResult.Miss },
|
||||
|
||||
// OD = 7.8 test cases.
|
||||
// GREAT hit window is [-26.6ms, 26.6ms]
|
||||
// OK hit window is [-63.2ms, 63.2ms]
|
||||
// MISS hit window is [-81.0ms, 81.0ms]
|
||||
new object[] { 7.8f, -26d, HitResult.Great },
|
||||
new object[] { 7.8f, -26.4d, HitResult.Great },
|
||||
new object[] { 7.8f, -26.59d, HitResult.Great },
|
||||
new object[] { 7.8f, -26.8d, HitResult.Ok },
|
||||
new object[] { 7.8f, -27d, HitResult.Ok },
|
||||
new object[] { 7.8f, -27.1d, HitResult.Ok },
|
||||
new object[] { 7.8f, -63d, HitResult.Ok },
|
||||
new object[] { 7.8f, -63.18d, HitResult.Ok },
|
||||
new object[] { 7.8f, -63.4d, HitResult.Ok },
|
||||
new object[] { 7.8f, -63.7d, HitResult.Miss },
|
||||
new object[] { 7.8f, -64d, HitResult.Miss },
|
||||
new object[] { 7.8f, -64.2d, HitResult.Miss },
|
||||
// GREAT hit window is [-25.5ms, 25.5ms]
|
||||
// OK hit window is [-62.5ms, 62.5ms]
|
||||
// MISS hit window is [-80.5ms, 80.5ms]
|
||||
new object[] { 7.8f, -25d, HitResult.Great },
|
||||
new object[] { 7.8f, -25.4d, HitResult.Great },
|
||||
new object[] { 7.8f, -25.8d, HitResult.Ok },
|
||||
new object[] { 7.8f, -26d, HitResult.Ok },
|
||||
new object[] { 7.8f, -26.1d, HitResult.Ok },
|
||||
new object[] { 7.8f, -62d, HitResult.Ok },
|
||||
new object[] { 7.8f, -62.4d, HitResult.Ok },
|
||||
new object[] { 7.8f, -62.7d, HitResult.Miss },
|
||||
new object[] { 7.8f, -63d, HitResult.Miss },
|
||||
new object[] { 7.8f, -63.2d, HitResult.Miss },
|
||||
};
|
||||
|
||||
[TestCaseSource(nameof(test_cases))]
|
||||
|
||||
@@ -14,26 +14,27 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
|
||||
protected override IResourceStore<byte[]> RulesetResources => new DllResourceStore(Assembly.GetAssembly(typeof(TestSceneTaikoHitObjectSamples)));
|
||||
|
||||
[TestCase("taiko-normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string expectedSample)
|
||||
[TestCase("taiko-normal-hitnormal2", "taiko-normal-hitnormal")]
|
||||
[TestCase("hitnormal", "hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string beatmapSkinSampleName, string userSkinSampleName)
|
||||
{
|
||||
SetupSkins(expectedSample, expectedSample);
|
||||
SetupSkins(beatmapSkinSampleName, userSkinSampleName);
|
||||
|
||||
CreateTestWithBeatmap("taiko-hitobject-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertBeatmapLookup(expectedSample);
|
||||
AssertBeatmapLookup(beatmapSkinSampleName);
|
||||
}
|
||||
|
||||
[TestCase("taiko-normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromUserSkinFallback(string expectedSample)
|
||||
[TestCase("", "taiko-normal-hitnormal")]
|
||||
[TestCase("taiko-normal-hitnormal", "taiko-normal-hitnormal")]
|
||||
[TestCase("", "hitnormal")]
|
||||
public void TestDefaultCustomSampleFromUserSkinFallback(string beatmapSkinSampleName, string userSkinSampleName)
|
||||
{
|
||||
SetupSkins(string.Empty, expectedSample);
|
||||
SetupSkins(beatmapSkinSampleName, userSkinSampleName);
|
||||
|
||||
CreateTestWithBeatmap("taiko-hitobject-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertUserLookup(expectedSample);
|
||||
AssertUserLookup(userSkinSampleName);
|
||||
}
|
||||
|
||||
[TestCase("taiko-normal-hitnormal2")]
|
||||
|
||||
@@ -25,16 +25,16 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UserAdjustedSettingsCount != 1)
|
||||
if (!IsExactlyOneSettingChanged(ScrollSpeed, OverallDifficulty, DrainRate))
|
||||
return string.Empty;
|
||||
|
||||
if (!ScrollSpeed.IsDefault) return format("SC", ScrollSpeed);
|
||||
if (!OverallDifficulty.IsDefault) return format("OD", OverallDifficulty);
|
||||
if (!DrainRate.IsDefault) return format("HP", DrainRate);
|
||||
if (!ScrollSpeed.IsDefault) return format("SC", ScrollSpeed, 2);
|
||||
if (!OverallDifficulty.IsDefault) return format("OD", OverallDifficulty, 1);
|
||||
if (!DrainRate.IsDefault) return format("HP", DrainRate, 1);
|
||||
|
||||
return string.Empty;
|
||||
|
||||
string format(string acronym, DifficultyBindable bindable) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||
string format(string acronym, DifficultyBindable bindable, int digits) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(digits)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
|
||||
public override void SetDifficulty(double difficulty)
|
||||
{
|
||||
great = IBeatmapDifficultyInfo.DifficultyRange(difficulty, GREAT_WINDOW_RANGE);
|
||||
ok = IBeatmapDifficultyInfo.DifficultyRange(difficulty, OK_WINDOW_RANGE);
|
||||
miss = IBeatmapDifficultyInfo.DifficultyRange(difficulty, MISS_WINDOW_RANGE);
|
||||
great = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, GREAT_WINDOW_RANGE)) - 0.5;
|
||||
ok = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, OK_WINDOW_RANGE)) - 0.5;
|
||||
miss = Math.Floor(IBeatmapDifficultyInfo.DifficultyRange(difficulty, MISS_WINDOW_RANGE)) - 0.5;
|
||||
}
|
||||
|
||||
public override double WindowFor(HitResult result)
|
||||
|
||||
@@ -64,11 +64,9 @@ namespace osu.Game.Tests.Gameplay
|
||||
/// <summary>
|
||||
/// Tests that a hitobject which provides a custom sample set of 2 retrieves the following samples from the beatmap skin:
|
||||
/// normal-hitnormal2
|
||||
/// normal-hitnormal
|
||||
/// hitnormal
|
||||
/// </summary>
|
||||
[TestCase("normal-hitnormal2")]
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestDefaultCustomSampleFromBeatmap(string expectedSample)
|
||||
{
|
||||
@@ -162,7 +160,6 @@ namespace osu.Game.Tests.Gameplay
|
||||
/// Tests that a control point that provides a custom sample of 2 causes <see cref="TestDefaultCustomSampleFromBeatmap"/>.
|
||||
/// </summary>
|
||||
[TestCase("normal-hitnormal2")]
|
||||
[TestCase("normal-hitnormal")]
|
||||
[TestCase("hitnormal")]
|
||||
public void TestControlPointCustomSampleFromBeatmap(string sampleName)
|
||||
{
|
||||
|
||||
@@ -342,13 +342,14 @@ namespace osu.Game.Tests.Mods
|
||||
{
|
||||
foreach (var mod in ruleset.CreateAllMods())
|
||||
{
|
||||
if (mod.ValidForFreestyleAsRequiredMod && mod.UserPlayable && !commonAcronyms.Contains(mod.Acronym))
|
||||
Assert.Fail($"{mod.GetType().ReadableName()} declares {nameof(Mod.ValidForFreestyleAsRequiredMod)} but does not exist in all four basic rulesets!");
|
||||
if (mod.ValidForFreestyleAsRequiredMod && !mod.UserPlayable)
|
||||
Assert.Fail($"Mod {mod.GetType().ReadableName()} declares {nameof(Mod.ValidForFreestyleAsRequiredMod)} but is not playable!");
|
||||
|
||||
// downgraded to warning, because there are valid reasons why they may still not be specified to be valid for freestyle as required
|
||||
// (see `TestModsValidForRequiredFreestyleAreConsistentlyCompatibleAcrossRulesets()` test case below).
|
||||
if (!mod.ValidForFreestyleAsRequiredMod && mod.UserPlayable && commonAcronyms.Contains(mod.Acronym))
|
||||
Assert.Warn($"{mod.GetType().ReadableName()} does not declare {nameof(Mod.ValidForFreestyleAsRequiredMod)} but exists in all four basic rulesets.");
|
||||
if (mod.ValidForFreestyleAsRequiredMod && !mod.HasImplementation)
|
||||
Assert.Fail($"Mod {mod.GetType().ReadableName()} declares {nameof(Mod.ValidForFreestyleAsRequiredMod)} but is not implemented!");
|
||||
|
||||
if (mod.ValidForFreestyleAsRequiredMod && mod.UserPlayable && mod.HasImplementation && !commonAcronyms.Contains(mod.Acronym))
|
||||
Assert.Fail($"{mod.GetType().ReadableName()} declares {nameof(Mod.ValidForFreestyleAsRequiredMod)} but does not exist in all four basic rulesets!");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK;
|
||||
@@ -325,7 +325,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
private void setupUserSettings()
|
||||
{
|
||||
AddUntilStep("Song select is current", () => songSelect.IsCurrentScreen());
|
||||
AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmapInfo != null);
|
||||
AddUntilStep("Song select has selection", () => songSelect.Carousel?.CurrentSelection != null);
|
||||
AddStep("Set default user settings", () =>
|
||||
{
|
||||
SelectedMods.Value = new[] { new OsuModNoFail() };
|
||||
@@ -340,7 +340,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
rulesets?.Dispose();
|
||||
}
|
||||
|
||||
private partial class DummySongSelect : PlaySongSelect
|
||||
private partial class DummySongSelect : SoloSongSelect
|
||||
{
|
||||
private FadeAccessibleBackground background;
|
||||
|
||||
@@ -355,7 +355,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public readonly Bindable<double> DimLevel = new BindableDouble();
|
||||
public readonly Bindable<double> BlurLevel = new BindableDouble();
|
||||
|
||||
public new BeatmapCarousel Carousel => base.Carousel;
|
||||
public BeatmapCarousel Carousel => this.ChildrenOfType<BeatmapCarousel>().SingleOrDefault();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
@@ -368,7 +368,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
public bool IsBackgroundDimmed() => background.CurrentColour == OsuColour.Gray(1f - background.CurrentDim);
|
||||
|
||||
public bool IsBackgroundUndimmed() => background.CurrentColour == Color4.White;
|
||||
public bool IsBackgroundUndimmed() => background.CurrentColour == new Color4(0.9f, 0.9f, 0.9f, 1f);
|
||||
|
||||
public bool IsUserBlurApplied() => Precision.AlmostEquals(background.CurrentBlur, new Vector2((float)BlurLevel.Value * BackgroundScreenBeatmap.USER_BLUR_FACTOR), 0.1f);
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
public bool IsBackgroundVisible() => background.CurrentAlpha == 1;
|
||||
|
||||
public bool IsBackgroundBlur() => Precision.AlmostEquals(background.CurrentBlur, new Vector2(BACKGROUND_BLUR), 0.1f);
|
||||
public bool IsBackgroundBlur() => Precision.AlmostBigger(background.CurrentBlur.X, 0, 0.1f);
|
||||
|
||||
public bool CheckBackgroundBlur(Vector2 expected) => Precision.AlmostEquals(background.CurrentBlur, expected, 0.1f);
|
||||
|
||||
|
||||
@@ -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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
@@ -190,7 +190,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddStep("Set tags again", () => EditorBeatmap.BeatmapInfo.Metadata.Tags = tags_to_discard);
|
||||
|
||||
AddStep("Exit editor", () => Editor.Exit());
|
||||
AddUntilStep("Wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddUntilStep("Wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
AddAssert("Tags reverted correctly", () => Game.Beatmap.Value.BeatmapInfo.Metadata.Tags == tags_to_save);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Resources;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editing
|
||||
@@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
() => Is.EqualTo(1));
|
||||
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("entered song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("entered song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
addStepClickLink("00:00:000 (1)", waitForSeek: false);
|
||||
AddUntilStep("received 'must be in edit'",
|
||||
@@ -151,12 +151,12 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddStep("Present beatmap", () => Game.PresentBeatmap(beatmapSet));
|
||||
AddUntilStep("Wait for song select", () =>
|
||||
Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet)
|
||||
&& Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect
|
||||
&& songSelect.BeatmapSetsLoaded
|
||||
&& Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect
|
||||
&& songSelect.CarouselItemsPresented
|
||||
);
|
||||
AddStep("Switch ruleset", () => Game.Ruleset.Value = ruleset);
|
||||
AddStep("Open editor for ruleset", () =>
|
||||
((PlaySongSelect)Game.ScreenStack.CurrentScreen)
|
||||
((SoloSongSelect)Game.ScreenStack.CurrentScreen)
|
||||
.Edit(beatmapSet.Beatmaps.Last(beatmap => beatmap.Ruleset.Name == ruleset.Name))
|
||||
);
|
||||
AddUntilStep("Wait for editor open", () => editor?.ReadyForUse == true);
|
||||
|
||||
@@ -9,7 +9,6 @@ using osu.Game.Audio;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
@@ -74,8 +73,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
//
|
||||
// We want to keep seeking while asserting various test conditions, so
|
||||
// continue to seek until we unset the flag.
|
||||
var gameplayClockContainer = Player.ChildrenOfType<GameplayClockContainer>().First();
|
||||
gameplayClockContainer.Seek(gameplayClockContainer.CurrentTime > 30000 ? 0 : 60000);
|
||||
var gameplayClockContainer = Player?.GameplayClockContainer;
|
||||
gameplayClockContainer?.Seek(gameplayClockContainer.CurrentTime > 30000 ? 0 : 60000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,16 @@ using NUnit.Framework;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
@@ -157,6 +162,51 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("Jumped forwards", () => Player.GameplayClockContainer.CurrentTime - lastTime > 500);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestReplayDoesNotFailUntilRunningOutOfFrames()
|
||||
{
|
||||
var score = new Score
|
||||
{
|
||||
ScoreInfo = TestResources.CreateTestScoreInfo(Beatmap.Value.BeatmapInfo),
|
||||
Replay = new Replay
|
||||
{
|
||||
Frames =
|
||||
{
|
||||
new OsuReplayFrame(0, Vector2.Zero),
|
||||
new OsuReplayFrame(10000, Vector2.Zero),
|
||||
}
|
||||
}
|
||||
};
|
||||
score.ScoreInfo.Mods = [];
|
||||
score.ScoreInfo.Rank = ScoreRank.F;
|
||||
AddStep("set global state", () =>
|
||||
{
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
Ruleset.Value = Beatmap.Value.BeatmapInfo.Ruleset;
|
||||
SelectedMods.Value = score.ScoreInfo.Mods;
|
||||
});
|
||||
AddStep("create player", () => Player = new TestReplayPlayer(score, showResults: false));
|
||||
AddStep("load player", () => LoadScreen(Player));
|
||||
AddUntilStep("wait for loaded", () => Player.IsCurrentScreen());
|
||||
AddStep("seek to 8000", () => Player.Seek(8000));
|
||||
AddUntilStep("wait for fail", () => Player.GameplayState.HasFailed);
|
||||
AddAssert("player failed after 10000", () => Player.GameplayClockContainer.CurrentTime, () => Is.GreaterThanOrEqualTo(10000));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlayerLoaderSettingsHover()
|
||||
{
|
||||
loadPlayerWithBeatmap();
|
||||
|
||||
AddUntilStep("wait for settings overlay hidden", () => settingsOverlay().Expanded.Value, () => Is.False);
|
||||
AddStep("move mouse to right of screen", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopRight));
|
||||
AddUntilStep("wait for settings overlay visible", () => settingsOverlay().Expanded.Value, () => Is.True);
|
||||
AddStep("move mouse to centre of screen", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddUntilStep("wait for settings overlay hidden", () => settingsOverlay().Expanded.Value, () => Is.False);
|
||||
|
||||
PlayerSettingsOverlay settingsOverlay() => Player.ChildrenOfType<PlayerSettingsOverlay>().Single();
|
||||
}
|
||||
|
||||
private void loadPlayerWithBeatmap(IBeatmap? beatmap = null)
|
||||
{
|
||||
AddStep("create player", () =>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("exit", () => getEditor().Exit());
|
||||
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect
|
||||
&& songSelect.Beatmap.Value is DummyWorkingBeatmap);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("switch ruleset at song select", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
|
||||
AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
|
||||
AddStep("open editor", () => ((SoloSongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
|
||||
|
||||
AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse);
|
||||
AddAssert("editor ruleset is osu!", () => Game.Ruleset.Value, () => Is.EqualTo(new OsuRuleset().RulesetInfo));
|
||||
@@ -187,8 +187,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
});
|
||||
AddAssert("gameplay ruleset is osu!", () => Game.Ruleset.Value, () => Is.EqualTo(new OsuRuleset().RulesetInfo));
|
||||
|
||||
AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield()));
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(SoloSongSelect).Yield()));
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
AddAssert("previous ruleset restored", () => Game.Ruleset.Value.Equals(new ManiaRuleset().RulesetInfo));
|
||||
}
|
||||
|
||||
@@ -289,8 +289,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("user request play", () => Game.MusicController.Play(requestedByUser: true));
|
||||
AddUntilStep("music still stopped", () => !Game.MusicController.IsPlaying);
|
||||
|
||||
AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(PlaySongSelect).Yield()));
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddStep("exit to song select", () => Game.PerformFromScreen(_ => { }, typeof(SoloSongSelect).Yield()));
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
|
||||
AddUntilStep("wait for music playing", () => Game.MusicController.IsPlaying);
|
||||
AddStep("user request stop", () => Game.MusicController.Stop(requestedByUser: true));
|
||||
@@ -352,13 +352,13 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("present beatmap", () => Game.PresentBeatmap(beatmapSet));
|
||||
AddUntilStep("wait for song select",
|
||||
() => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet)
|
||||
&& Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect
|
||||
&& songSelect.BeatmapSetsLoaded);
|
||||
&& Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect
|
||||
&& songSelect.CarouselItemsPresented);
|
||||
}
|
||||
|
||||
private void openEditor()
|
||||
{
|
||||
AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
|
||||
AddStep("open editor", () => ((SoloSongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
|
||||
AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
@@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
InputManager.Key(Key.P);
|
||||
});
|
||||
|
||||
AddAssert("entered song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddAssert("entered song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("state is play", () => buttons.State == ButtonSystemState.Play);
|
||||
|
||||
AddStep("press P", () => InputManager.Key(Key.P));
|
||||
AddAssert("entered song select", () => Game.ScreenStack.CurrentScreen is PlaySongSelect);
|
||||
AddAssert("entered song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -54,10 +54,10 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
PushAndConfirm(() => new PlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
|
||||
AddUntilStep("wait for selection", () => !Game.Beatmap.IsDefault);
|
||||
AddUntilStep("wait for carousel load", () => songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for carousel load", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("enter gameplay", () => InputManager.Key(Key.Enter));
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
.AsEnumerable()
|
||||
.First(k => k.RulesetName == "osu" && k.ActionInt == 0);
|
||||
|
||||
private Screens.Select.SongSelect songSelect => Game.ScreenStack.CurrentScreen as Screens.Select.SongSelect;
|
||||
private SoloSongSelect songSelect => Game.ScreenStack.CurrentScreen as SoloSongSelect;
|
||||
|
||||
private Player player => Game.ScreenStack.CurrentScreen as Player;
|
||||
|
||||
|
||||
@@ -5,6 +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.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -83,9 +84,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
private void loadToPlayerNonBreakTime()
|
||||
{
|
||||
Player? player = null;
|
||||
Screens.Select.SongSelect songSelect = null!;
|
||||
PushAndConfirm(() => songSelect = new TestSceneScreenNavigation.TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
SoloSongSelect songSelect = null!;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game, virtualTrack: true).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
@@ -17,9 +17,9 @@ 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.Tests.Beatmaps.IO;
|
||||
using osuTK.Input;
|
||||
using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
@@ -44,17 +44,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestPerformAtSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => new TestPlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
|
||||
AddStep("perform immediately", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(TestPlaySongSelect) }));
|
||||
AddStep("perform immediately", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(SoloSongSelect) }));
|
||||
AddAssert("did perform", () => actionPerformed);
|
||||
AddAssert("screen didn't change", () => Game.ScreenStack.CurrentScreen is TestPlaySongSelect);
|
||||
AddAssert("screen didn't change", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPerformAtMenuFromSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => new TestPlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
|
||||
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true));
|
||||
AddUntilStep("returned to menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
|
||||
@@ -69,8 +69,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("Press enter", () => InputManager.Key(Key.Enter));
|
||||
AddUntilStep("Wait for new screen", () => Game.ScreenStack.CurrentScreen is PlayerLoader);
|
||||
|
||||
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(TestPlaySongSelect) }));
|
||||
AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is TestPlaySongSelect);
|
||||
AddStep("try to perform", () => Game.PerformFromScreen(_ => actionPerformed = true, new[] { typeof(SoloSongSelect) }));
|
||||
AddUntilStep("returned to song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect);
|
||||
AddAssert("did perform", () => actionPerformed);
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
private void importAndWaitForSongSelect()
|
||||
{
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
PushAndConfirm(() => new TestPlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
AddUntilStep("beatmap updated", () => Game.Beatmap.Value.BeatmapSetInfo.OnlineID == 241526);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
@@ -81,11 +81,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
presentAndConfirm(osuImport);
|
||||
|
||||
var maniaImport = importBeatmap(2, new ManiaRuleset().RulesetInfo);
|
||||
confirmBeatmapInSongSelect(maniaImport);
|
||||
presentAndConfirm(maniaImport);
|
||||
|
||||
var catchImport = importBeatmap(3, new CatchRuleset().RulesetInfo);
|
||||
confirmBeatmapInSongSelect(catchImport);
|
||||
presentAndConfirm(catchImport);
|
||||
|
||||
// Ruleset is always changed.
|
||||
@@ -103,11 +101,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
presentAndConfirm(osuImport);
|
||||
|
||||
var maniaImport = importBeatmap(2, new ManiaRuleset().RulesetInfo);
|
||||
confirmBeatmapInSongSelect(maniaImport);
|
||||
presentAndConfirm(maniaImport);
|
||||
|
||||
var catchImport = importBeatmap(3, new CatchRuleset().RulesetInfo);
|
||||
confirmBeatmapInSongSelect(catchImport);
|
||||
presentAndConfirm(catchImport);
|
||||
|
||||
// force ruleset to osu!mania
|
||||
@@ -178,14 +174,14 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
AddUntilStep("wait for carousel loaded", () =>
|
||||
{
|
||||
var songSelect = (Screens.Select.SongSelect)Game.ScreenStack.CurrentScreen;
|
||||
var songSelect = (SoloSongSelect)Game.ScreenStack.CurrentScreen;
|
||||
return songSelect.ChildrenOfType<BeatmapCarousel>().SingleOrDefault()?.IsLoaded == true;
|
||||
});
|
||||
|
||||
AddUntilStep("beatmap in song select", () =>
|
||||
{
|
||||
var songSelect = (Screens.Select.SongSelect)Game.ScreenStack.CurrentScreen;
|
||||
return songSelect.ChildrenOfType<BeatmapCarousel>().Single().BeatmapSets.Any(b => b.MatchesOnlineID(getImport()));
|
||||
var songSelect = (SoloSongSelect)Game.ScreenStack.CurrentScreen;
|
||||
return songSelect.ChildrenOfType<BeatmapCarousel>().Single().GetCarouselItems()!.Any(i => i.Model is BeatmapSetInfo bsi && bsi.MatchesOnlineID(getImport()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -193,7 +189,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
||||
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.OnlineID, () => Is.EqualTo(getImport().OnlineID));
|
||||
AddAssert("correct ruleset selected", () => Game.Ruleset.Value, () => Is.EqualTo(getImport().Beatmaps.First().Ruleset));
|
||||
}
|
||||
@@ -203,7 +199,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
Predicate<BeatmapInfo> pred = b => b.OnlineID == importedID * 1024 + 2;
|
||||
AddStep("present difficulty", () => Game.PresentBeatmap(getImport(), pred));
|
||||
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID, () => Is.EqualTo(importedID * 1024 + 2));
|
||||
AddAssert("correct ruleset selected", () => Game.Ruleset.Value.OnlineID, () => Is.EqualTo(expectedRulesetOnlineID ?? getImport().Beatmaps.First().Ruleset.OnlineID));
|
||||
}
|
||||
|
||||
@@ -18,7 +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.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using FilterControl = osu.Game.Screens.SelectV2.FilterControl;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
@@ -96,9 +97,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestFromSongSelectWithFilter([Values] ScorePresentType type)
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("filter to nothing", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).FilterControl.CurrentTextSearch.Value = "fdsajkl;fgewq");
|
||||
AddStep("filter to nothing", () => ((SoloSongSelect)Game.ScreenStack.CurrentScreen).ChildrenOfType<FilterControl>().Single().Search("fdsajkl;fgewq"));
|
||||
AddUntilStep("wait for no results", () => Beatmap.IsDefault);
|
||||
|
||||
var firstImport = importScore(1, new CatchRuleset().RulesetInfo);
|
||||
@@ -109,7 +110,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestFromSongSelectWithConvertRulesetChange([Values] ScorePresentType type)
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("set convert to false", () => Game.LocalConfig.SetValue(OsuSetting.ShowConvertedBeatmaps, false));
|
||||
|
||||
@@ -121,7 +122,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestFromSongSelect([Values] ScorePresentType type)
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
var firstImport = importScore(1);
|
||||
presentAndConfirm(firstImport, type);
|
||||
@@ -134,7 +135,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestFromSongSelectDifferentRuleset([Values] ScorePresentType type)
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
var firstImport = importScore(1);
|
||||
presentAndConfirm(firstImport, type);
|
||||
@@ -147,7 +148,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestPresentTwoImportsWithSameOnlineIDButDifferentHashes([Values] ScorePresentType type)
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
var firstImport = importScore(1);
|
||||
presentAndConfirm(firstImport, type);
|
||||
@@ -160,7 +161,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestScoreRefetchIgnoresEmptyHash()
|
||||
{
|
||||
AddStep("enter song select", () => Game.ChildrenOfType<ButtonSystem>().Single().OnSolo?.Invoke());
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is PlaySongSelect songSelect && songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("song select is current", () => Game.ScreenStack.CurrentScreen is SoloSongSelect songSelect && songSelect.CarouselItemsPresented);
|
||||
|
||||
importScore(-1, hash: string.Empty);
|
||||
importScore(3, hash: @"deadbeef");
|
||||
|
||||
@@ -26,7 +26,6 @@ using osu.Game.Graphics.Carousel;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Online.Notifications.WebSocket;
|
||||
using osu.Game.Online.Notifications.WebSocket.Events;
|
||||
using osu.Game.Overlays;
|
||||
@@ -49,20 +48,13 @@ using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Screens.Ranking;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.Select.Options;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using BeatmapCarousel = osu.Game.Screens.Select.BeatmapCarousel;
|
||||
using CollectionDropdown = osu.Game.Collections.CollectionDropdown;
|
||||
using FilterControl = osu.Game.Screens.Select.FilterControl;
|
||||
using FooterButtonRandom = osu.Game.Screens.Select.FooterButtonRandom;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
@@ -146,62 +138,70 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestExitSongSelectWithEscape()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
ModSelectOverlay modSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddStep("Show mods overlay", () =>
|
||||
{
|
||||
modSelect = songSelect!.ChildrenOfType<ModSelectOverlay>().Single();
|
||||
modSelect.Show();
|
||||
});
|
||||
AddAssert("Overlay was shown", () => modSelect.State.Value == Visibility.Visible);
|
||||
pushEscape();
|
||||
AddAssert("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
AddAssert("Overlay was hidden", () => modSelect.State.Value == Visibility.Hidden);
|
||||
exitViaEscapeAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEnterGameplayWhileFilteringToNoSelection()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("force selection", () =>
|
||||
AddStep("force selection and change filter immediately", () =>
|
||||
{
|
||||
songSelect.FinaliseSelection();
|
||||
songSelect.FilterControl.CurrentTextSearch.Value = "test";
|
||||
InputManager.Key(Key.Enter);
|
||||
songSelect.ChildrenOfType<FilterControl>().Single().Search("test");
|
||||
});
|
||||
|
||||
AddUntilStep("wait for player", () => !songSelect.IsCurrentScreen());
|
||||
AddStep("return to song select", () => songSelect.MakeCurrent());
|
||||
|
||||
AddUntilStep("wait for selection lost", () => songSelect.Beatmap.IsDefault);
|
||||
AddUntilStep("selection not lost", () => !songSelect.Beatmap.IsDefault);
|
||||
AddUntilStep("placeholder visible", () => songSelect.ChildrenOfType<NoResultsPlaceholder>().Single().State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSongSelectBackActionHandling()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
|
||||
AddUntilStep("wait for filter control", () => filterControlTextBox().IsLoaded);
|
||||
|
||||
AddStep("set filter", () => filterControlTextBox().Current.Value = "test");
|
||||
AddStep("press back", () => InputManager.Click(MouseButton.Button1));
|
||||
|
||||
AddAssert("still at song select", () => Game.ScreenStack.CurrentScreen == songSelect);
|
||||
AddAssert("still at song select", () => Game.ScreenStack.CurrentScreen, () => Is.EqualTo(songSelect));
|
||||
AddAssert("filter cleared", () => string.IsNullOrEmpty(filterControlTextBox().Current.Value));
|
||||
|
||||
AddStep("set filter again", () => filterControlTextBox().Current.Value = "test");
|
||||
AddStep("open collections dropdown", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(songSelect.ChildrenOfType<CollectionDropdown>().Single());
|
||||
InputManager.MoveMouseTo(songSelect.ChildrenOfType<Screens.SelectV2.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<CollectionDropdown>().Single()
|
||||
.ChildrenOfType<Screens.SelectV2.CollectionDropdown>().Single()
|
||||
.ChildrenOfType<Dropdown<CollectionFilterMenuItem>.DropdownMenu>().Single().State == MenuState.Closed);
|
||||
|
||||
AddStep("press back a second time", () => InputManager.Click(MouseButton.Button1));
|
||||
@@ -210,17 +210,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("press back a third time", () => InputManager.Click(MouseButton.Button1));
|
||||
ConfirmAtMainMenu();
|
||||
|
||||
TextBox filterControlTextBox() => songSelect.ChildrenOfType<FilterControl.FilterControlTextBox>().Single();
|
||||
FilterControl.SongSelectSearchTextBox filterControlTextBox() => songSelect.ChildrenOfType<FilterControl.SongSelectSearchTextBox>().Single();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSongSelectRandomRewindButton()
|
||||
{
|
||||
Guid? originalSelection = null;
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("Add two beatmaps", () =>
|
||||
{
|
||||
@@ -247,41 +247,6 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
[Test]
|
||||
public void TestSongSelectScrollHandling()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
double scrollPosition = 0;
|
||||
|
||||
AddStep("set game volume to max", () => Game.Dependencies.Get<FrameworkConfigManager>().SetValue(FrameworkSetting.VolumeUniversal, 1d));
|
||||
AddUntilStep("wait for volume overlay to hide", () => Game.ChildrenOfType<VolumeOverlay>().SingleOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
AddStep("store scroll position", () => scrollPosition = getCarouselScrollPosition());
|
||||
|
||||
AddStep("move to left side", () => InputManager.MoveMouseTo(
|
||||
songSelect.ChildrenOfType<Screens.Select.SongSelect.LeftSideInteractionContainer>().Single().ScreenSpaceDrawQuad.TopLeft + new Vector2(1)));
|
||||
AddStep("scroll down", () => InputManager.ScrollVerticalBy(-1));
|
||||
AddAssert("carousel didn't move", getCarouselScrollPosition, () => Is.EqualTo(scrollPosition));
|
||||
|
||||
AddRepeatStep("alt-scroll down", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.AltLeft);
|
||||
InputManager.ScrollVerticalBy(-1);
|
||||
InputManager.ReleaseKey(Key.AltLeft);
|
||||
}, 5);
|
||||
AddAssert("game volume decreased", () => Game.Dependencies.Get<FrameworkConfigManager>().Get<double>(FrameworkSetting.VolumeUniversal), () => Is.LessThan(1));
|
||||
|
||||
AddStep("move to carousel", () => InputManager.MoveMouseTo(songSelect.ChildrenOfType<BeatmapCarousel>().Single()));
|
||||
AddStep("scroll down", () => InputManager.ScrollVerticalBy(-1));
|
||||
AddAssert("carousel moved", getCarouselScrollPosition, () => Is.Not.EqualTo(scrollPosition));
|
||||
|
||||
double getCarouselScrollPosition() => Game.ChildrenOfType<UserTrackingScrollContainer<DrawableCarouselItem>>().Single().Current;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNewSongSelectScrollHandling()
|
||||
{
|
||||
SoloSongSelect songSelect = null;
|
||||
double scrollPosition = 0;
|
||||
@@ -293,6 +258,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for beatmap", () => Game.ChildrenOfType<PanelBeatmapSet>().Any());
|
||||
|
||||
// TODO: this logic can likely be removed when we fix https://github.com/ppy/osu/issues/33379
|
||||
// It should be probably be immediate in this case.
|
||||
AddWaitStep("wait for scroll", 10);
|
||||
|
||||
AddStep("store scroll position", () => scrollPosition = getCarouselScrollPosition());
|
||||
@@ -325,7 +292,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
}, 5);
|
||||
AddAssert("game volume decreased", () => Game.Dependencies.Get<FrameworkConfigManager>().Get<double>(FrameworkSetting.VolumeUniversal), () => Is.LessThan(1));
|
||||
|
||||
AddStep("move to carousel", () => InputManager.MoveMouseTo(songSelect.ChildrenOfType<Screens.SelectV2.BeatmapCarousel>().Single()));
|
||||
AddStep("move to carousel", () => InputManager.MoveMouseTo(songSelect.ChildrenOfType<BeatmapCarousel>().Single()));
|
||||
AddStep("scroll down", () => InputManager.ScrollVerticalBy(-1));
|
||||
AddAssert("carousel moved", getCarouselScrollPosition, () => Is.Not.EqualTo(scrollPosition));
|
||||
|
||||
@@ -339,21 +306,21 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestOpenModSelectOverlayUsingAction()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddStep("Show mods overlay", () => InputManager.Key(Key.F1));
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
AddAssert("Overlay was shown", () => songSelect!.ChildrenOfType<ModSelectOverlay>().Single().State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAttemptPlayBeatmapWrongHashFails()
|
||||
{
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
@@ -384,11 +351,11 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestAttemptPlayBeatmapMissingFails()
|
||||
{
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
|
||||
@@ -418,9 +385,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -461,9 +428,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -515,9 +482,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -558,9 +525,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
Player player = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -663,7 +630,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
playToResults();
|
||||
|
||||
ScoreInfo score = null;
|
||||
LeaderboardScore scorePanel = null;
|
||||
BeatmapLeaderboardScore scorePanel = null;
|
||||
|
||||
AddStep("get score", () => score = ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score);
|
||||
|
||||
@@ -672,18 +639,11 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("press back button", () => Game.ChildrenOfType<BackButton>().First().Action!.Invoke());
|
||||
|
||||
AddStep("show local scores",
|
||||
() => Game.ChildrenOfType<BeatmapDetailAreaTabControl>().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem<BeatmapLeaderboardScope>(BeatmapLeaderboardScope.Local));
|
||||
() => Game.ChildrenOfType<Dropdown<BeatmapLeaderboardScope>>().First().Current.Value = BeatmapLeaderboardScope.Local);
|
||||
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<LeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<BeatmapLeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
|
||||
AddStep("open options", () => InputManager.Key(Key.F3));
|
||||
|
||||
AddStep("choose clear all scores", () => InputManager.Key(Key.Number4));
|
||||
|
||||
AddUntilStep("wait for dialog display", () => ((Drawable)Game.Dependencies.Get<IDialogOverlay>()).IsLoaded);
|
||||
AddUntilStep("wait for dialog", () => Game.Dependencies.Get<IDialogOverlay>().CurrentDialog != null);
|
||||
AddStep("confirm deletion", () => InputManager.Key(Key.Number1));
|
||||
AddUntilStep("wait for dialog dismissed", () => Game.Dependencies.Get<IDialogOverlay>().CurrentDialog == null);
|
||||
AddStep("Clear all scores", () => Game.Dependencies.Get<ScoreManager>().Delete());
|
||||
|
||||
AddUntilStep("ensure score is pending deletion", () => Game.Realm.Run(r => r.Find<ScoreInfo>(score.ID)?.DeletePending == true));
|
||||
|
||||
@@ -696,7 +656,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
playToResults();
|
||||
|
||||
ScoreInfo score = null;
|
||||
LeaderboardScore scorePanel = null;
|
||||
BeatmapLeaderboardScore scorePanel = null;
|
||||
|
||||
AddStep("get score", () => score = ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score);
|
||||
|
||||
@@ -705,9 +665,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("press back button", () => Game.ChildrenOfType<BackButton>().First().Action!.Invoke());
|
||||
|
||||
AddStep("show local scores",
|
||||
() => Game.ChildrenOfType<BeatmapDetailAreaTabControl>().First().Current.Value = new BeatmapDetailAreaLeaderboardTabItem<BeatmapLeaderboardScope>(BeatmapLeaderboardScope.Local));
|
||||
() => Game.ChildrenOfType<Dropdown<BeatmapLeaderboardScope>>().First().Current.Value = BeatmapLeaderboardScope.Local);
|
||||
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<LeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
AddUntilStep("wait for score displayed", () => (scorePanel = Game.ChildrenOfType<BeatmapLeaderboardScore>().FirstOrDefault(s => s.Score.Equals(score))) != null);
|
||||
|
||||
AddStep("right click panel", () =>
|
||||
{
|
||||
@@ -718,7 +678,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("click delete", () =>
|
||||
{
|
||||
var dropdownItem = Game
|
||||
.ChildrenOfType<PlayBeatmapDetailArea>().First()
|
||||
.ChildrenOfType<BeatmapLeaderboardWedge>().First()
|
||||
.ChildrenOfType<OsuContextMenu>().First()
|
||||
.ChildrenOfType<DrawableOsuMenuItem>().First(i => i.Item.Text.ToString() == "Delete");
|
||||
|
||||
@@ -744,9 +704,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game, virtualTrack: true).WaitSafely());
|
||||
|
||||
@@ -777,9 +737,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestMenuMakesMusic()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
|
||||
AddUntilStep("wait for no track", () => Game.MusicController.CurrentTrack.IsDummyDevice);
|
||||
|
||||
@@ -791,7 +751,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestPushSongSelectAndPressBackButtonImmediately()
|
||||
{
|
||||
AddStep("push song select", () => Game.ScreenStack.Push(new TestPlaySongSelect()));
|
||||
AddStep("push song select", () => Game.ScreenStack.Push(new SoloSongSelect()));
|
||||
AddStep("press back button", () => Game.ChildrenOfType<BackButton>().First().Action!.Invoke());
|
||||
|
||||
ConfirmAtMainMenu();
|
||||
@@ -800,18 +760,23 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestExitSongSelectWithClick()
|
||||
{
|
||||
TestPlaySongSelect songSelect = null;
|
||||
SoloSongSelect songSelect = null;
|
||||
ModSelectOverlay modSelect = null;
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddAssert("Overlay was shown", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddStep("Show mods overlay", () =>
|
||||
{
|
||||
modSelect = songSelect!.ChildrenOfType<ModSelectOverlay>().Single();
|
||||
modSelect.Show();
|
||||
});
|
||||
AddAssert("Overlay was shown", () => modSelect.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("Move mouse to dimmed area", () => InputManager.MoveMouseTo(new Vector2(
|
||||
songSelect.ScreenSpaceDrawQuad.TopLeft.X + 1,
|
||||
songSelect.ScreenSpaceDrawQuad.TopLeft.Y + songSelect.ScreenSpaceDrawQuad.Height / 2)));
|
||||
AddStep("Click left mouse button", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddUntilStep("Overlay was hidden", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
AddUntilStep("Overlay was hidden", () => modSelect.State.Value == Visibility.Hidden);
|
||||
exitViaBackButtonAndConfirm();
|
||||
}
|
||||
|
||||
@@ -876,10 +841,18 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
AddUntilStep("Wait for toolbar to load", () => Game.Toolbar.IsLoaded);
|
||||
|
||||
TestPlaySongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
SoloSongSelect songSelect = null;
|
||||
ModSelectOverlay modSelect = null;
|
||||
|
||||
AddStep("Show mods overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddStep("Show mods overlay", () =>
|
||||
{
|
||||
modSelect = songSelect!.ChildrenOfType<ModSelectOverlay>().Single();
|
||||
modSelect.Show();
|
||||
});
|
||||
AddAssert("Overlay was shown", () => modSelect.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("Show mods overlay", () => modSelect.Show());
|
||||
|
||||
AddStep("Change ruleset to osu!taiko", () =>
|
||||
{
|
||||
@@ -890,7 +863,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType<ToolbarRulesetSelector>().Single().Current.Value.OnlineID == 1);
|
||||
|
||||
AddAssert("Mods overlay still visible", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
|
||||
AddAssert("Mods overlay still visible", () => modSelect.State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -900,10 +873,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
TestPlaySongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
SoloSongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("Show options overlay", () => songSelect.BeatmapOptionsOverlay.Show());
|
||||
AddStep("Show options overlay", () => InputManager.Key(Key.F3));
|
||||
AddUntilStep("Options overlay visible", () => this.ChildrenOfType<FooterButtonOptions.Popover>().SingleOrDefault()?.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("Change ruleset to osu!taiko", () =>
|
||||
{
|
||||
@@ -914,7 +889,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType<ToolbarRulesetSelector>().Single().Current.Value.OnlineID == 1);
|
||||
|
||||
AddAssert("Options overlay still visible", () => songSelect.BeatmapOptionsOverlay.State.Value == Visibility.Visible);
|
||||
AddAssert("Options overlay still visible", () => this.ChildrenOfType<FooterButtonOptions.Popover>().Single().State.Value == Visibility.Visible);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -1186,7 +1161,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestExitGameFromSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => new TestPlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
exitViaEscapeAndConfirm();
|
||||
|
||||
pushEscape(); // returns to osu! logo
|
||||
@@ -1258,10 +1233,10 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("close settings sidebar", () => InputManager.Key(Key.Escape));
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
AddRepeatStep("go to solo", () => InputManager.Key(Key.P), 3);
|
||||
AddUntilStep("wait for song select", () => (songSelect = Game.ScreenStack.CurrentScreen as Screens.Select.SongSelect) != null);
|
||||
AddUntilStep("wait for beatmap sets loaded", () => songSelect.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for song select", () => (songSelect = Game.ScreenStack.CurrentScreen as Screens.SelectV2.SongSelect) != null);
|
||||
AddUntilStep("wait for beatmap sets loaded", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("switch to osu! ruleset", () =>
|
||||
{
|
||||
@@ -1271,7 +1246,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
});
|
||||
AddStep("touch beatmap wedge", () =>
|
||||
{
|
||||
var wedge = Game.ChildrenOfType<BeatmapInfoWedge>().Single();
|
||||
var wedge = Game.ChildrenOfType<BeatmapTitleWedge>().Single();
|
||||
var touch = new Touch(TouchSource.Touch2, wedge.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.BeginTouch(touch);
|
||||
InputManager.EndTouch(touch);
|
||||
@@ -1287,7 +1262,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddUntilStep("touch device mod not activated", () => Game.SelectedMods.Value, () => Has.None.InstanceOf<ModTouchDevice>());
|
||||
AddStep("touch beatmap wedge", () =>
|
||||
{
|
||||
var wedge = Game.ChildrenOfType<BeatmapInfoWedge>().Single();
|
||||
var wedge = Game.ChildrenOfType<BeatmapTitleWedge>().Single();
|
||||
var touch = new Touch(TouchSource.Touch2, wedge.ScreenSpaceDrawQuad.Centre);
|
||||
InputManager.BeginTouch(touch);
|
||||
InputManager.EndTouch(touch);
|
||||
@@ -1304,7 +1279,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
AddStep("click beatmap wedge", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(Game.ChildrenOfType<BeatmapInfoWedge>().Single());
|
||||
InputManager.MoveMouseTo(Game.ChildrenOfType<BeatmapTitleWedge>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddUntilStep("touch device mod not activated", () => Game.SelectedMods.Value, () => Has.None.InstanceOf<ModTouchDevice>());
|
||||
@@ -1315,7 +1290,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
BeatmapSetInfo beatmapSet = null;
|
||||
|
||||
PushAndConfirm(() => new TestPlaySongSelect());
|
||||
PushAndConfirm(() => new SoloSongSelect());
|
||||
AddStep("import beatmap", () => beatmapSet = BeatmapImportHelper.LoadQuickOszIntoOsu(Game).GetResultSafely());
|
||||
AddUntilStep("wait for selected", () => Game.Beatmap.Value.BeatmapSetInfo.Equals(beatmapSet));
|
||||
AddStep("select", () => InputManager.Key(Key.Enter));
|
||||
@@ -1345,9 +1320,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
[Test]
|
||||
public void TestExitSongSelectAndImmediatelyClickLogo()
|
||||
{
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -1376,9 +1351,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
BeatmapSetInfo beatmap = null;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||
@@ -1407,9 +1382,9 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||
|
||||
Screens.Select.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
Screens.SelectV2.SongSelect songSelect = null;
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
|
||||
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||
|
||||
@@ -1447,12 +1422,5 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddStep("Click back button", () => InputManager.Click(MouseButton.Left));
|
||||
ConfirmAtMainMenu();
|
||||
}
|
||||
|
||||
public partial class TestPlaySongSelect : PlaySongSelect
|
||||
{
|
||||
public ModSelectOverlay ModSelectOverlay => ModSelect;
|
||||
|
||||
public BeatmapOptionsOverlay BeatmapOptionsOverlay => BeatmapOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ using osu.Framework.Testing;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Mods;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Overlays.SkinEditor;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -26,17 +27,19 @@ 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.Skinning;
|
||||
using osu.Game.Tests.Beatmaps.IO;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using static osu.Game.Tests.Visual.Navigation.TestSceneScreenNavigation;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
public partial class TestSceneSkinEditorNavigation : OsuGameTestScene
|
||||
{
|
||||
private TestPlaySongSelect songSelect;
|
||||
private SoloSongSelect songSelect;
|
||||
private ModSelectOverlay modSelect => songSelect.ChildrenOfType<ModSelectOverlay>().First();
|
||||
|
||||
private SkinEditor skinEditor => Game.ChildrenOfType<SkinEditor>().FirstOrDefault();
|
||||
|
||||
[Test]
|
||||
@@ -331,10 +334,10 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
public void TestModOverlayClosesOnOpeningSkinEditor()
|
||||
{
|
||||
advanceToSongSelect();
|
||||
AddStep("open mod overlay", () => songSelect.ModSelectOverlay.Show());
|
||||
AddStep("open mod overlay", () => modSelect.Show());
|
||||
|
||||
openSkinEditor();
|
||||
AddUntilStep("mod overlay closed", () => songSelect.ModSelectOverlay.State.Value == Visibility.Hidden);
|
||||
AddUntilStep("mod overlay closed", () => modSelect.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -448,8 +451,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
private void advanceToSongSelect()
|
||||
{
|
||||
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||
PushAndConfirm(() => songSelect = new SoloSongSelect());
|
||||
AddUntilStep("wait for song select", () => songSelect.CarouselItemsPresented);
|
||||
}
|
||||
|
||||
private void openSkinEditor()
|
||||
|
||||
@@ -1,548 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
public partial class TestSceneBeatmapLeaderboard : OsuManualInputManagerTestScene
|
||||
{
|
||||
private readonly FailableLeaderboard leaderboard;
|
||||
|
||||
[Cached(typeof(IDialogOverlay))]
|
||||
private readonly DialogOverlay dialogOverlay;
|
||||
|
||||
private ScoreManager scoreManager = null!;
|
||||
private RulesetStore rulesetStore = null!;
|
||||
private BeatmapManager beatmapManager = null!;
|
||||
private PlaySongSelect songSelect = null!;
|
||||
|
||||
private LeaderboardManager leaderboardManager = null!;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
|
||||
dependencies.Cache(rulesetStore = new RealmRulesetStore(Realm));
|
||||
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
|
||||
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, Realm, API));
|
||||
dependencies.CacheAs<Screens.Select.SongSelect>(songSelect = new PlaySongSelect());
|
||||
dependencies.Cache(leaderboardManager = new LeaderboardManager());
|
||||
|
||||
Dependencies.Cache(Realm);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponent(songSelect);
|
||||
LoadComponent(leaderboardManager);
|
||||
}
|
||||
|
||||
public TestSceneBeatmapLeaderboard()
|
||||
{
|
||||
Add(new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
dialogOverlay = new DialogOverlay
|
||||
{
|
||||
Depth = -1
|
||||
},
|
||||
leaderboard = new FailableLeaderboard
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(550f, 450f),
|
||||
Scope = BeatmapLeaderboardScope.Global,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalScoresDisplay()
|
||||
{
|
||||
BeatmapInfo beatmapInfo = null!;
|
||||
|
||||
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local);
|
||||
|
||||
AddStep(@"Set beatmap", () =>
|
||||
{
|
||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
||||
|
||||
leaderboard.BeatmapInfo = beatmapInfo;
|
||||
});
|
||||
|
||||
clearScores();
|
||||
checkDisplayedCount(0);
|
||||
|
||||
importMoreScores(() => beatmapInfo);
|
||||
checkDisplayedCount(10);
|
||||
|
||||
importMoreScores(() => beatmapInfo);
|
||||
checkDisplayedCount(20);
|
||||
|
||||
clearScores();
|
||||
checkDisplayedCount(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalScoresDisplayWorksWhenStartingOffline()
|
||||
{
|
||||
BeatmapInfo beatmapInfo = null!;
|
||||
|
||||
AddStep("Log out", () => API.Logout());
|
||||
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local);
|
||||
|
||||
AddStep(@"Set beatmap", () =>
|
||||
{
|
||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
||||
|
||||
leaderboard.BeatmapInfo = beatmapInfo;
|
||||
});
|
||||
|
||||
clearScores();
|
||||
importMoreScores(() => beatmapInfo);
|
||||
checkDisplayedCount(10);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLocalScoresDisplayOnBeatmapEdit()
|
||||
{
|
||||
BeatmapInfo beatmapInfo = null!;
|
||||
string originalHash = string.Empty;
|
||||
|
||||
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local);
|
||||
|
||||
AddStep(@"Import beatmap", () =>
|
||||
{
|
||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
||||
|
||||
leaderboard.BeatmapInfo = beatmapInfo;
|
||||
});
|
||||
|
||||
clearScores();
|
||||
checkDisplayedCount(0);
|
||||
|
||||
AddStep(@"Perform initial save to guarantee stable hash", () =>
|
||||
{
|
||||
IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap;
|
||||
beatmapManager.Save(beatmapInfo, beatmap);
|
||||
|
||||
originalHash = beatmapInfo.Hash;
|
||||
});
|
||||
|
||||
importMoreScores(() => beatmapInfo);
|
||||
|
||||
checkDisplayedCount(10);
|
||||
checkStoredCount(10);
|
||||
|
||||
AddStep(@"Save with changes", () =>
|
||||
{
|
||||
IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap;
|
||||
beatmap.Difficulty.ApproachRate = 12;
|
||||
beatmapManager.Save(beatmapInfo, beatmap);
|
||||
});
|
||||
|
||||
AddAssert("Hash changed", () => beatmapInfo.Hash, () => Is.Not.EqualTo(originalHash));
|
||||
checkDisplayedCount(0);
|
||||
checkStoredCount(10);
|
||||
|
||||
importMoreScores(() => beatmapInfo);
|
||||
importMoreScores(() => beatmapInfo);
|
||||
checkDisplayedCount(20);
|
||||
checkStoredCount(30);
|
||||
|
||||
AddStep(@"Revert changes", () =>
|
||||
{
|
||||
IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap;
|
||||
beatmap.Difficulty.ApproachRate = 8;
|
||||
beatmapManager.Save(beatmapInfo, beatmap);
|
||||
});
|
||||
|
||||
AddAssert("Hash restored", () => beatmapInfo.Hash, () => Is.EqualTo(originalHash));
|
||||
checkDisplayedCount(10);
|
||||
checkStoredCount(30);
|
||||
|
||||
clearScores();
|
||||
checkDisplayedCount(0);
|
||||
checkStoredCount(0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGlobalScoresDisplay()
|
||||
{
|
||||
AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Global);
|
||||
AddStep(@"New Scores", () => leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo())));
|
||||
AddStep(@"New Scores with teams", () => leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo()).Select(s =>
|
||||
{
|
||||
s.User.Team = new APITeam();
|
||||
return s;
|
||||
})));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPersonalBest()
|
||||
{
|
||||
AddStep(@"Show personal best", showPersonalBest);
|
||||
AddStep("null personal best position", showPersonalBestWithNullPosition);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceholderStates()
|
||||
{
|
||||
AddStep("ensure no scores displayed", () => leaderboard.SetScores(null));
|
||||
|
||||
AddStep(@"Network failure", () => leaderboard.SetErrorState(LeaderboardState.NetworkFailure));
|
||||
AddStep(@"No team", () => leaderboard.SetErrorState(LeaderboardState.NoTeam));
|
||||
AddStep(@"No supporter", () => leaderboard.SetErrorState(LeaderboardState.NotSupporter));
|
||||
AddStep(@"Not logged in", () => leaderboard.SetErrorState(LeaderboardState.NotLoggedIn));
|
||||
AddStep(@"Ruleset unavailable", () => leaderboard.SetErrorState(LeaderboardState.RulesetUnavailable));
|
||||
AddStep(@"Beatmap unavailable", () => leaderboard.SetErrorState(LeaderboardState.BeatmapUnavailable));
|
||||
AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUseTheseModsDoesNotCopySystemMods()
|
||||
{
|
||||
AddStep(@"set scores", () => leaderboard.SetScores(leaderboard.Scores, new ScoreInfo
|
||||
{
|
||||
Position = 999,
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
Mods = new Mod[] { new OsuModHidden(), new ModScoreV2(), },
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6602580,
|
||||
Username = @"waaiiru",
|
||||
CountryCode = CountryCode.ES,
|
||||
}
|
||||
}));
|
||||
AddUntilStep("wait for scores", () => this.ChildrenOfType<LeaderboardScore>().Count(), () => Is.GreaterThan(0));
|
||||
AddStep("right click panel", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<LeaderboardScore>().Single());
|
||||
InputManager.Click(MouseButton.Right);
|
||||
});
|
||||
AddStep("click use these mods", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(this.ChildrenOfType<DrawableOsuMenuItem>().Single());
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
AddAssert("song select received HD", () => songSelect.Mods.Value.Any(m => m is OsuModHidden));
|
||||
AddAssert("song select did not receive SV2", () => !songSelect.Mods.Value.Any(m => m is ModScoreV2));
|
||||
}
|
||||
|
||||
private void showPersonalBestWithNullPosition()
|
||||
{
|
||||
leaderboard.SetScores(leaderboard.Scores, new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock() },
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6602580,
|
||||
Username = @"waaiiru",
|
||||
CountryCode = CountryCode.ES,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private void showPersonalBest()
|
||||
{
|
||||
leaderboard.SetScores(leaderboard.Scores, new ScoreInfo
|
||||
{
|
||||
Position = 999,
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6602580,
|
||||
Username = @"waaiiru",
|
||||
CountryCode = CountryCode.ES,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void importMoreScores(Func<BeatmapInfo> beatmapInfo)
|
||||
{
|
||||
AddStep(@"Import new scores", () =>
|
||||
{
|
||||
foreach (var score in GenerateSampleScores(beatmapInfo()))
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
}
|
||||
|
||||
private void clearScores()
|
||||
{
|
||||
AddStep("Clear all scores", () => scoreManager.Delete());
|
||||
}
|
||||
|
||||
private void checkDisplayedCount(int expected) =>
|
||||
AddUntilStep($"{expected} scores displayed", () => leaderboard.ChildrenOfType<LeaderboardScore>().Count(), () => Is.EqualTo(expected));
|
||||
|
||||
private void checkStoredCount(int expected) =>
|
||||
AddUntilStep($"Total scores stored is {expected}", () => Realm.Run(r => r.All<ScoreInfo>().Count(s => !s.DeletePending)), () => Is.EqualTo(expected));
|
||||
|
||||
public static ScoreInfo[] GenerateSampleScores(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now,
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight
|
||||
{
|
||||
FollowDelay = { Value = 200 },
|
||||
SizeMultiplier = { Value = 5 },
|
||||
},
|
||||
new OsuModDifficultyAdjust
|
||||
{
|
||||
CircleSize = { Value = 11 },
|
||||
ApproachRate = { Value = 10 },
|
||||
OverallDifficulty = { Value = 10 },
|
||||
DrainRate = { Value = 10 },
|
||||
ExtendedLimits = { Value = true }
|
||||
}
|
||||
},
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6602580,
|
||||
Username = @"waaiiru",
|
||||
CountryCode = CountryCode.ES,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.X,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddSeconds(-30),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 4608074,
|
||||
Username = @"Skycries",
|
||||
CountryCode = CountryCode.BR,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.SH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddSeconds(-70),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 1014222,
|
||||
Username = @"eLy",
|
||||
CountryCode = CountryCode.JP,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.S,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddMinutes(-40),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 1541390,
|
||||
Username = @"Toukai",
|
||||
CountryCode = CountryCode.CA,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.A,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-2),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2243452,
|
||||
Username = @"Satoruu",
|
||||
CountryCode = CountryCode.VE,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.B,
|
||||
Accuracy = 0.9826,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-25),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2705430,
|
||||
Username = @"Mooha",
|
||||
CountryCode = CountryCode.FR,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.C,
|
||||
Accuracy = 0.9654,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-50),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 7151382,
|
||||
Username = @"Mayuri Hana",
|
||||
CountryCode = CountryCode.TH,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.6025,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-72),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2051389,
|
||||
Username = @"FunOrange",
|
||||
CountryCode = CountryCode.CA,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.5140,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddMonths(-10),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6169483,
|
||||
Username = @"-Hebel-",
|
||||
CountryCode = CountryCode.MX,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.4222,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddYears(-2),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6702666,
|
||||
Username = @"prhtnsm",
|
||||
CountryCode = CountryCode.DE,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private partial class FailableLeaderboard : BeatmapLeaderboard
|
||||
{
|
||||
public new void SetErrorState(LeaderboardState state) => base.SetErrorState(state);
|
||||
public new void SetScores(IEnumerable<ScoreInfo>? scores, ScoreInfo? userScore = null) => base.SetScores(scores, userScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Utils;
|
||||
@@ -248,7 +249,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
||||
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded);
|
||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is SoloSongSelect select && select.CarouselItemsPresented);
|
||||
AddUntilStep("recommended beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID, () => Is.EqualTo(getImport().Beatmaps[expectedDiff - 1].OnlineID));
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -263,8 +263,8 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
|
||||
var results = await runGrouping(GroupMode.Difficulty, beatmapSets);
|
||||
assertGroup(results, 0, "Below 1 Star", new[] { beatmapBelow1 }, ref total);
|
||||
assertGroup(results, 1, "1 Star", new[] { beatmapAbove1 }, ref total);
|
||||
assertGroup(results, 2, "2 Stars", new[] { beatmapAlmost2, beatmap2, beatmapAbove2 }, ref total);
|
||||
assertGroup(results, 1, "1 Star", new[] { beatmapAbove1, beatmapAlmost2 }, ref total);
|
||||
assertGroup(results, 2, "2 Stars", new[] { beatmap2, beatmapAbove2 }, ref total);
|
||||
assertGroup(results, 3, "7 Stars", new[] { beatmap7 }, ref total);
|
||||
assertTotal(results, total);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Select.Leaderboards;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual.SongSelect;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -118,8 +117,8 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
{
|
||||
setScope(BeatmapLeaderboardScope.Global);
|
||||
|
||||
AddStep(@"New Scores", () => leaderboard.SetScores(TestSceneBeatmapLeaderboard.GenerateSampleScores(new BeatmapInfo())));
|
||||
AddStep(@"New Scores with teams", () => leaderboard.SetScores(TestSceneBeatmapLeaderboard.GenerateSampleScores(new BeatmapInfo()).Select(s =>
|
||||
AddStep(@"New Scores", () => leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo())));
|
||||
AddStep(@"New Scores with teams", () => leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo()).Select(s =>
|
||||
{
|
||||
s.User.Team = new APITeam();
|
||||
return s;
|
||||
@@ -150,7 +149,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
[Test]
|
||||
public void TestUseTheseModsDoesNotCopySystemMods()
|
||||
{
|
||||
AddStep(@"set scores", () => leaderboard.SetScores(TestSceneBeatmapLeaderboard.GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
AddStep(@"set scores", () => leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
{
|
||||
OnlineID = 1337,
|
||||
Position = 999,
|
||||
@@ -297,7 +296,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
|
||||
private void showPersonalBestWithNullPosition()
|
||||
{
|
||||
leaderboard.SetScores(TestSceneBeatmapLeaderboard.GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
{
|
||||
OnlineID = 1337,
|
||||
Rank = ScoreRank.XH,
|
||||
@@ -318,7 +317,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
|
||||
private void showPersonalBest()
|
||||
{
|
||||
leaderboard.SetScores(TestSceneBeatmapLeaderboard.GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
leaderboard.SetScores(GenerateSampleScores(new BeatmapInfo()), new ScoreInfo
|
||||
{
|
||||
OnlineID = 1337,
|
||||
Position = 999,
|
||||
@@ -347,7 +346,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
{
|
||||
AddStep(@"Import new scores", () =>
|
||||
{
|
||||
foreach (var score in TestSceneBeatmapLeaderboard.GenerateSampleScores(beatmapInfo()))
|
||||
foreach (var score in GenerateSampleScores(beatmapInfo()))
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
}
|
||||
@@ -368,5 +367,216 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
public new void SetState(LeaderboardState state) => base.SetState(state);
|
||||
public new void SetScores(IEnumerable<ScoreInfo> scores, ScoreInfo? userScore = null, int? totalCount = null) => base.SetScores(scores, userScore, totalCount);
|
||||
}
|
||||
|
||||
public static ScoreInfo[] GenerateSampleScores(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.XH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now,
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new OsuModHidden(),
|
||||
new OsuModFlashlight
|
||||
{
|
||||
FollowDelay = { Value = 200 },
|
||||
SizeMultiplier = { Value = 5 },
|
||||
},
|
||||
new OsuModDifficultyAdjust
|
||||
{
|
||||
CircleSize = { Value = 11 },
|
||||
ApproachRate = { Value = 10 },
|
||||
OverallDifficulty = { Value = 10 },
|
||||
DrainRate = { Value = 10 },
|
||||
ExtendedLimits = { Value = true }
|
||||
}
|
||||
},
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6602580,
|
||||
Username = @"waaiiru",
|
||||
CountryCode = CountryCode.ES,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.X,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddSeconds(-30),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 4608074,
|
||||
Username = @"Skycries",
|
||||
CountryCode = CountryCode.BR,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.SH,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddSeconds(-70),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 1014222,
|
||||
Username = @"eLy",
|
||||
CountryCode = CountryCode.JP,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.S,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddMinutes(-40),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 1541390,
|
||||
Username = @"Toukai",
|
||||
CountryCode = CountryCode.CA,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.A,
|
||||
Accuracy = 1,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-2),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2243452,
|
||||
Username = @"Satoruu",
|
||||
CountryCode = CountryCode.VE,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.B,
|
||||
Accuracy = 0.9826,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-25),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2705430,
|
||||
Username = @"Mooha",
|
||||
CountryCode = CountryCode.FR,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.C,
|
||||
Accuracy = 0.9654,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-50),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 7151382,
|
||||
Username = @"Mayuri Hana",
|
||||
CountryCode = CountryCode.TH,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.6025,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddHours(-72),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 2051389,
|
||||
Username = @"FunOrange",
|
||||
CountryCode = CountryCode.CA,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.5140,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddMonths(-10),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6169483,
|
||||
Username = @"-Hebel-",
|
||||
CountryCode = CountryCode.MX,
|
||||
},
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.4222,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
Date = DateTime.Now.AddYears(-2),
|
||||
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
|
||||
BeatmapInfo = beatmapInfo,
|
||||
BeatmapHash = beatmapInfo.Hash,
|
||||
Ruleset = new OsuRuleset().RulesetInfo,
|
||||
|
||||
User = new APIUser
|
||||
{
|
||||
Id = 6702666,
|
||||
Username = @"prhtnsm",
|
||||
CountryCode = CountryCode.DE,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace osu.Game.Beatmaps.Formats
|
||||
public abstract class LegacyDecoder<T> : Decoder<T>
|
||||
where T : new()
|
||||
{
|
||||
// If this is updated, a new release of `osu-server-beatmap-submission` is required with updated packages.
|
||||
// See usage at https://github.com/ppy/osu-server-beatmap-submission/blob/master/osu.Server.BeatmapSubmission/Services/BeatmapPackageParser.cs#L96-L97.
|
||||
public const int LATEST_VERSION = 14;
|
||||
|
||||
public const int MAX_COMBO_COLOUR_COUNT = 8;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Configuration
|
||||
[LocalisableDescription(typeof(UserInterfaceStrings), nameof(UserInterfaceStrings.BeatmapWithStoryboard))]
|
||||
BeatmapWithStoryboard,
|
||||
|
||||
[Description("Use 'Resource\\Webm\\*.webm' file from local folders")]
|
||||
[Description("'EzResource/Webm/*.webm' from local folders")]
|
||||
WebmSource,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Mods.Input;
|
||||
using osu.Game.Overlays.Settings.Sections.Gameplay;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osu.Game.Screens.LAsEzExtensions;
|
||||
@@ -51,7 +52,6 @@ namespace osu.Game.Configuration
|
||||
|
||||
SetDefault(OsuSetting.SongSelectGroupMode, GroupMode.None);
|
||||
SetDefault(OsuSetting.SongSelectSortingMode, SortMode.Title);
|
||||
SetDefault(OsuSetting.SelectEzMode, EzSelectMode.All);
|
||||
|
||||
SetDefault(OsuSetting.RandomSelectAlgorithm, RandomSelectAlgorithm.RandomPermutation);
|
||||
SetDefault(OsuSetting.ModSelectHotkeyStyle, ModSelectHotkeyStyle.Sequential);
|
||||
@@ -157,10 +157,19 @@ namespace osu.Game.Configuration
|
||||
SetDefault(OsuSetting.FloatingComments, false);
|
||||
|
||||
SetDefault(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised);
|
||||
|
||||
//新增自定义
|
||||
SetDefault(OsuSetting.SelectEzMode, EzSelectMode.All);
|
||||
SetDefault(OsuSetting.HitMode, MUGHitMode.EZ2AC);
|
||||
SetDefault(OsuSetting.AccuracyCutoffS, 0.95, 0.95, 1, 0.005);
|
||||
SetDefault(OsuSetting.AccuracyCutoffA, 0.9, 0.9, 1, 0.005);
|
||||
|
||||
// SetDefault(OsuSetting.ScrollBaseSpeed, 500, 100, 1000, 1.0);
|
||||
// SetDefault(OsuSetting.ScrollTimePerSpeed, 5, 1.0, 40, 1.0);
|
||||
// SetDefault(OsuSetting.ScrollStyle, EzManiaScrollingStyle.ScrollTimeStyleFixed);
|
||||
// SetDefault(OsuSetting.ScrollPerKeyMode, false);
|
||||
// SetDefault(OsuSetting.PerspectiveAngle, 90.0f, 30.0f, 90.0f);
|
||||
|
||||
SetDefault(OsuSetting.IncreaseFirstObjectVisibility, true);
|
||||
SetDefault(OsuSetting.GameplayDisableWinKey, true);
|
||||
|
||||
@@ -175,8 +184,6 @@ namespace osu.Game.Configuration
|
||||
SetDefault(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
|
||||
SetDefault(OsuSetting.ScreenshotCaptureMenuCursor, false);
|
||||
|
||||
SetDefault(OsuSetting.SongSelectRightMouseScroll, true);
|
||||
|
||||
SetDefault(OsuSetting.Scaling, ScalingMode.Off);
|
||||
SetDefault(OsuSetting.ScalingGameMode, ScalingGameMode.Mania);
|
||||
SetDefault(OsuSetting.SafeAreaConsiderations, true);
|
||||
@@ -413,19 +420,27 @@ namespace osu.Game.Configuration
|
||||
Skin,
|
||||
ScreenshotFormat,
|
||||
ScreenshotCaptureMenuCursor,
|
||||
SongSelectRightMouseScroll,
|
||||
BeatmapSkins,
|
||||
BeatmapColours,
|
||||
BeatmapHitsounds,
|
||||
IncreaseFirstObjectVisibility,
|
||||
ScoreDisplayMode,
|
||||
SelectEzMode,
|
||||
SelectManiaRulesetSubset,
|
||||
ScalingGameMode,
|
||||
|
||||
HitMode,
|
||||
//自定义
|
||||
SelectEzMode,
|
||||
ScalingGameMode,
|
||||
AccuracyCutoffS,
|
||||
AccuracyCutoffA,
|
||||
HitMode,
|
||||
// //mania用自定义
|
||||
// SelectManiaRulesetSubset,
|
||||
// ScrollBaseSpeed,
|
||||
// ScrollTimePerSpeed,
|
||||
// ScrollStyle,
|
||||
//
|
||||
// PerspectiveAngle,
|
||||
// ScrollPerKeyMode,
|
||||
|
||||
ExternalLinkWarning,
|
||||
PreferNoVideo,
|
||||
Scaling,
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Extensions;
|
||||
@@ -85,6 +86,7 @@ namespace osu.Game.Database
|
||||
/// </summary>
|
||||
public void AddFile(TModel item, Stream contents, string filename, Realm realm)
|
||||
{
|
||||
filename = filename.ToStandardisedPath();
|
||||
var existing = item.GetFile(filename);
|
||||
|
||||
if (existing != null)
|
||||
|
||||
@@ -102,6 +102,8 @@ namespace osu.Game.Database
|
||||
/// </summary>
|
||||
private const int schema_version = 49;
|
||||
|
||||
public static int SchemaVersion => schema_version;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
|
||||
/// </summary>
|
||||
@@ -202,10 +204,10 @@ namespace osu.Game.Database
|
||||
if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal))
|
||||
Filename += realm_extension;
|
||||
|
||||
#if DEBUG
|
||||
// #if DEBUG
|
||||
if (!DebugUtils.IsNUnitRunning)
|
||||
applyFilenameSchemaSuffix(ref Filename);
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
// `prepareFirstRealmAccess()` triggers the first `getRealmInstance` call, which will implicitly run realm migrations and bring the schema up-to-date.
|
||||
using (var realm = prepareFirstRealmAccess())
|
||||
@@ -543,6 +545,44 @@ namespace osu.Game.Database
|
||||
return writeTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write changes to realm asynchronously, guaranteeing order of execution.
|
||||
/// </summary>
|
||||
/// <param name="action">The work to run.</param>
|
||||
public Task<T> WriteAsync<T>(Func<Realm, T> action)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(isDisposed, this);
|
||||
|
||||
// Required to ensure the write is tracked and accounted for before disposal.
|
||||
// Can potentially be avoided if we have a need to do so in the future.
|
||||
if (!ThreadSafety.IsUpdateThread)
|
||||
throw new InvalidOperationException(@$"{nameof(WriteAsync)} must be called from the update thread.");
|
||||
|
||||
// CountdownEvent will fail if already at zero.
|
||||
if (!pendingAsyncWrites.TryAddCount())
|
||||
pendingAsyncWrites.Reset(1);
|
||||
|
||||
// Regardless of calling Realm.GetInstance or Realm.GetInstanceAsync, there is a blocking overhead on retrieval.
|
||||
// Adding a forced Task.Run resolves this.
|
||||
var writeTask = Task.Run(async () =>
|
||||
{
|
||||
T result;
|
||||
total_writes_async.Value++;
|
||||
|
||||
// Not attempting to use Realm.GetInstanceAsync as there's seemingly no benefit to us (for now) and it adds complexity due to locking
|
||||
// concerns in getRealmInstance(). On a quick check, it looks to be more suited to cases where realm is connecting to an online sync
|
||||
// server, which we don't use. May want to report upstream or revisit in the future.
|
||||
using (var realm = getRealmInstance())
|
||||
// ReSharper disable once AccessToDisposedClosure (WriteAsync should be marked as [InstantHandle]).
|
||||
result = await realm.WriteAsync(() => action(realm)).ConfigureAwait(false);
|
||||
|
||||
pendingAsyncWrites.Signal();
|
||||
return result;
|
||||
});
|
||||
|
||||
return writeTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to a realm collection and begin watching for asynchronous changes.
|
||||
/// </summary>
|
||||
|
||||
@@ -14,6 +14,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Database
|
||||
@@ -177,6 +178,7 @@ namespace osu.Game.Database
|
||||
c.CreateMap<RealmUser, RealmUser>();
|
||||
c.CreateMap<RealmFile, RealmFile>();
|
||||
c.CreateMap<RealmNamedFileUsage, RealmNamedFileUsage>();
|
||||
c.CreateMap<SkinInfo, SkinInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace osu.Game.Graphics.Carousel
|
||||
/// <summary>
|
||||
/// Retrieve a list of all <see cref="CarouselItem"/>s currently displayed.
|
||||
/// </summary>
|
||||
protected IReadOnlyCollection<CarouselItem>? GetCarouselItems() => carouselItems;
|
||||
public IReadOnlyCollection<CarouselItem>? GetCarouselItems() => carouselItems;
|
||||
|
||||
private List<CarouselItem>? carouselItems;
|
||||
|
||||
@@ -670,7 +670,7 @@ namespace osu.Game.Graphics.Carousel
|
||||
|
||||
private void loadSamples(AudioManager audio)
|
||||
{
|
||||
sampleKeyboardTraversal = audio.Samples.Get(@"UI/button-hover");
|
||||
sampleKeyboardTraversal = audio.Samples.Get(@"SongSelect/select-difficulty");
|
||||
}
|
||||
|
||||
private void playTraversalSound()
|
||||
@@ -1028,7 +1028,7 @@ namespace osu.Game.Graphics.Carousel
|
||||
/// Implementation of scroll container which handles very large vertical lists by internally using <c>double</c> precision
|
||||
/// for pre-display Y values.
|
||||
/// </summary>
|
||||
protected partial class CarouselScrollContainer : UserTrackingScrollContainer, IKeyBindingHandler<GlobalAction>
|
||||
public partial class CarouselScrollContainer : UserTrackingScrollContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public readonly Container Panels;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -41,24 +40,20 @@ namespace osu.Game.Graphics.Containers
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = contractedWidth;
|
||||
|
||||
FillFlow = new FillFlowContainer
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = CreateScrollContainer().With(s =>
|
||||
{
|
||||
s.RelativeSizeAxes = Axes.Both;
|
||||
s.ScrollbarVisible = false;
|
||||
}).WithChild(FillFlow);
|
||||
}).WithChild(
|
||||
FillFlow = new FillFlowContainer
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected virtual OsuScrollContainer CreateScrollContainer() => new OsuScrollContainer();
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
Content.ScaleTo(0.9f, 2000, Easing.OutQuint);
|
||||
return base.OnMouseDown(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseUpEvent e)
|
||||
|
||||
@@ -154,6 +154,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString TimelineShowTimingChanges => new TranslatableString(getKey(@"timeline_show_timing_changes"), @"Show timing changes");
|
||||
|
||||
/// <summary>
|
||||
/// "Finish editing and import changes"
|
||||
/// </summary>
|
||||
public static LocalisableString FinishEditingExternally => new TranslatableString(getKey(@"Finish editing and import changes"), @"Finish editing and import changes");
|
||||
|
||||
/// <summary>
|
||||
/// "Show breaks"
|
||||
/// </summary>
|
||||
|
||||
@@ -149,6 +149,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString DragAndDropImageInSkinEditor => new TranslatableString(getKey(@"drag_and_drop_image_in_skin_editor"), @"Drag and drop any image into the skin editor to load it in quickly!");
|
||||
|
||||
/// <summary>
|
||||
/// "Try holding your right mouse button near the beatmap carousel to quickly scroll to an absolute position!"
|
||||
/// </summary>
|
||||
public static LocalisableString RightMouseAbsoluteScroll => new TranslatableString(getKey(@"right_mouse_absolute_scroll"), @"Try holding your right mouse button near the beatmap carousel to quickly scroll to an absolute position!");
|
||||
|
||||
/// <summary>
|
||||
/// "a tip for you:"
|
||||
/// </summary>
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString NoPPForUnrankedMods => new TranslatableString(getKey(@"no_pp_for_unranked_mods"), @"Performance points are not granted for this score because of unranked mods.");
|
||||
|
||||
/// <summary>
|
||||
/// "Performance points are not granted for failed scores."
|
||||
/// </summary>
|
||||
public static LocalisableString NoPPForFailedScores => new TranslatableString(getKey(@"no_pp_for_failed_scores"), @"Performance points are not granted for failed scores.");
|
||||
|
||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,6 @@ namespace osu.Game.Localisation.SkinComponents
|
||||
/// </summary>
|
||||
public static LocalisableString Attribute => new TranslatableString(getKey(@"attribute"), @"Attribute");
|
||||
|
||||
/// <summary>
|
||||
/// "The attribute to be displayed."
|
||||
/// </summary>
|
||||
public static LocalisableString AttributeDescription => new TranslatableString(getKey(@"attribute_description"), @"The attribute to be displayed.");
|
||||
|
||||
/// <summary>
|
||||
/// "Template"
|
||||
/// </summary>
|
||||
|
||||
@@ -14,31 +14,16 @@ namespace osu.Game.Localisation.SkinComponents
|
||||
/// </summary>
|
||||
public static LocalisableString SpriteName => new TranslatableString(getKey(@"sprite_name"), @"Sprite name");
|
||||
|
||||
/// <summary>
|
||||
/// "The filename of the sprite"
|
||||
/// </summary>
|
||||
public static LocalisableString SpriteNameDescription => new TranslatableString(getKey(@"sprite_name_description"), @"The filename of the sprite");
|
||||
|
||||
/// <summary>
|
||||
/// "Font"
|
||||
/// </summary>
|
||||
public static LocalisableString Font => new TranslatableString(getKey(@"font"), @"Font");
|
||||
|
||||
/// <summary>
|
||||
/// "The font to use."
|
||||
/// </summary>
|
||||
public static LocalisableString FontDescription => new TranslatableString(getKey(@"font_description"), @"The font to use.");
|
||||
|
||||
/// <summary>
|
||||
/// "Text"
|
||||
/// </summary>
|
||||
public static LocalisableString TextElementText => new TranslatableString(getKey(@"text_element_text"), @"Text");
|
||||
|
||||
/// <summary>
|
||||
/// "The text to be displayed."
|
||||
/// </summary>
|
||||
public static LocalisableString TextElementTextDescription => new TranslatableString(getKey(@"text_element_text_description"), @"The text to be displayed.");
|
||||
|
||||
/// <summary>
|
||||
/// "Corner radius"
|
||||
/// </summary>
|
||||
@@ -54,31 +39,16 @@ namespace osu.Game.Localisation.SkinComponents
|
||||
/// </summary>
|
||||
public static LocalisableString ShowLabel => new TranslatableString(getKey(@"show_label"), @"Show label");
|
||||
|
||||
/// <summary>
|
||||
/// "Whether the component's label should be shown."
|
||||
/// </summary>
|
||||
public static LocalisableString ShowLabelDescription => new TranslatableString(getKey(@"show_label_description"), @"Whether the component's label should be shown.");
|
||||
|
||||
/// <summary>
|
||||
/// "Colour"
|
||||
/// </summary>
|
||||
public static LocalisableString Colour => new TranslatableString(getKey(@"colour"), @"Colour");
|
||||
|
||||
/// <summary>
|
||||
/// "The colour of the component."
|
||||
/// </summary>
|
||||
public static LocalisableString ColourDescription => new TranslatableString(getKey(@"colour_description"), @"The colour of the component.");
|
||||
|
||||
/// <summary>
|
||||
/// "Text colour"
|
||||
/// </summary>
|
||||
public static LocalisableString TextColour => new TranslatableString(getKey(@"text_colour"), @"Text colour");
|
||||
|
||||
/// <summary>
|
||||
/// "The colour of the text."
|
||||
/// </summary>
|
||||
public static LocalisableString TextColourDescription => new TranslatableString(getKey(@"text_colour_description"), @"The colour of the text.");
|
||||
|
||||
/// <summary>
|
||||
/// "Text weight"
|
||||
/// </summary>
|
||||
|
||||
@@ -227,6 +227,8 @@ namespace osu.Game
|
||||
|
||||
private Bindable<string> configSkin;
|
||||
|
||||
private RealmDetachedBeatmapStore detachedBeatmapStore;
|
||||
|
||||
private readonly string[] args;
|
||||
|
||||
private readonly List<OsuFocusedOverlayContainer> focusedOverlays = new List<OsuFocusedOverlayContainer>();
|
||||
@@ -312,6 +314,8 @@ namespace osu.Game
|
||||
foreach (var overlay in focusedOverlays)
|
||||
overlay.Hide();
|
||||
|
||||
ScreenFooter.ActiveOverlay?.Hide();
|
||||
|
||||
if (hideToolbar) Toolbar.Hide();
|
||||
}
|
||||
|
||||
@@ -1000,6 +1004,10 @@ namespace osu.Game
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
// Without this, tests may deadlock due to cancellation token not becoming cancelled before disposal.
|
||||
// To reproduce, run `TestSceneButtonSystemNavigation` ensuring `TestConstructor` runs before `TestFastShortcutKeys`.
|
||||
detachedBeatmapStore?.Dispose();
|
||||
|
||||
base.Dispose(isDisposing);
|
||||
SentryLogger.Dispose();
|
||||
}
|
||||
@@ -1243,7 +1251,7 @@ namespace osu.Game
|
||||
loadComponentSingleFile(new MedalOverlay(), topMostOverlayContent.Add);
|
||||
|
||||
loadComponentSingleFile(new BackgroundDataStoreProcessor(), Add);
|
||||
loadComponentSingleFile<BeatmapStore>(new RealmDetachedBeatmapStore(), Add, true);
|
||||
loadComponentSingleFile<BeatmapStore>(detachedBeatmapStore = new RealmDetachedBeatmapStore(), Add, true);
|
||||
|
||||
Add(externalLinkOpener = new ExternalLinkOpener());
|
||||
Add(new MusicKeyBindingHandler());
|
||||
|
||||
@@ -78,9 +78,9 @@ namespace osu.Game
|
||||
public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncProvider
|
||||
{
|
||||
#if DEBUG
|
||||
public const string GAME_NAME = "osu! (development)";
|
||||
public const string GAME_NAME = "ez2osu! (development)";
|
||||
#else
|
||||
public const string GAME_NAME = "osu!";
|
||||
public const string GAME_NAME = "ez2osu!";
|
||||
#endif
|
||||
|
||||
public const string OSU_PROTOCOL = "osu://";
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
|
||||
public readonly Bindable<APIBeatmap?> Beatmap = new Bindable<APIBeatmap?>();
|
||||
private APIBeatmapSet? beatmapSet;
|
||||
private readonly Box background;
|
||||
|
||||
public APIBeatmapSet? BeatmapSet
|
||||
{
|
||||
@@ -68,12 +69,29 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Difficulties = new DifficultiesContainer
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Left = -(tile_icon_padding + tile_spacing / 2), Bottom = 10 },
|
||||
OnLostHover = () => showBeatmap(Beatmap.Value, withStarRating: false),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = 10,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.5f
|
||||
}
|
||||
},
|
||||
Difficulties = new DifficultiesContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
OnLostHover = () => showBeatmap(Beatmap.Value, withStarRating: false),
|
||||
},
|
||||
}
|
||||
},
|
||||
infoContainer = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 11))
|
||||
{
|
||||
@@ -108,9 +126,10 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
updateDisplay();
|
||||
background.Colour = colourProvider.Background3;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -123,6 +142,12 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Beatmap.TriggerChange();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
Difficulties.MaximumSize = new Vector2(DrawWidth, float.MaxValue);
|
||||
}
|
||||
|
||||
private void updateDisplay()
|
||||
{
|
||||
Difficulties.Clear();
|
||||
@@ -240,8 +265,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
public partial class DifficultySelectorButton : OsuClickableContainer, IStateful<DifficultySelectorState>
|
||||
{
|
||||
private const float transition_duration = 100;
|
||||
private const float size = 54;
|
||||
private const float background_size = size - 2;
|
||||
private const float size = 40;
|
||||
private const float background_size = size - 1;
|
||||
|
||||
private readonly Container background;
|
||||
private readonly Box backgroundBox;
|
||||
@@ -276,7 +301,6 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
Beatmap = beatmapInfo;
|
||||
Size = new Vector2(size);
|
||||
Margin = new MarginPadding { Horizontal = tile_spacing / 2 };
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@@ -284,7 +308,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
{
|
||||
Size = new Vector2(background_size),
|
||||
Masking = true,
|
||||
CornerRadius = 4,
|
||||
CornerRadius = 10,
|
||||
BorderThickness = 3,
|
||||
Child = backgroundBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@@ -338,6 +363,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
backgroundBox.Colour = colourProvider.Background6;
|
||||
background.BorderColour = colourProvider.Light2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Footer;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
@@ -101,11 +101,14 @@ namespace osu.Game.Overlays.FirstRunSetup
|
||||
}
|
||||
}
|
||||
|
||||
private partial class NestedSongSelect : PlaySongSelect
|
||||
private partial class NestedSongSelect : SoloSongSelect
|
||||
{
|
||||
protected override bool ControlGlobalMusic => false;
|
||||
|
||||
public override bool? ApplyModTrackAdjustments => false;
|
||||
|
||||
public NestedSongSelect()
|
||||
{
|
||||
ControlGlobalMusic = false;
|
||||
}
|
||||
}
|
||||
|
||||
private partial class UIScaleSlider : RoundedSliderBar<float>
|
||||
@@ -145,16 +148,17 @@ namespace osu.Game.Overlays.FirstRunSetup
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) =>
|
||||
new DependencyContainer(new DependencyIsolationContainer(base.CreateChildDependencies(parent)));
|
||||
|
||||
private ScreenFooter footer;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, TextureStore textures, RulesetStore rulesets)
|
||||
{
|
||||
Beatmap.Value = new DummyWorkingBeatmap(audio, textures);
|
||||
Beatmap.Default = Beatmap.Value = new DummyWorkingBeatmap(audio, textures);
|
||||
|
||||
Ruleset.Value = rulesets.AvailableRulesets.First();
|
||||
|
||||
OsuScreenStack stack;
|
||||
OsuLogo logo;
|
||||
ScreenFooter footer;
|
||||
|
||||
Padding = new MarginPadding(5);
|
||||
|
||||
@@ -192,6 +196,13 @@ namespace osu.Game.Overlays.FirstRunSetup
|
||||
// intentionally load synchronously so it is included in the initial load of the first run screen.
|
||||
stack.PushSynchronously(screen);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
footer.Show();
|
||||
}
|
||||
}
|
||||
|
||||
private class DependencyIsolationContainer : IReadOnlyDependencyContainer
|
||||
|
||||
@@ -448,7 +448,7 @@ namespace osu.Game.Overlays.Mods
|
||||
}
|
||||
else
|
||||
{
|
||||
modState.Mod.ResetHitWindows();
|
||||
modState.Mod.ResetSettingsToDefaults();
|
||||
modState.Active.Value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +60,12 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum MUGHitMode
|
||||
{
|
||||
Lazer,
|
||||
EZ2AC,
|
||||
IIDX,
|
||||
Melody,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -113,15 +112,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
||||
AutoSizeAxes = Axes.Y,
|
||||
}.With(t =>
|
||||
{
|
||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows || RuntimeInfo.OS == RuntimeInfo.Platform.Linux)
|
||||
{
|
||||
t.NewLine();
|
||||
var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedString(TabletSettingsStrings.NoTabletDetectedDescription(
|
||||
RuntimeInfo.OS == RuntimeInfo.Platform.Windows
|
||||
? @"https://opentabletdriver.net/Wiki/FAQ/Windows"
|
||||
: @"https://opentabletdriver.net/Wiki/FAQ/Linux")));
|
||||
t.AddLinks(formattedSource.Text, formattedSource.Links);
|
||||
}
|
||||
t.NewLine();
|
||||
|
||||
const string url = @"https://opentabletdriver.net/Wiki/FAQ/General";
|
||||
var formattedSource = MessageFormatter.FormatText(localisation.GetLocalisedString(TabletSettingsStrings.NoTabletDetectedDescription(url)));
|
||||
|
||||
t.AddLinks(formattedSource.Text, formattedSource.Links);
|
||||
}),
|
||||
}
|
||||
},
|
||||
|
||||
@@ -178,9 +178,12 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
base.LoadComplete();
|
||||
|
||||
currentSkin = skins.CurrentSkin.GetBoundCopy();
|
||||
currentSkin.BindValueChanged(skin => Enabled.Value = skin.NewValue.SkinInfo.PerformRead(s => !s.Protected), true);
|
||||
currentSkin.BindValueChanged(_ => updateState());
|
||||
currentSkin.BindDisabledChanged(_ => updateState(), true);
|
||||
}
|
||||
|
||||
private void updateState() => Enabled.Value = !currentSkin.Disabled && currentSkin.Value.SkinInfo.PerformRead(s => !s.Protected);
|
||||
|
||||
public Popover GetPopover()
|
||||
{
|
||||
return new RenameSkinPopover();
|
||||
@@ -206,9 +209,12 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
base.LoadComplete();
|
||||
|
||||
currentSkin = skins.CurrentSkin.GetBoundCopy();
|
||||
currentSkin.BindValueChanged(skin => Enabled.Value = skin.NewValue.SkinInfo.PerformRead(s => !s.Protected), true);
|
||||
currentSkin.BindValueChanged(_ => updateState());
|
||||
currentSkin.BindDisabledChanged(_ => updateState(), true);
|
||||
}
|
||||
|
||||
private void updateState() => Enabled.Value = !currentSkin.Disabled && currentSkin.Value.SkinInfo.PerformRead(s => !s.Protected);
|
||||
|
||||
private void export()
|
||||
{
|
||||
try
|
||||
@@ -244,9 +250,12 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
base.LoadComplete();
|
||||
|
||||
currentSkin = skins.CurrentSkin.GetBoundCopy();
|
||||
currentSkin.BindValueChanged(skin => Enabled.Value = skin.NewValue.SkinInfo.PerformRead(s => !s.Protected), true);
|
||||
currentSkin.BindValueChanged(_ => updateState());
|
||||
currentSkin.BindDisabledChanged(_ => updateState(), true);
|
||||
}
|
||||
|
||||
private void updateState() => Enabled.Value = !currentSkin.Disabled && currentSkin.Value.SkinInfo.PerformRead(s => !s.Protected);
|
||||
|
||||
private void delete()
|
||||
{
|
||||
dialogOverlay?.Push(new SkinDeleteDialog(currentSkin.Value));
|
||||
|
||||
284
osu.Game/Overlays/SkinEditor/ExternalEditOverlay.cs
Normal file
284
osu.Game/Overlays/SkinEditor/ExternalEditOverlay.cs
Normal file
@@ -0,0 +1,284 @@
|
||||
// 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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.SkinEditor
|
||||
{
|
||||
public partial class ExternalEditOverlay : OsuFocusedOverlayContainer
|
||||
{
|
||||
private const double transition_duration = 300;
|
||||
private FillFlowContainer flow = null!;
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
[Resolved]
|
||||
private GameHost gameHost { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private SkinManager skinManager { get; set; } = null!;
|
||||
|
||||
private ExternalEditOperation<SkinInfo>? editOperation;
|
||||
private TaskCompletionSource? taskCompletionSource;
|
||||
|
||||
protected override bool DimMainContent => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
InternalChild = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
// Since we're drawing this overlay on top of another overlay (SkinEditor), the dimming effect isn't applied. So we need to add a dimming effect manually.
|
||||
new Box
|
||||
{
|
||||
Colour = Color4.Black.Opacity(0.5f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = 20,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
AutoSizeDuration = 500,
|
||||
AutoSizeEasing = Easing.OutQuint,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colourProvider.Background5,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
flow = new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(20),
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Spacing = new Vector2(15),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Task> Begin(SkinInfo skinInfo)
|
||||
{
|
||||
if (taskCompletionSource != null)
|
||||
throw new InvalidOperationException("Cannot start multiple concurrent external edits!");
|
||||
|
||||
Show();
|
||||
showSpinner("Mounting external skin...");
|
||||
setGlobalSkinDisabled(true);
|
||||
|
||||
await Task.Delay(500).ConfigureAwait(true);
|
||||
|
||||
try
|
||||
{
|
||||
editOperation = await skinManager.BeginExternalEditing(skinInfo).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Failed to initialize external edit operation: {ex}", LoggingTarget.Database, LogLevel.Error);
|
||||
setGlobalSkinDisabled(false);
|
||||
Schedule(() => showSpinner("Export failed!"));
|
||||
Scheduler.AddDelayed(Hide, 1000);
|
||||
return Task.FromException(ex);
|
||||
}
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
flow.Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "Skin is mounted externally",
|
||||
Font = OsuFont.Default.With(size: 30),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
},
|
||||
new OsuTextFlowContainer
|
||||
{
|
||||
Padding = new MarginPadding(5),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Width = 350,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Text = "Any changes made to the exported folder will be imported to the game, including file additions, modifications and deletions.",
|
||||
},
|
||||
new PurpleRoundedButton
|
||||
{
|
||||
Text = "Open folder",
|
||||
Width = 350,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Action = openDirectory,
|
||||
Enabled = { Value = false }
|
||||
},
|
||||
new DangerousRoundedButton
|
||||
{
|
||||
Text = EditorStrings.FinishEditingExternally,
|
||||
Width = 350,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Action = () => finish().FireAndForget(),
|
||||
Enabled = { Value = false }
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Scheduler.AddDelayed(() =>
|
||||
{
|
||||
foreach (var b in flow.ChildrenOfType<RoundedButton>())
|
||||
b.Enabled.Value = true;
|
||||
openDirectory();
|
||||
}, 1000);
|
||||
return (taskCompletionSource = new TaskCompletionSource()).Task;
|
||||
}
|
||||
|
||||
private void openDirectory()
|
||||
{
|
||||
if (editOperation == null)
|
||||
return;
|
||||
|
||||
gameHost.OpenFileExternally(editOperation.MountedPath.TrimDirectorySeparator() + Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
private async Task finish()
|
||||
{
|
||||
Debug.Assert(taskCompletionSource != null);
|
||||
|
||||
showSpinner("Cleaning up...");
|
||||
await Task.Delay(500).ConfigureAwait(true);
|
||||
|
||||
try
|
||||
{
|
||||
await editOperation!.Finish().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Failed to finish external edit operation: {ex}", LoggingTarget.Database, LogLevel.Error);
|
||||
showSpinner("Import failed!");
|
||||
Scheduler.AddDelayed(Hide, 1000);
|
||||
setGlobalSkinDisabled(false);
|
||||
taskCompletionSource.SetException(ex);
|
||||
taskCompletionSource = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
var oldSkin = skinManager.CurrentSkin!.Value;
|
||||
var newSkinInfo = oldSkin.SkinInfo.PerformRead(s => s);
|
||||
|
||||
// Create a new skin instance to ensure the skin is reloaded
|
||||
// If there's a better way to reload the skin, this should be replaced with it.
|
||||
setGlobalSkinDisabled(false);
|
||||
skinManager.CurrentSkin.Value = newSkinInfo.CreateInstance(skinManager);
|
||||
|
||||
oldSkin.Dispose();
|
||||
|
||||
Hide();
|
||||
});
|
||||
taskCompletionSource.SetResult();
|
||||
taskCompletionSource = null;
|
||||
}
|
||||
|
||||
private void setGlobalSkinDisabled(bool disabled)
|
||||
{
|
||||
skinManager.CurrentSkin.Disabled = disabled;
|
||||
skinManager.CurrentSkinInfo.Disabled = disabled;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.FadeIn(transition_duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
this.FadeOut(transition_duration, Easing.OutQuint).Finally(_ =>
|
||||
{
|
||||
// Set everything to a clean state
|
||||
editOperation = null;
|
||||
flow.Children = Array.Empty<Drawable>();
|
||||
});
|
||||
}
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Repeat)
|
||||
return false;
|
||||
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
case GlobalAction.Select:
|
||||
if (editOperation == null) return base.OnPressed(e);
|
||||
|
||||
finish().FireAndForget();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnPressed(e);
|
||||
}
|
||||
|
||||
private void showSpinner(string text)
|
||||
{
|
||||
foreach (var b in flow.ChildrenOfType<RoundedButton>())
|
||||
b.Enabled.Value = false;
|
||||
|
||||
flow.Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = text,
|
||||
Font = OsuFont.Default.With(size: 30),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
},
|
||||
new LoadingSpinner
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
State = { Value = Visibility.Visible }
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
public readonly BindableList<ISerialisableDrawable> SelectedComponents = new BindableList<ISerialisableDrawable>();
|
||||
|
||||
public bool ExternalEditInProgress => externalEditOperation != null && !externalEditOperation.IsCompleted;
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
private Drawable? targetScreen;
|
||||
@@ -105,6 +107,11 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
[Resolved]
|
||||
private IDialogOverlay? dialogOverlay { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private ExternalEditOverlay? externalEditOverlay { get; set; }
|
||||
|
||||
private Task? externalEditOperation;
|
||||
|
||||
public SkinEditor()
|
||||
{
|
||||
}
|
||||
@@ -160,6 +167,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
{
|
||||
new EditorMenuItem(Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()) { Hotkey = new Hotkey(PlatformAction.Save) },
|
||||
new EditorMenuItem(CommonStrings.Export, MenuItemType.Standard, () => skins.ExportCurrentSkin()) { Action = { Disabled = !RuntimeInfo.IsDesktop } },
|
||||
new EditorMenuItem(EditorStrings.EditExternally, MenuItemType.Standard, () => _ = editExternally()) { Action = { Disabled = !RuntimeInfo.IsDesktop } },
|
||||
new OsuMenuItemSpacer(),
|
||||
new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, () => dialogOverlay?.Push(new RevertConfirmDialog(revert))),
|
||||
new OsuMenuItemSpacer(),
|
||||
@@ -277,6 +285,15 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
selectedTarget.BindValueChanged(targetChanged, true);
|
||||
}
|
||||
|
||||
private async Task editExternally()
|
||||
{
|
||||
Save();
|
||||
|
||||
var skin = currentSkin.Value.SkinInfo.PerformRead(s => s.Detach());
|
||||
|
||||
externalEditOperation = await externalEditOverlay!.Begin(skin).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
|
||||
{
|
||||
switch (e.Action)
|
||||
@@ -512,6 +529,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
private void populateSettings()
|
||||
{
|
||||
//过滤选择组件
|
||||
settingsSidebar.PopulateSettings(content =>
|
||||
{
|
||||
foreach (var component in SelectedComponents.OfType<Drawable>())
|
||||
|
||||
@@ -28,7 +28,7 @@ using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.SelectV2;
|
||||
using osu.Game.Users;
|
||||
using osu.Game.Utils;
|
||||
|
||||
@@ -49,9 +49,15 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
[Resolved]
|
||||
private IPerformFromScreenRunner? performer { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IOverlayManager? overlayManager { get; set; }
|
||||
|
||||
[Cached]
|
||||
public readonly EditorClipboard Clipboard = new EditorClipboard();
|
||||
|
||||
[Cached]
|
||||
private readonly ExternalEditOverlay externalEditOverlay = new ExternalEditOverlay();
|
||||
|
||||
[Resolved]
|
||||
private OsuGame game { get; set; } = null!;
|
||||
|
||||
@@ -69,6 +75,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
private OsuScreen? lastTargetScreen;
|
||||
private InvokeOnDisposal? nestedInputManagerDisable;
|
||||
private IDisposable? externalEditOverlayRegistration;
|
||||
|
||||
private readonly LayoutValue drawSizeLayout;
|
||||
|
||||
@@ -86,6 +93,13 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
externalEditOverlayRegistration = overlayManager?.RegisterBlockingOverlay(externalEditOverlay);
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
switch (e.Action)
|
||||
@@ -180,7 +194,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
// the validity of the current game-wide beatmap + ruleset combination is enforced by song select.
|
||||
// if we're anywhere else, the state is unknown and may not make sense, so forcibly set something that does.
|
||||
if (screen is not PlaySongSelect)
|
||||
if (screen is not SoloSongSelect)
|
||||
ruleset.Value = beatmap.Value.BeatmapInfo.Ruleset;
|
||||
var replayGeneratingMod = ruleset.Value.CreateInstance().GetAutoplayMod();
|
||||
|
||||
@@ -194,7 +208,7 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
|
||||
if (replayGeneratingMod != null)
|
||||
screen.Push(new EndlessPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)));
|
||||
}, new[] { typeof(Player), typeof(PlaySongSelect) });
|
||||
}, new[] { typeof(Player), typeof(SoloSongSelect) });
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
@@ -334,6 +348,22 @@ namespace osu.Game.Overlays.SkinEditor
|
||||
leasedBeatmapSkins = null;
|
||||
}
|
||||
|
||||
public new void ToggleVisibility()
|
||||
{
|
||||
if (skinEditor?.ExternalEditInProgress == true)
|
||||
return;
|
||||
|
||||
base.ToggleVisibility();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
externalEditOverlayRegistration?.Dispose();
|
||||
externalEditOverlayRegistration = null;
|
||||
}
|
||||
|
||||
private partial class EndlessPlayer : ReplayPlayer
|
||||
{
|
||||
protected override UserActivity? InitialActivity => null;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user