Delete unused rule sets
@ -13,7 +13,8 @@
|
||||
<AssemblyName>osu.Android</AssemblyName>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
||||
<EnableLLVM>false</EnableLLVM> <!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
||||
<EnableLLVM>false</EnableLLVM>
|
||||
<!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
||||
@ -35,22 +36,10 @@
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
||||
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
|
||||
<Name>osu.Game.Rulesets.Catch</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj">
|
||||
<Project>{48f4582b-7687-4621-9cbe-5c24197cb536}</Project>
|
||||
<Name>osu.Game.Rulesets.Mania</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
|
||||
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
|
||||
<Name>osu.Game.Rulesets.Osu</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
|
||||
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
|
||||
<Name>osu.Game.Rulesets.Taiko</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
|
@ -19,9 +19,6 @@
|
||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Clowd.Squirrel" Version="2.9.40" />
|
||||
|
@ -1,15 +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 Android.App;
|
||||
using osu.Framework.Android;
|
||||
using osu.Game.Tests;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Android
|
||||
{
|
||||
[Activity(ConfigurationChanges = DEFAULT_CONFIG_CHANGES, Exported = true, LaunchMode = DEFAULT_LAUNCH_MODE, MainLauncher = true)]
|
||||
public class MainActivity : AndroidGameActivity
|
||||
{
|
||||
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- using a different name because package name cannot contain 'catch' -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="osu.Game.Rulesets.Catch_Tests.Android" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
|
||||
<application android:allowBackup="true" android:supportsRtl="true" android:label="osu!catch Test" />
|
||||
</manifest>
|
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\osu.Android.props" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C5379ECB-3A94-4D2F-AC3B-2615AC23EB0D}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TemplateGuid>{122416d6-6b49-4ee2-a1e8-b825f31c79fe}</TemplateGuid>
|
||||
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
||||
<AssemblyName>osu.Game.Rulesets.Catch.Tests.Android</AssemblyName>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainActivity.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\*.cs">
|
||||
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
||||
<Project>{58f6c80c-1253-4a0e-a465-b8c85ebeadf3}</Project>
|
||||
<Name>osu.Game.Rulesets.Catch</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Formats.Asn1">
|
||||
<Version>5.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
@ -1,15 +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 Foundation;
|
||||
using osu.Framework.iOS;
|
||||
using osu.Game.Tests;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
||||
{
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : GameAppDelegate
|
||||
{
|
||||
protected override Framework.Game CreateGame() => new OsuTestBrowser();
|
||||
}
|
||||
}
|
@ -1,16 +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 osu.Framework.iOS;
|
||||
using UIKit;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.iOS
|
||||
{
|
||||
public static class Application
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
UIApplication.Main(args, typeof(GameUIApplication), typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
</dict>
|
||||
</plist>
|
@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>osu.Game.Rulesets.Catch.Tests.iOS</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>ppy.osu-Game-Rulesets-Catch-Tests-iOS</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>10.0</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
|
||||
<ProjectGuid>{4004C7B7-1A62-43F1-9DF2-52450FA67E70}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>osu.Game.Rulesets.Catch.Tests</RootNamespace>
|
||||
<AssemblyName>osu.Game.Rulesets.Catch.Tests.iOS</AssemblyName>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\osu.iOS.props" />
|
||||
<ItemGroup>
|
||||
<None Include="Info.plist" />
|
||||
<None Include="Entitlements.plist" />
|
||||
<LinkDescription Include="..\osu.iOS\Linker.xml">
|
||||
<Link>Linker.xml</Link>
|
||||
</LinkDescription>
|
||||
<Compile Include="Application.cs" />
|
||||
<Compile Include="AppDelegate.cs" />
|
||||
<Compile Include="..\osu.Game.Rulesets.Catch.Tests\**\*.cs" Exclude="**\obj\**">
|
||||
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj">
|
||||
<Project>{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}</Project>
|
||||
<Name>osu.Game.Rulesets.Catch</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
</Project>
|
@ -1,31 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "VisualTests (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/net6.0/osu.Game.Rulesets.Catch.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
"env": {},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "VisualTests (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/net6.0/osu.Game.Rulesets.Catch.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
"env": {},
|
||||
"console": "internalConsole"
|
||||
}
|
||||
]
|
||||
}
|
36
osu.Game.Rulesets.Catch.Tests/.vscode/tasks.json
vendored
@ -1,36 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"osu.Game.Rulesets.Catch.Tests.csproj",
|
||||
"-p:GenerateFullPaths=true",
|
||||
"-m",
|
||||
"-verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Build (Release)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"osu.Game.Rulesets.Catch.Tests.csproj",
|
||||
"-p:Configuration=Release",
|
||||
"-p:GenerateFullPaths=true",
|
||||
"-m",
|
||||
"-verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,105 +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 Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class CatchBeatmapConversionTest : BeatmapConversionTest<ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
|
||||
|
||||
[TestCase("basic")]
|
||||
[TestCase("spinner")]
|
||||
[TestCase("spinner-and-circles")]
|
||||
[TestCase("slider")]
|
||||
[TestCase("hardrock-stream", new[] { typeof(CatchModHardRock) })]
|
||||
[TestCase("hardrock-repeat-slider", new[] { typeof(CatchModHardRock) })]
|
||||
[TestCase("hardrock-spinner", new[] { typeof(CatchModHardRock) })]
|
||||
[TestCase("right-bound-hr-offset", new[] { typeof(CatchModHardRock) })]
|
||||
[TestCase("basic-hyperdash")]
|
||||
public new void Test(string name, params Type[] mods) => base.Test(name, mods);
|
||||
|
||||
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
||||
{
|
||||
switch (hitObject)
|
||||
{
|
||||
case JuiceStream stream:
|
||||
foreach (var nested in stream.NestedHitObjects)
|
||||
yield return new ConvertValue((CatchHitObject)nested);
|
||||
|
||||
break;
|
||||
|
||||
case BananaShower shower:
|
||||
foreach (var nested in shower.NestedHitObjects)
|
||||
yield return new ConvertValue((CatchHitObject)nested);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
yield return new ConvertValue((CatchHitObject)hitObject);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// A sane value to account for osu!stable using ints everwhere.
|
||||
/// </summary>
|
||||
private const float conversion_lenience = 2;
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly CatchHitObject HitObject;
|
||||
|
||||
public ConvertValue(CatchHitObject hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
startTime = 0;
|
||||
position = 0;
|
||||
hyperDash = false;
|
||||
}
|
||||
|
||||
private double startTime;
|
||||
|
||||
public double StartTime
|
||||
{
|
||||
get => HitObject?.StartTime ?? startTime;
|
||||
set => startTime = value;
|
||||
}
|
||||
|
||||
private float position;
|
||||
|
||||
public float Position
|
||||
{
|
||||
get => HitObject?.EffectiveX ?? position;
|
||||
set => position = value;
|
||||
}
|
||||
|
||||
private bool hyperDash;
|
||||
|
||||
public bool HyperDash
|
||||
{
|
||||
get => (HitObject as PalpableCatchHitObject)?.HyperDash ?? hyperDash;
|
||||
set => hyperDash = value;
|
||||
}
|
||||
|
||||
public bool Equals(ConvertValue other)
|
||||
=> Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience)
|
||||
&& Precision.AlmostEquals(Position, other.Position, conversion_lenience)
|
||||
&& HyperDash == other.HyperDash;
|
||||
}
|
||||
}
|
@ -1,29 +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 NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Difficulty;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class CatchDifficultyCalculatorTest : DifficultyCalculatorTest
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
|
||||
|
||||
[TestCase(4.0505463516206195d, 127, "diffcalc-test")]
|
||||
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
|
||||
=> base.Test(expectedStarRating, expectedMaxCombo, name);
|
||||
|
||||
[TestCase(5.1696411260785498d, 127, "diffcalc-test")]
|
||||
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
|
||||
=> Test(expectedStarRating, expectedMaxCombo, name, new CatchModDoubleTime());
|
||||
|
||||
protected override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new CatchDifficultyCalculator(new CatchRuleset().RulesetInfo, beatmap);
|
||||
|
||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||
}
|
||||
}
|
@ -1,44 +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 NUnit.Framework;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class CatchLegacyModConversionTest : LegacyModConversionTest
|
||||
{
|
||||
private static readonly object[][] catch_mod_mapping =
|
||||
{
|
||||
new object[] { LegacyMods.NoFail, new[] { typeof(CatchModNoFail) } },
|
||||
new object[] { LegacyMods.Easy, new[] { typeof(CatchModEasy) } },
|
||||
new object[] { LegacyMods.Hidden, new[] { typeof(CatchModHidden) } },
|
||||
new object[] { LegacyMods.HardRock, new[] { typeof(CatchModHardRock) } },
|
||||
new object[] { LegacyMods.SuddenDeath, new[] { typeof(CatchModSuddenDeath) } },
|
||||
new object[] { LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) } },
|
||||
new object[] { LegacyMods.Relax, new[] { typeof(CatchModRelax) } },
|
||||
new object[] { LegacyMods.HalfTime, new[] { typeof(CatchModHalfTime) } },
|
||||
new object[] { LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) } },
|
||||
new object[] { LegacyMods.Flashlight, new[] { typeof(CatchModFlashlight) } },
|
||||
new object[] { LegacyMods.Autoplay, new[] { typeof(CatchModAutoplay) } },
|
||||
new object[] { LegacyMods.Perfect, new[] { typeof(CatchModPerfect) } },
|
||||
new object[] { LegacyMods.Cinema, new[] { typeof(CatchModCinema) } },
|
||||
new object[] { LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) } }
|
||||
};
|
||||
|
||||
[TestCaseSource(nameof(catch_mod_mapping))]
|
||||
[TestCase(LegacyMods.Cinema | LegacyMods.Autoplay, new[] { typeof(CatchModCinema) })]
|
||||
[TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })]
|
||||
[TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })]
|
||||
public new void TestFromLegacy(LegacyMods legacyMods, Type[] expectedMods) => base.TestFromLegacy(legacyMods, expectedMods);
|
||||
|
||||
[TestCaseSource(nameof(catch_mod_mapping))]
|
||||
public new void TestToLegacy(LegacyMods legacyMods, Type[] givenMods) => base.TestToLegacy(legacyMods, givenMods);
|
||||
|
||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||
}
|
||||
}
|
@ -1,38 +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 NUnit.Framework;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Game.Rulesets.Catch.Skinning;
|
||||
using osu.Game.Rulesets.Catch.Skinning.Legacy;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class CatchSkinColourDecodingTest
|
||||
{
|
||||
[Test]
|
||||
public void TestCatchSkinColourDecoding()
|
||||
{
|
||||
var store = new NamespacedResourceStore<byte[]>(new DllResourceStore(GetType().Assembly), "Resources/special-skin");
|
||||
var rawSkin = new TestLegacySkin(new SkinInfo { Name = "special-skin" }, store);
|
||||
var skinSource = new SkinProvidingContainer(rawSkin);
|
||||
var skin = new CatchLegacySkinTransformer(skinSource);
|
||||
|
||||
Assert.AreEqual(new Color4(232, 185, 35, 255), skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value);
|
||||
Assert.AreEqual(new Color4(232, 74, 35, 255), skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value);
|
||||
Assert.AreEqual(new Color4(0, 255, 255, 255), skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashFruit)?.Value);
|
||||
}
|
||||
|
||||
private class TestLegacySkin : LegacySkin
|
||||
{
|
||||
public TestLegacySkin(SkinInfo skin, IResourceStore<byte[]> storage)
|
||||
// Bypass LegacySkinResourceStore to avoid returning null for retrieving files due to bad skin info (SkinInfo.Files = null).
|
||||
: base(skin, null, storage)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +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 osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public abstract class CatchSkinnableTestScene : SkinnableTestScene
|
||||
{
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset();
|
||||
}
|
||||
}
|
@ -1,66 +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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class CatchEditorTestSceneContainer : Container
|
||||
{
|
||||
[Cached(typeof(Playfield))]
|
||||
public readonly ScrollingPlayfield Playfield;
|
||||
|
||||
protected override Container<Drawable> Content { get; }
|
||||
|
||||
public CatchEditorTestSceneContainer()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Width = CatchPlayfield.WIDTH;
|
||||
Height = 1000;
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Bottom = 100
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
{
|
||||
TimeRange = 1000,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = Playfield = new TestCatchPlayfield
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
new PlayfieldBorder
|
||||
{
|
||||
PlayfieldBorderStyle = { Value = PlayfieldBorderStyle.Full },
|
||||
Clock = new FramedClock(new StopwatchClock(true))
|
||||
},
|
||||
Content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class TestCatchPlayfield : CatchEditorPlayfield
|
||||
{
|
||||
public TestCatchPlayfield()
|
||||
: base(new BeatmapDifficulty { CircleSize = 0 })
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,79 +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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public abstract class CatchPlacementBlueprintTestScene : PlacementBlueprintTestScene
|
||||
{
|
||||
protected const double TIME_SNAP = 100;
|
||||
|
||||
protected DrawableCatchHitObject LastObject;
|
||||
|
||||
protected new ScrollingHitObjectContainer HitObjectContainer => contentContainer.Playfield.HitObjectContainer;
|
||||
|
||||
protected override Container<Drawable> Content => contentContainer;
|
||||
|
||||
private readonly CatchEditorTestSceneContainer contentContainer;
|
||||
|
||||
protected CatchPlacementBlueprintTestScene()
|
||||
{
|
||||
base.Content.Add(contentContainer = new CatchEditorTestSceneContainer());
|
||||
|
||||
contentContainer.Playfield.Clock = new FramedClock(new ManualClock());
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
HitObjectContainer.Clear();
|
||||
ResetPlacement();
|
||||
LastObject = null;
|
||||
});
|
||||
|
||||
protected void AddMoveStep(double time, float x) => AddStep($"move to time={time}, x={x}", () =>
|
||||
{
|
||||
float y = HitObjectContainer.PositionAtTime(time);
|
||||
Vector2 pos = HitObjectContainer.ToScreenSpace(new Vector2(x, y + HitObjectContainer.DrawHeight));
|
||||
InputManager.MoveMouseTo(pos);
|
||||
});
|
||||
|
||||
protected void AddClickStep(MouseButton button) => AddStep($"click {button}", () =>
|
||||
{
|
||||
InputManager.Click(button);
|
||||
});
|
||||
|
||||
protected IEnumerable<FruitOutline> FruitOutlines => Content.ChildrenOfType<FruitOutline>();
|
||||
|
||||
// Unused because AddHitObject is overriden
|
||||
protected override Container CreateHitObjectContainer() => new Container();
|
||||
|
||||
protected override void AddHitObject(DrawableHitObject hitObject)
|
||||
{
|
||||
LastObject = (DrawableCatchHitObject)hitObject;
|
||||
contentContainer.Playfield.HitObjectContainer.Add(hitObject);
|
||||
}
|
||||
|
||||
protected override SnapResult SnapForBlueprint(PlacementBlueprint blueprint)
|
||||
{
|
||||
var result = base.SnapForBlueprint(blueprint);
|
||||
result.Time = Math.Round(HitObjectContainer.TimeAtScreenSpacePosition(result.ScreenSpacePosition) / TIME_SNAP) * TIME_SNAP;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,78 +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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public abstract class CatchSelectionBlueprintTestScene : SelectionBlueprintTestScene
|
||||
{
|
||||
protected ScrollingHitObjectContainer HitObjectContainer => contentContainer.Playfield.HitObjectContainer;
|
||||
|
||||
protected override Container<Drawable> Content => contentContainer;
|
||||
|
||||
[Cached(typeof(EditorBeatmap))]
|
||||
[Cached(typeof(IBeatSnapProvider))]
|
||||
protected readonly EditorBeatmap EditorBeatmap;
|
||||
|
||||
private readonly CatchEditorTestSceneContainer contentContainer;
|
||||
|
||||
protected CatchSelectionBlueprintTestScene()
|
||||
{
|
||||
var catchBeatmap = new CatchBeatmap
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
Ruleset = new CatchRuleset().RulesetInfo,
|
||||
}
|
||||
};
|
||||
EditorBeatmap = new EditorBeatmap(catchBeatmap) { Difficulty = { CircleSize = 0 } };
|
||||
EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint
|
||||
{
|
||||
BeatLength = 100
|
||||
});
|
||||
|
||||
base.Content.Add(new EditorBeatmapDependencyContainer(EditorBeatmap, new BindableBeatDivisor())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
EditorBeatmap,
|
||||
contentContainer = new CatchEditorTestSceneContainer()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
protected void AddMouseMoveStep(double time, float x) => AddStep($"move to time={time}, x={x}", () =>
|
||||
{
|
||||
float y = HitObjectContainer.PositionAtTime(time);
|
||||
Vector2 pos = HitObjectContainer.ToScreenSpace(new Vector2(x, y + HitObjectContainer.DrawHeight));
|
||||
InputManager.MoveMouseTo(pos);
|
||||
});
|
||||
|
||||
private class EditorBeatmapDependencyContainer : Container
|
||||
{
|
||||
[Cached]
|
||||
private readonly EditorClock editorClock;
|
||||
|
||||
[Cached]
|
||||
private readonly BindableBeatDivisor beatDivisor;
|
||||
|
||||
public EditorBeatmapDependencyContainer(IBeatmap beatmap, BindableBeatDivisor beatDivisor)
|
||||
{
|
||||
editorClock = new EditorClock(beatmap, beatDivisor);
|
||||
this.beatDivisor = beatDivisor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,118 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Edit.Checks;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCheckBananaShowerGap
|
||||
{
|
||||
private CheckBananaShowerGap check;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
check = new CheckBananaShowerGap();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAllowedSpinnerGaps()
|
||||
{
|
||||
assertOk(mockBeatmap(250, 1000, 1250), DifficultyRating.Easy);
|
||||
assertOk(mockBeatmap(250, 1000, 1250), DifficultyRating.Normal);
|
||||
assertOk(mockBeatmap(125, 1000, 1250), DifficultyRating.Hard);
|
||||
assertOk(mockBeatmap(125, 1000, 1125), DifficultyRating.Insane);
|
||||
assertOk(mockBeatmap(62, 1000, 1125), DifficultyRating.Expert);
|
||||
assertOk(mockBeatmap(62, 1000, 1125), DifficultyRating.ExpertPlus);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisallowedSpinnerGapStart()
|
||||
{
|
||||
assertTooShortSpinnerStart(mockBeatmap(249, 1000, 1250), DifficultyRating.Easy);
|
||||
assertTooShortSpinnerStart(mockBeatmap(249, 1000, 1250), DifficultyRating.Normal);
|
||||
assertTooShortSpinnerStart(mockBeatmap(124, 1000, 1250), DifficultyRating.Hard);
|
||||
assertTooShortSpinnerStart(mockBeatmap(124, 1000, 1250), DifficultyRating.Insane);
|
||||
assertTooShortSpinnerStart(mockBeatmap(61, 1000, 1250), DifficultyRating.Expert);
|
||||
assertTooShortSpinnerStart(mockBeatmap(61, 1000, 1250), DifficultyRating.ExpertPlus);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisallowedSpinnerGapEnd()
|
||||
{
|
||||
assertTooShortSpinnerEnd(mockBeatmap(250, 1000, 1249), DifficultyRating.Easy);
|
||||
assertTooShortSpinnerEnd(mockBeatmap(250, 1000, 1249), DifficultyRating.Normal);
|
||||
assertTooShortSpinnerEnd(mockBeatmap(125, 1000, 1249), DifficultyRating.Hard);
|
||||
assertTooShortSpinnerEnd(mockBeatmap(125, 1000, 1124), DifficultyRating.Insane);
|
||||
assertTooShortSpinnerEnd(mockBeatmap(62, 1000, 1124), DifficultyRating.Expert);
|
||||
assertTooShortSpinnerEnd(mockBeatmap(62, 1000, 1124), DifficultyRating.ExpertPlus);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConsecutiveSpinners()
|
||||
{
|
||||
var spinnerConsecutiveBeatmap = new Beatmap<HitObject>
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new BananaShower { StartTime = 0, EndTime = 100, X = 0 },
|
||||
new BananaShower { StartTime = 101, EndTime = 200, X = 0 },
|
||||
new BananaShower { StartTime = 201, EndTime = 300, X = 0 }
|
||||
}
|
||||
};
|
||||
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.Easy);
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.Normal);
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.Hard);
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.Insane);
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.Expert);
|
||||
assertOk(spinnerConsecutiveBeatmap, DifficultyRating.ExpertPlus);
|
||||
}
|
||||
|
||||
private Beatmap<HitObject> mockBeatmap(double bananaShowerStart, double bananaShowerEnd, double nextFruitStart)
|
||||
{
|
||||
return new Beatmap<HitObject>
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new Fruit { StartTime = 0, X = 0 },
|
||||
new BananaShower { StartTime = bananaShowerStart, EndTime = bananaShowerEnd, X = 0 },
|
||||
new Fruit { StartTime = nextFruitStart, X = 0 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void assertOk(IBeatmap beatmap, DifficultyRating difficultyRating)
|
||||
{
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap), difficultyRating);
|
||||
Assert.That(check.Run(context), Is.Empty);
|
||||
}
|
||||
|
||||
private void assertTooShortSpinnerStart(IBeatmap beatmap, DifficultyRating difficultyRating)
|
||||
{
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap), difficultyRating);
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckBananaShowerGap.IssueTemplateBananaShowerStartGap));
|
||||
}
|
||||
|
||||
private void assertTooShortSpinnerEnd(IBeatmap beatmap, DifficultyRating difficultyRating)
|
||||
{
|
||||
var context = new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap), difficultyRating);
|
||||
var issues = check.Run(context).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(1));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckBananaShowerGap.IssueTemplateBananaShowerEndGap));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class TestSceneBananaShowerPlacementBlueprint : CatchPlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableBananaShower((BananaShower)hitObject);
|
||||
|
||||
protected override PlacementBlueprint CreateBlueprint() => new BananaShowerPlacementBlueprint();
|
||||
|
||||
protected override void AddHitObject(DrawableHitObject hitObject)
|
||||
{
|
||||
// Create nested bananas (but positions are not randomized because beatmap processing is not done).
|
||||
hitObject.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
base.AddHitObject(hitObject);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBasicPlacement()
|
||||
{
|
||||
const double start_time = 100;
|
||||
const double end_time = 500;
|
||||
|
||||
AddMoveStep(start_time, 0);
|
||||
AddClickStep(MouseButton.Left);
|
||||
AddMoveStep(end_time, 0);
|
||||
AddClickStep(MouseButton.Right);
|
||||
AddAssert("banana shower is placed", () => LastObject is DrawableBananaShower);
|
||||
AddAssert("start time is correct", () => Precision.AlmostEquals(LastObject.HitObject.StartTime, start_time));
|
||||
AddAssert("end time is correct", () => Precision.AlmostEquals(LastObject.HitObject.GetEndTime(), end_time));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestReversePlacement()
|
||||
{
|
||||
const double start_time = 100;
|
||||
const double end_time = 500;
|
||||
|
||||
AddMoveStep(end_time, 0);
|
||||
AddClickStep(MouseButton.Left);
|
||||
|
||||
AddMoveStep(start_time, 0);
|
||||
AddAssert("duration is positive", () => ((BananaShower)CurrentBlueprint.HitObject).Duration > 0);
|
||||
|
||||
AddClickStep(MouseButton.Right);
|
||||
AddAssert("start time is correct", () => Precision.AlmostEquals(LastObject.HitObject.StartTime, start_time));
|
||||
AddAssert("end time is correct", () => Precision.AlmostEquals(LastObject.HitObject.GetEndTime(), end_time));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFinishWithZeroDuration()
|
||||
{
|
||||
AddMoveStep(100, 0);
|
||||
AddClickStep(MouseButton.Left);
|
||||
AddClickStep(MouseButton.Right);
|
||||
AddAssert("banana shower is not placed", () => LastObject == null);
|
||||
AddAssert("state is waiting", () => CurrentBlueprint?.PlacementActive == PlacementBlueprint.PlacementState.Waiting);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOpacity()
|
||||
{
|
||||
AddMoveStep(100, 0);
|
||||
AddClickStep(MouseButton.Left);
|
||||
AddUntilStep("outline is semitransparent", () => Precision.DefinitelyBigger(1, timeSpanOutline.Alpha));
|
||||
AddMoveStep(200, 0);
|
||||
AddUntilStep("outline is opaque", () => Precision.AlmostEquals(timeSpanOutline.Alpha, 1));
|
||||
AddMoveStep(100, 0);
|
||||
AddUntilStep("outline is semitransparent", () => Precision.DefinitelyBigger(1, timeSpanOutline.Alpha));
|
||||
}
|
||||
|
||||
private TimeSpanOutline timeSpanOutline => Content.ChildrenOfType<TimeSpanOutline>().Single();
|
||||
}
|
||||
}
|
@ -1,91 +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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class TestSceneCatchDistanceSnapGrid : OsuManualInputManagerTestScene
|
||||
{
|
||||
private readonly ManualClock manualClock = new ManualClock();
|
||||
|
||||
[Cached(typeof(Playfield))]
|
||||
private readonly CatchPlayfield playfield;
|
||||
|
||||
private ScrollingHitObjectContainer hitObjectContainer => playfield.HitObjectContainer;
|
||||
|
||||
private readonly CatchDistanceSnapGrid distanceGrid;
|
||||
|
||||
private readonly FruitOutline fruitOutline;
|
||||
|
||||
private readonly Fruit fruit = new Fruit();
|
||||
|
||||
public TestSceneCatchDistanceSnapGrid()
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 500,
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = playfield = new CatchPlayfield(new BeatmapDifficulty())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedClock(manualClock)
|
||||
}
|
||||
},
|
||||
distanceGrid = new CatchDistanceSnapGrid(new double[] { 0, -1, 1 }),
|
||||
fruitOutline = new FruitOutline()
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
distanceGrid.StartTime = 100;
|
||||
distanceGrid.StartX = 250;
|
||||
|
||||
Vector2 screenSpacePosition = InputManager.CurrentState.Mouse.Position;
|
||||
|
||||
var result = distanceGrid.GetSnappedPosition(screenSpacePosition);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
fruit.OriginalX = hitObjectContainer.ToLocalSpace(result.ScreenSpacePosition).X;
|
||||
|
||||
if (result.Time != null)
|
||||
fruit.StartTime = result.Time.Value;
|
||||
}
|
||||
|
||||
fruitOutline.Position = CatchHitObjectUtils.GetStartPosition(hitObjectContainer, fruit);
|
||||
fruitOutline.UpdateFrom(fruit);
|
||||
}
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e)
|
||||
{
|
||||
manualClock.CurrentTime -= e.ScrollDelta.Y * 50;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +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 NUnit.Framework;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneEditor : EditorTestScene
|
||||
{
|
||||
protected override Ruleset CreateEditorRuleset() => new CatchRuleset();
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class TestSceneFruitPlacementBlueprint : CatchPlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableFruit((Fruit)hitObject);
|
||||
|
||||
protected override PlacementBlueprint CreateBlueprint() => new FruitPlacementBlueprint();
|
||||
|
||||
[Test]
|
||||
public void TestFruitPlacementPosition()
|
||||
{
|
||||
const double time = 300;
|
||||
const float x = CatchPlayfield.CENTER_X;
|
||||
|
||||
AddMoveStep(time, x);
|
||||
AddClickStep(MouseButton.Left);
|
||||
|
||||
AddAssert("outline position is correct", () =>
|
||||
{
|
||||
var outline = FruitOutlines.Single();
|
||||
return Precision.AlmostEquals(outline.X, x) &&
|
||||
Precision.AlmostEquals(outline.Y, HitObjectContainer.PositionAtTime(time));
|
||||
});
|
||||
|
||||
AddAssert("fruit time is correct", () => Precision.AlmostEquals(LastObject.StartTimeBindable.Value, time));
|
||||
AddAssert("fruit position is correct", () => Precision.AlmostEquals(LastObject.X, x));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,141 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class TestSceneJuiceStreamPlacementBlueprint : CatchPlacementBlueprintTestScene
|
||||
{
|
||||
private const double velocity_factor = 0.5;
|
||||
|
||||
private JuiceStream lastObject => LastObject?.HitObject as JuiceStream;
|
||||
|
||||
protected override IBeatmap GetPlayableBeatmap()
|
||||
{
|
||||
var playable = base.GetPlayableBeatmap();
|
||||
playable.Difficulty.SliderTickRate = 5;
|
||||
playable.Difficulty.SliderMultiplier = velocity_factor * 10;
|
||||
return playable;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBasicPlacement()
|
||||
{
|
||||
double[] times = { 300, 800 };
|
||||
float[] positions = { 100, 200 };
|
||||
addPlacementSteps(times, positions);
|
||||
|
||||
AddAssert("juice stream is placed", () => lastObject != null);
|
||||
AddAssert("start time is correct", () => Precision.AlmostEquals(lastObject.StartTime, times[0]));
|
||||
AddAssert("end time is correct", () => Precision.AlmostEquals(lastObject.EndTime, times[1]));
|
||||
AddAssert("start position is correct", () => Precision.AlmostEquals(lastObject.OriginalX, positions[0]));
|
||||
AddAssert("end position is correct", () => Precision.AlmostEquals(lastObject.EndX, positions[1]));
|
||||
AddAssert("default slider velocity", () => lastObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyNotCommitted()
|
||||
{
|
||||
addMoveAndClickSteps(100, 100);
|
||||
addMoveAndClickSteps(100, 100);
|
||||
addMoveAndClickSteps(100, 100, true);
|
||||
AddAssert("juice stream not placed", () => lastObject == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleSegments()
|
||||
{
|
||||
double[] times = { 100, 300, 500, 700 };
|
||||
float[] positions = { 100, 150, 100, 100 };
|
||||
addPlacementSteps(times, positions);
|
||||
|
||||
AddAssert("has 4 vertices", () => lastObject.Path.ControlPoints.Count == 4);
|
||||
addPathCheckStep(times, positions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderVelocityChange()
|
||||
{
|
||||
double[] times = { 100, 300 };
|
||||
float[] positions = { 200, 500 };
|
||||
addPlacementSteps(times, positions);
|
||||
addPathCheckStep(times, positions);
|
||||
|
||||
AddAssert("slider velocity changed", () => !lastObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClampedPositionIsRestored()
|
||||
{
|
||||
double[] times = { 100, 300, 500 };
|
||||
float[] positions = { 200, 200, -3000, 250 };
|
||||
|
||||
addMoveAndClickSteps(times[0], positions[0]);
|
||||
addMoveAndClickSteps(times[1], positions[1]);
|
||||
AddMoveStep(times[2], positions[2]);
|
||||
addMoveAndClickSteps(times[2], positions[3], true);
|
||||
|
||||
addPathCheckStep(times, new float[] { 200, 200, 250 });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOutOfOrder()
|
||||
{
|
||||
double[] times = { 100, 700, 500, 300 };
|
||||
float[] positions = { 100, 200, 150, 50 };
|
||||
addPlacementSteps(times, positions);
|
||||
addPathCheckStep(times, positions);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMoveBeforeFirstVertex()
|
||||
{
|
||||
double[] times = { 300, 500, 100 };
|
||||
float[] positions = { 100, 100, 100 };
|
||||
addPlacementSteps(times, positions);
|
||||
AddAssert("start time is correct", () => Precision.AlmostEquals(lastObject.StartTime, times[0]));
|
||||
AddAssert("end time is correct", () => Precision.AlmostEquals(lastObject.EndTime, times[1], 1e-3));
|
||||
}
|
||||
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableJuiceStream((JuiceStream)hitObject);
|
||||
|
||||
protected override PlacementBlueprint CreateBlueprint() => new JuiceStreamPlacementBlueprint();
|
||||
|
||||
private void addMoveAndClickSteps(double time, float position, bool end = false)
|
||||
{
|
||||
AddMoveStep(time, position);
|
||||
AddClickStep(end ? MouseButton.Right : MouseButton.Left);
|
||||
}
|
||||
|
||||
private void addPlacementSteps(double[] times, float[] positions)
|
||||
{
|
||||
for (int i = 0; i < times.Length; i++)
|
||||
addMoveAndClickSteps(times[i], positions[i], i == times.Length - 1);
|
||||
}
|
||||
|
||||
private void addPathCheckStep(double[] times, float[] positions) => AddStep("assert path is correct", () =>
|
||||
Assert.That(getPositions(times), Is.EqualTo(positions).Within(Precision.FLOAT_EPSILON)));
|
||||
|
||||
private float[] getPositions(IEnumerable<double> times)
|
||||
{
|
||||
JuiceStream hitObject = lastObject.AsNonNull();
|
||||
return times
|
||||
.Select(time => (time - hitObject.StartTime) * hitObject.Velocity)
|
||||
.Select(distance => hitObject.EffectiveX + hitObject.Path.PositionAt(distance / hitObject.Distance).X)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,271 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Editor
|
||||
{
|
||||
public class TestSceneJuiceStreamSelectionBlueprint : CatchSelectionBlueprintTestScene
|
||||
{
|
||||
private JuiceStream hitObject;
|
||||
|
||||
private readonly ManualClock manualClock = new ManualClock();
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
EditorBeatmap.Clear();
|
||||
Content.Clear();
|
||||
|
||||
manualClock.CurrentTime = 0;
|
||||
Content.Clock = new FramedClock(manualClock);
|
||||
|
||||
InputManager.ReleaseButton(MouseButton.Left);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestBasicComponentLayout()
|
||||
{
|
||||
double[] times = { 100, 300, 500 };
|
||||
float[] positions = { 100, 200, 100 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
for (int i = 0; i < times.Length; i++)
|
||||
addVertexCheckStep(times.Length, i, times[i], positions[i]);
|
||||
|
||||
AddAssert("correct outline count", () =>
|
||||
{
|
||||
int expected = hitObject.NestedHitObjects.Count(h => !(h is TinyDroplet));
|
||||
return this.ChildrenOfType<FruitOutline>().Count() == expected;
|
||||
});
|
||||
AddAssert("correct vertex piece count", () =>
|
||||
this.ChildrenOfType<VertexPiece>().Count() == times.Length);
|
||||
|
||||
AddAssert("first vertex is semitransparent", () =>
|
||||
Precision.DefinitelyBigger(1, this.ChildrenOfType<VertexPiece>().First().Alpha));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVertexDrag()
|
||||
{
|
||||
double[] times = { 100, 400, 700 };
|
||||
float[] positions = { 100, 100, 100 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
addDragStartStep(times[1], positions[1]);
|
||||
|
||||
AddMouseMoveStep(500, 150);
|
||||
addVertexCheckStep(3, 1, 500, 150);
|
||||
|
||||
addDragEndStep();
|
||||
addDragStartStep(times[2], positions[2]);
|
||||
|
||||
AddMouseMoveStep(300, 50);
|
||||
addVertexCheckStep(3, 1, 300, 50);
|
||||
addVertexCheckStep(3, 2, 500, 150);
|
||||
|
||||
AddMouseMoveStep(-100, 100);
|
||||
addVertexCheckStep(3, 1, times[0], positions[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleDrag()
|
||||
{
|
||||
double[] times = { 100, 300, 500, 700 };
|
||||
float[] positions = { 100, 100, 100, 100 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
AddMouseMoveStep(times[1], positions[1]);
|
||||
AddStep("press left", () => InputManager.PressButton(MouseButton.Left));
|
||||
AddStep("release left", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
AddStep("hold control", () => InputManager.PressKey(Key.ControlLeft));
|
||||
addDragStartStep(times[2], positions[2]);
|
||||
|
||||
AddMouseMoveStep(times[2] - 50, positions[2] - 50);
|
||||
addVertexCheckStep(4, 1, times[1] - 50, positions[1] - 50);
|
||||
addVertexCheckStep(4, 2, times[2] - 50, positions[2] - 50);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderVelocityChange()
|
||||
{
|
||||
double[] times = { 100, 300 };
|
||||
float[] positions = { 200, 300 };
|
||||
addBlueprintStep(times, positions);
|
||||
AddAssert("default slider velocity", () => hitObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault);
|
||||
|
||||
addDragStartStep(times[1], positions[1]);
|
||||
AddMouseMoveStep(times[1], 400);
|
||||
AddAssert("slider velocity changed", () => !hitObject.DifficultyControlPoint.SliderVelocityBindable.IsDefault);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollWhileDrag()
|
||||
{
|
||||
double[] times = { 300, 500 };
|
||||
float[] positions = { 100, 100 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
addDragStartStep(times[1], positions[1]);
|
||||
// This mouse move is necessary to start drag and capture the input.
|
||||
AddMouseMoveStep(times[1], positions[1] + 50);
|
||||
|
||||
AddStep("scroll playfield", () => manualClock.CurrentTime += 200);
|
||||
AddMouseMoveStep(times[1] + 200, positions[1] + 100);
|
||||
addVertexCheckStep(2, 1, times[1] + 200, positions[1] + 100);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUpdateFromHitObject()
|
||||
{
|
||||
double[] times = { 100, 300 };
|
||||
float[] positions = { 200, 200 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
AddStep("update hit object path", () =>
|
||||
{
|
||||
hitObject.Path = new SliderPath(PathType.PerfectCurve, new[]
|
||||
{
|
||||
Vector2.Zero,
|
||||
new Vector2(100, 100),
|
||||
new Vector2(0, 200),
|
||||
});
|
||||
EditorBeatmap.Update(hitObject);
|
||||
});
|
||||
AddAssert("path is updated", () => getVertices().Count > 2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddVertex()
|
||||
{
|
||||
double[] times = { 100, 700 };
|
||||
float[] positions = { 200, 200 };
|
||||
addBlueprintStep(times, positions, 0.2);
|
||||
|
||||
addAddVertexSteps(500, 150);
|
||||
addVertexCheckStep(3, 1, 500, 150);
|
||||
|
||||
addAddVertexSteps(90, 200);
|
||||
addVertexCheckStep(4, 1, times[0], positions[0]);
|
||||
|
||||
addAddVertexSteps(750, 180);
|
||||
addVertexCheckStep(5, 4, 750, 180);
|
||||
AddAssert("duration is changed", () => Precision.AlmostEquals(hitObject.Duration, 800 - times[0], 1e-3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeleteVertex()
|
||||
{
|
||||
double[] times = { 100, 300, 500 };
|
||||
float[] positions = { 100, 200, 150 };
|
||||
addBlueprintStep(times, positions);
|
||||
|
||||
addDeleteVertexSteps(times[1], positions[1]);
|
||||
addVertexCheckStep(2, 1, times[2], positions[2]);
|
||||
|
||||
// The first vertex cannot be deleted.
|
||||
addDeleteVertexSteps(times[0], positions[0]);
|
||||
addVertexCheckStep(2, 0, times[0], positions[0]);
|
||||
|
||||
addDeleteVertexSteps(times[2], positions[2]);
|
||||
addVertexCheckStep(1, 0, times[0], positions[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVertexResampling()
|
||||
{
|
||||
addBlueprintStep(100, 100, new SliderPath(PathType.PerfectCurve, new[]
|
||||
{
|
||||
Vector2.Zero,
|
||||
new Vector2(100, 100),
|
||||
new Vector2(50, 200),
|
||||
}), 0.5);
|
||||
AddAssert("1 vertex per 1 nested HO", () => getVertices().Count == hitObject.NestedHitObjects.Count);
|
||||
AddAssert("slider path not yet changed", () => hitObject.Path.ControlPoints[0].Type == PathType.PerfectCurve);
|
||||
addAddVertexSteps(150, 150);
|
||||
AddAssert("slider path change to linear", () => hitObject.Path.ControlPoints[0].Type == PathType.Linear);
|
||||
}
|
||||
|
||||
private void addBlueprintStep(double time, float x, SliderPath sliderPath, double velocity) => AddStep("add selection blueprint", () =>
|
||||
{
|
||||
hitObject = new JuiceStream
|
||||
{
|
||||
StartTime = time,
|
||||
X = x,
|
||||
Path = sliderPath,
|
||||
};
|
||||
EditorBeatmap.Difficulty.SliderMultiplier = velocity;
|
||||
EditorBeatmap.Add(hitObject);
|
||||
EditorBeatmap.Update(hitObject);
|
||||
Assert.That(hitObject.Velocity, Is.EqualTo(velocity));
|
||||
AddBlueprint(new JuiceStreamSelectionBlueprint(hitObject));
|
||||
});
|
||||
|
||||
private void addBlueprintStep(double[] times, float[] positions, double velocity = 0.5)
|
||||
{
|
||||
var path = new JuiceStreamPath();
|
||||
for (int i = 1; i < times.Length; i++)
|
||||
path.Add(times[i] - times[0], positions[i] - positions[0]);
|
||||
|
||||
var sliderPath = new SliderPath();
|
||||
path.ConvertToSliderPath(sliderPath, 0, velocity);
|
||||
addBlueprintStep(times[0], positions[0], sliderPath, velocity);
|
||||
}
|
||||
|
||||
private IReadOnlyList<JuiceStreamPathVertex> getVertices() => this.ChildrenOfType<EditablePath>().Single().Vertices;
|
||||
|
||||
private void addVertexCheckStep(int count, int index, double time, float x) => AddAssert($"vertex {index} of {count} at {time}, {x}", () =>
|
||||
{
|
||||
double expectedTime = time - hitObject.StartTime;
|
||||
float expectedX = x - hitObject.OriginalX;
|
||||
var vertices = getVertices();
|
||||
return vertices.Count == count &&
|
||||
Precision.AlmostEquals(vertices[index].Time, expectedTime, 1e-3) &&
|
||||
Precision.AlmostEquals(vertices[index].X, expectedX);
|
||||
});
|
||||
|
||||
private void addDragStartStep(double time, float x)
|
||||
{
|
||||
AddMouseMoveStep(time, x);
|
||||
AddStep("start dragging", () => InputManager.PressButton(MouseButton.Left));
|
||||
}
|
||||
|
||||
private void addDragEndStep() => AddStep("end dragging", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
|
||||
private void addAddVertexSteps(double time, float x)
|
||||
{
|
||||
AddMouseMoveStep(time, x);
|
||||
AddStep("add vertex", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ControlLeft);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
InputManager.ReleaseKey(Key.ControlLeft);
|
||||
});
|
||||
}
|
||||
|
||||
private void addDeleteVertexSteps(double time, float x)
|
||||
{
|
||||
AddMouseMoveStep(time, x);
|
||||
AddStep("delete vertex", () =>
|
||||
{
|
||||
InputManager.PressKey(Key.ShiftLeft);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,289 +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.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class JuiceStreamPathTest
|
||||
{
|
||||
[TestCase(1e3, true, false)]
|
||||
// When the coordinates are large, the slope invariant fails within the specified absolute allowance due to the floating-number precision.
|
||||
[TestCase(1e9, false, false)]
|
||||
// Using discrete values sometimes discover more edge cases.
|
||||
[TestCase(10, true, true)]
|
||||
public void TestRandomInsertSetPosition(double scale, bool checkSlope, bool integralValues)
|
||||
{
|
||||
var rng = new Random(1);
|
||||
var path = new JuiceStreamPath();
|
||||
|
||||
for (int iteration = 0; iteration < 100000; iteration++)
|
||||
{
|
||||
if (rng.Next(10) == 0)
|
||||
path.Clear();
|
||||
|
||||
int vertexCount = path.Vertices.Count;
|
||||
|
||||
switch (rng.Next(2))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
double time = rng.NextDouble() * scale * 2 - scale;
|
||||
if (integralValues)
|
||||
time = Math.Round(time);
|
||||
|
||||
float oldX = path.PositionAtTime(time);
|
||||
int index = path.InsertVertex(time);
|
||||
Assert.That(path.Vertices.Count, Is.EqualTo(vertexCount + 1));
|
||||
Assert.That(path.Vertices[index].Time, Is.EqualTo(time));
|
||||
Assert.That(path.Vertices[index].X, Is.EqualTo(oldX));
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
int index = rng.Next(path.Vertices.Count);
|
||||
double time = path.Vertices[index].Time;
|
||||
float newX = (float)(rng.NextDouble() * scale * 2 - scale);
|
||||
if (integralValues)
|
||||
newX = MathF.Round(newX);
|
||||
|
||||
path.SetVertexPosition(index, newX);
|
||||
Assert.That(path.Vertices.Count, Is.EqualTo(vertexCount));
|
||||
Assert.That(path.Vertices[index].Time, Is.EqualTo(time));
|
||||
Assert.That(path.Vertices[index].X, Is.EqualTo(newX));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertInvariants(path.Vertices);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRemoveVertices()
|
||||
{
|
||||
var path = new JuiceStreamPath();
|
||||
path.Add(10, 5);
|
||||
path.Add(20, -5);
|
||||
|
||||
int removeCount = path.RemoveVertices((v, i) => v.Time == 10 && i == 1);
|
||||
Assert.That(removeCount, Is.EqualTo(1));
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
new JuiceStreamPathVertex(0, 0),
|
||||
new JuiceStreamPathVertex(20, -5)
|
||||
}));
|
||||
|
||||
removeCount = path.RemoveVertices((_, i) => i == 0);
|
||||
Assert.That(removeCount, Is.EqualTo(1));
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
new JuiceStreamPathVertex(20, -5)
|
||||
}));
|
||||
|
||||
removeCount = path.RemoveVertices((_, i) => true);
|
||||
Assert.That(removeCount, Is.EqualTo(1));
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
new JuiceStreamPathVertex()
|
||||
}));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestResampleVertices()
|
||||
{
|
||||
var path = new JuiceStreamPath();
|
||||
path.Add(-100, -10);
|
||||
path.Add(100, 50);
|
||||
path.ResampleVertices(new double[]
|
||||
{
|
||||
-50,
|
||||
0,
|
||||
70,
|
||||
120
|
||||
});
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
new JuiceStreamPathVertex(-100, -10),
|
||||
new JuiceStreamPathVertex(-50, -5),
|
||||
new JuiceStreamPathVertex(0, 0),
|
||||
new JuiceStreamPathVertex(70, 35),
|
||||
new JuiceStreamPathVertex(100, 50),
|
||||
new JuiceStreamPathVertex(100, 50),
|
||||
}));
|
||||
|
||||
path.Clear();
|
||||
path.SetVertexPosition(0, 10);
|
||||
path.ResampleVertices(Array.Empty<double>());
|
||||
Assert.That(path.Vertices, Is.EqualTo(new[]
|
||||
{
|
||||
new JuiceStreamPathVertex(0, 10)
|
||||
}));
|
||||
}
|
||||
|
||||
[TestCase(10)]
|
||||
[TestCase(0.1)]
|
||||
public void TestRandomConvertFromSliderPath(double velocity)
|
||||
{
|
||||
var rng = new Random(1);
|
||||
var path = new JuiceStreamPath();
|
||||
var sliderPath = new SliderPath();
|
||||
|
||||
for (int iteration = 0; iteration < 10000; iteration++)
|
||||
{
|
||||
sliderPath.ControlPoints.Clear();
|
||||
|
||||
do
|
||||
{
|
||||
int start = sliderPath.ControlPoints.Count;
|
||||
|
||||
do
|
||||
{
|
||||
float x = (float)(rng.NextDouble() * 1e3);
|
||||
float y = (float)(rng.NextDouble() * 1e3);
|
||||
sliderPath.ControlPoints.Add(new PathControlPoint(new Vector2(x, y)));
|
||||
} while (rng.Next(2) != 0);
|
||||
|
||||
int length = sliderPath.ControlPoints.Count - start + 1;
|
||||
sliderPath.ControlPoints[start].Type = length <= 2 ? PathType.Linear : length == 3 ? PathType.PerfectCurve : PathType.Bezier;
|
||||
} while (rng.Next(3) != 0);
|
||||
|
||||
if (rng.Next(5) == 0)
|
||||
sliderPath.ExpectedDistance.Value = rng.NextDouble() * 3e3;
|
||||
else
|
||||
sliderPath.ExpectedDistance.Value = null;
|
||||
|
||||
path.ConvertFromSliderPath(sliderPath, velocity);
|
||||
Assert.That(path.Vertices[0].Time, Is.EqualTo(0));
|
||||
Assert.That(path.Duration * velocity, Is.EqualTo(sliderPath.Distance).Within(1e-3));
|
||||
assertInvariants(path.Vertices);
|
||||
|
||||
double[] sampleTimes = Enumerable.Range(0, 10)
|
||||
.Select(_ => rng.NextDouble() * sliderPath.Distance / velocity)
|
||||
.ToArray();
|
||||
|
||||
foreach (double time in sampleTimes)
|
||||
{
|
||||
float expected = sliderPath.PositionAt(time * velocity / sliderPath.Distance).X;
|
||||
Assert.That(path.PositionAtTime(time), Is.EqualTo(expected).Within(1e-3));
|
||||
}
|
||||
|
||||
path.ResampleVertices(sampleTimes);
|
||||
assertInvariants(path.Vertices);
|
||||
|
||||
foreach (double time in sampleTimes)
|
||||
{
|
||||
float expected = sliderPath.PositionAt(time * velocity / sliderPath.Distance).X;
|
||||
Assert.That(path.PositionAtTime(time), Is.EqualTo(expected).Within(1e-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRandomConvertToSliderPath()
|
||||
{
|
||||
var rng = new Random(1);
|
||||
var path = new JuiceStreamPath();
|
||||
var sliderPath = new SliderPath();
|
||||
|
||||
for (int iteration = 0; iteration < 10000; iteration++)
|
||||
{
|
||||
path.Clear();
|
||||
|
||||
do
|
||||
{
|
||||
double time = rng.NextDouble() * 1e3;
|
||||
float x = (float)(rng.NextDouble() * 1e3);
|
||||
path.Add(time, x);
|
||||
} while (rng.Next(5) != 0);
|
||||
|
||||
float sliderStartY = (float)(rng.NextDouble() * JuiceStreamPath.OSU_PLAYFIELD_HEIGHT);
|
||||
|
||||
double requiredVelocity = path.ComputeRequiredVelocity();
|
||||
double velocity = Math.Clamp(requiredVelocity, 1, 100);
|
||||
|
||||
path.ConvertToSliderPath(sliderPath, sliderStartY, velocity);
|
||||
|
||||
foreach (var point in sliderPath.ControlPoints)
|
||||
{
|
||||
Assert.That(point.Type, Is.EqualTo(PathType.Linear).Or.Null);
|
||||
Assert.That(sliderStartY + point.Position.Y, Is.InRange(0, JuiceStreamPath.OSU_PLAYFIELD_HEIGHT));
|
||||
}
|
||||
|
||||
Assert.That(sliderPath.ControlPoints[0].Position.X, Is.EqualTo(path.Vertices[0].X));
|
||||
|
||||
// The path is preserved only if required velocity is used.
|
||||
if (velocity < requiredVelocity) continue;
|
||||
|
||||
Assert.That(sliderPath.Distance / velocity, Is.EqualTo(path.Duration).Within(1e-3));
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
double time = rng.NextDouble() * path.Duration;
|
||||
float expected = path.PositionAtTime(time);
|
||||
Assert.That(sliderPath.PositionAt(time * velocity / sliderPath.Distance).X, Is.EqualTo(expected).Within(3e-3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInvalidation()
|
||||
{
|
||||
var path = new JuiceStreamPath();
|
||||
Assert.That(path.InvalidationID, Is.EqualTo(1));
|
||||
int previousId = path.InvalidationID;
|
||||
|
||||
path.InsertVertex(10);
|
||||
checkNewId();
|
||||
|
||||
path.SetVertexPosition(1, 5);
|
||||
checkNewId();
|
||||
|
||||
path.Add(20, 0);
|
||||
checkNewId();
|
||||
|
||||
path.RemoveVertices((v, _) => v.Time == 20);
|
||||
checkNewId();
|
||||
|
||||
path.ResampleVertices(new double[] { 5, 10, 15 });
|
||||
checkNewId();
|
||||
|
||||
path.Clear();
|
||||
checkNewId();
|
||||
|
||||
path.ConvertFromSliderPath(new SliderPath(), 1);
|
||||
checkNewId();
|
||||
|
||||
void checkNewId()
|
||||
{
|
||||
Assert.That(path.InvalidationID, Is.Not.EqualTo(previousId));
|
||||
previousId = path.InvalidationID;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertInvariants(IReadOnlyList<JuiceStreamPathVertex> vertices)
|
||||
{
|
||||
Assert.That(vertices, Is.Not.Empty);
|
||||
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
Assert.That(double.IsFinite(vertices[i].Time));
|
||||
Assert.That(float.IsFinite(vertices[i].X));
|
||||
}
|
||||
|
||||
for (int i = 1; i < vertices.Count; i++)
|
||||
{
|
||||
Assert.That(vertices[i].Time, Is.GreaterThanOrEqualTo(vertices[i - 1].Time));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,120 +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.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||
{
|
||||
[TestFixture]
|
||||
public class CatchModMirrorTest
|
||||
{
|
||||
[Test]
|
||||
public void TestModMirror()
|
||||
{
|
||||
IBeatmap original = createBeatmap(false);
|
||||
IBeatmap mirrored = createBeatmap(true);
|
||||
|
||||
assertEffectivePositionsMirrored(original, mirrored);
|
||||
}
|
||||
|
||||
private static IBeatmap createBeatmap(bool withMirrorMod)
|
||||
{
|
||||
var beatmap = createRawBeatmap();
|
||||
var mirrorMod = new CatchModMirror();
|
||||
|
||||
var beatmapProcessor = new CatchBeatmapProcessor(beatmap);
|
||||
beatmapProcessor.PreProcess();
|
||||
|
||||
foreach (var hitObject in beatmap.HitObjects)
|
||||
hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
beatmapProcessor.PostProcess();
|
||||
|
||||
if (withMirrorMod)
|
||||
mirrorMod.ApplyToBeatmap(beatmap);
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private static IBeatmap createRawBeatmap() => new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new Fruit
|
||||
{
|
||||
OriginalX = 150,
|
||||
StartTime = 0
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
OriginalX = 450,
|
||||
StartTime = 500
|
||||
},
|
||||
new JuiceStream
|
||||
{
|
||||
OriginalX = 250,
|
||||
Path = new SliderPath
|
||||
{
|
||||
ControlPoints =
|
||||
{
|
||||
new PathControlPoint(new Vector2(-100, 1)),
|
||||
new PathControlPoint(new Vector2(0, 2)),
|
||||
new PathControlPoint(new Vector2(100, 3)),
|
||||
new PathControlPoint(new Vector2(0, 4))
|
||||
}
|
||||
},
|
||||
StartTime = 1000,
|
||||
},
|
||||
new BananaShower
|
||||
{
|
||||
StartTime = 5000,
|
||||
Duration = 5000
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static void assertEffectivePositionsMirrored(IBeatmap original, IBeatmap mirrored)
|
||||
{
|
||||
if (original.HitObjects.Count != mirrored.HitObjects.Count)
|
||||
Assert.Fail($"Top-level object count mismatch (original: {original.HitObjects.Count}, mirrored: {mirrored.HitObjects.Count})");
|
||||
|
||||
for (int i = 0; i < original.HitObjects.Count; ++i)
|
||||
{
|
||||
var originalObject = (CatchHitObject)original.HitObjects[i];
|
||||
var mirroredObject = (CatchHitObject)mirrored.HitObjects[i];
|
||||
|
||||
// banana showers themselves are exempt, as we only really care about their nested bananas' positions.
|
||||
if (!effectivePositionMirrored(originalObject, mirroredObject) && !(originalObject is BananaShower))
|
||||
Assert.Fail($"{originalObject.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalObject, mirroredObject)})");
|
||||
|
||||
if (originalObject.NestedHitObjects.Count != mirroredObject.NestedHitObjects.Count)
|
||||
Assert.Fail($"{originalObject.GetType().Name} nested object count mismatch (original: {originalObject.NestedHitObjects.Count}, mirrored: {mirroredObject.NestedHitObjects.Count})");
|
||||
|
||||
for (int j = 0; j < originalObject.NestedHitObjects.Count; ++j)
|
||||
{
|
||||
var originalNested = (CatchHitObject)originalObject.NestedHitObjects[j];
|
||||
var mirroredNested = (CatchHitObject)mirroredObject.NestedHitObjects[j];
|
||||
|
||||
if (!effectivePositionMirrored(originalNested, mirroredNested))
|
||||
Assert.Fail($"{originalObject.GetType().Name}'s nested {originalNested.GetType().Name} at time {originalObject.StartTime} is not mirrored ({printEffectivePositions(originalNested, mirroredNested)})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string printEffectivePositions(CatchHitObject original, CatchHitObject mirrored)
|
||||
=> $"original X: {original.EffectiveX}, mirrored X is: {mirrored.EffectiveX}, mirrored X should be: {CatchPlayfield.WIDTH - original.EffectiveX}";
|
||||
|
||||
private static bool effectivePositionMirrored(CatchHitObject original, CatchHitObject mirrored)
|
||||
=> Precision.AlmostEquals(original.EffectiveX, CatchPlayfield.WIDTH - mirrored.EffectiveX);
|
||||
}
|
||||
}
|
@ -1,110 +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.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||
{
|
||||
public class TestSceneCatchModNoScope : ModTestScene
|
||||
{
|
||||
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||
|
||||
[Test]
|
||||
public void TestVisibleDuringBreak()
|
||||
{
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new CatchModNoScope
|
||||
{
|
||||
HiddenComboCount = { Value = 0 },
|
||||
},
|
||||
Autoplay = true,
|
||||
PassCondition = () => true,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.CENTER_X,
|
||||
StartTime = 1000,
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.CENTER_X,
|
||||
StartTime = 5000,
|
||||
}
|
||||
},
|
||||
Breaks = new List<BreakPeriod>
|
||||
{
|
||||
new BreakPeriod(2000, 4000),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AddUntilStep("wait for catcher to hide", () => catcherAlphaAlmostEquals(0));
|
||||
AddUntilStep("wait for start of break", isBreak);
|
||||
AddUntilStep("wait for catcher to show", () => catcherAlphaAlmostEquals(1));
|
||||
AddUntilStep("wait for end of break", () => !isBreak());
|
||||
AddUntilStep("wait for catcher to hide", () => catcherAlphaAlmostEquals(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestVisibleAfterComboBreak()
|
||||
{
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new CatchModNoScope
|
||||
{
|
||||
HiddenComboCount = { Value = 2 },
|
||||
},
|
||||
Autoplay = true,
|
||||
PassCondition = () => true,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new Fruit
|
||||
{
|
||||
X = 0,
|
||||
StartTime = 1000,
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.CENTER_X,
|
||||
StartTime = 3000,
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.WIDTH,
|
||||
StartTime = 5000,
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AddAssert("catcher must start visible", () => catcherAlphaAlmostEquals(1));
|
||||
AddUntilStep("wait for combo", () => Player.ScoreProcessor.Combo.Value >= 2);
|
||||
AddAssert("catcher must dim after combo", () => !catcherAlphaAlmostEquals(1));
|
||||
AddStep("break combo", () => Player.ScoreProcessor.Combo.Value = 0);
|
||||
AddUntilStep("wait for catcher to show", () => catcherAlphaAlmostEquals(1));
|
||||
}
|
||||
|
||||
private bool isBreak() => Player.IsBreakTime.Value;
|
||||
|
||||
private bool catcherAlphaAlmostEquals(float alpha)
|
||||
{
|
||||
var playfield = (CatchPlayfield)Player.DrawableRuleset.Playfield;
|
||||
return Precision.AlmostEquals(playfield.CatcherArea.Alpha, alpha);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +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 NUnit.Framework;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||
{
|
||||
public class TestSceneCatchModPerfect : ModPerfectTestScene
|
||||
{
|
||||
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||
|
||||
public TestSceneCatchModPerfect()
|
||||
: base(new CatchModPerfect())
|
||||
{
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestBananaShower(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new BananaShower { StartTime = 1000, EndTime = 3000 }, false), shouldMiss);
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestFruit(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Fruit { StartTime = 1000 }), shouldMiss);
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestJuiceStream(bool shouldMiss)
|
||||
{
|
||||
var stream = new JuiceStream
|
||||
{
|
||||
StartTime = 1000,
|
||||
Path = new SliderPath(PathType.Linear, new[]
|
||||
{
|
||||
Vector2.Zero,
|
||||
new Vector2(100, 0),
|
||||
})
|
||||
};
|
||||
|
||||
CreateHitObjectTest(new HitObjectTestData(stream), shouldMiss);
|
||||
}
|
||||
|
||||
// We only care about testing misses, hits are tested via JuiceStream
|
||||
[TestCase(true)]
|
||||
public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss);
|
||||
|
||||
// We only care about testing misses, hits are tested via JuiceStream
|
||||
[TestCase(true)]
|
||||
public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss);
|
||||
}
|
||||
}
|
@ -1,84 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Mods;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests.Mods
|
||||
{
|
||||
public class TestSceneCatchModRelax : ModTestScene
|
||||
{
|
||||
protected override Ruleset CreatePlayerRuleset() => new CatchRuleset();
|
||||
|
||||
[Test]
|
||||
public void TestModRelax() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new CatchModRelax(),
|
||||
Autoplay = false,
|
||||
PassCondition = passCondition,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.CENTER_X,
|
||||
StartTime = 0
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
X = 0,
|
||||
StartTime = 1000
|
||||
},
|
||||
new Fruit
|
||||
{
|
||||
X = CatchPlayfield.WIDTH,
|
||||
StartTime = 2000
|
||||
},
|
||||
new JuiceStream
|
||||
{
|
||||
X = CatchPlayfield.CENTER_X,
|
||||
StartTime = 3000,
|
||||
Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 })
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
private bool passCondition()
|
||||
{
|
||||
var playfield = this.ChildrenOfType<CatchPlayfield>().Single();
|
||||
|
||||
switch (Player.ScoreProcessor.Combo.Value)
|
||||
{
|
||||
case 0:
|
||||
InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.BottomLeft);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.BottomRight);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
InputManager.MoveMouseTo(playfield.ScreenSpaceDrawQuad.Centre);
|
||||
break;
|
||||
}
|
||||
|
||||
return Player.ScoreProcessor.Combo.Value >= 6;
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB |
@ -1,2 +0,0 @@
|
||||
[General]
|
||||
// no version specified means v1
|
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 923 B |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |