mirror of
https://github.com/ppy/osu.git
synced 2026-05-13 21:13:39 +08:00
Compare commits
1589 Commits
2019.508.0
...
2019.628.0
@@ -0,0 +1 @@
|
||||
custom: https://osu.ppy.sh/home/support
|
||||
+6
-3
@@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (catch)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="CatchRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Catch.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+6
-3
@@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (mania)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="ManiaRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Mania.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+6
-3
@@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (osu!)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="OsuRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Osu.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+6
-3
@@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (taiko)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="TaikoRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Taiko.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,20 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament" type="DotNetProject" factoryName=".NET Project" folderName="Tournament">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="--tournament" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Desktop/osu.Desktop.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Tournament">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.1/osu.Game.Tournament.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project" folderName="osu!">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||
|
||||
+6
-3
@@ -1,17 +1,20 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="VisualTests" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="osu! (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="osu!">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Tests/osu.Game.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<method />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
Vendored
+107
-37
@@ -1,41 +1,6 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "VisualTests (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "VisualTests (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"configurations": [{
|
||||
"name": "osu! (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
@@ -69,6 +34,111 @@
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "osu! (Tests, Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
}, {
|
||||
"name": "osu! (Tests, Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.2/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Tests, Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Tests, Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Cake: Debug Script",
|
||||
"type": "coreclr",
|
||||
@@ -84,4 +154,4 @@
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Vendored
+31
-2
@@ -2,8 +2,7 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"tasks": [{
|
||||
"label": "Build osu! (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
@@ -65,6 +64,36 @@
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Build tournament tests (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
}, {
|
||||
"label": "Build tournament tests (Release)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests",
|
||||
"/p:Configuration=Release",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Restore (netcoreapp2.2)",
|
||||
"type": "shell",
|
||||
|
||||
@@ -10,6 +10,8 @@ This project is still heavily under development, but is in a state where users a
|
||||
|
||||
We are accepting bug reports (please report with as much detail as possible). Feature requests are welcome as long as you read and understand the contribution guidelines listed below.
|
||||
|
||||
Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh/home/changelog).
|
||||
|
||||
## Requirements
|
||||
|
||||
- A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed.
|
||||
@@ -20,17 +22,24 @@ We are accepting bug reports (please report with as much detail as possible). Fe
|
||||
|
||||
### Releases
|
||||
|
||||
If you are not interested in developing the game, please head over to the [releases](https://github.com/ppy/osu/releases) to download a precompiled build with automatic updating enabled.
|
||||

|
||||
|
||||
- Windows (x64) users should download and run `install.exe`.
|
||||
- macOS users (10.12 "Sierra" and higher) should download and run `osu.app.zip`.
|
||||
- iOS users can join the [TestFlight beta program](https://t.co/xQJmHkfC18).
|
||||
If you are not interested in developing the game, you can still consume our [binary releases](https://github.com/ppy/osu/releases).
|
||||
|
||||
**Latest build:**
|
||||
|
||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) |
|
||||
| ------------- | ------------- |
|
||||
|
||||
- **Linux** users are recommended to self-compile until we have official deployment in place.
|
||||
- **iOS** users can join the [TestFlight beta program](https://t.co/PasE1zrHhw) (note that due to high demand this is regularly full).
|
||||
- **Android** users can self-compile, and expect a public beta soon.
|
||||
|
||||
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
||||
|
||||
### Downloading the source code
|
||||
|
||||
Clone the repository **including submodules**:
|
||||
Clone the repository:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/ppy/osu
|
||||
@@ -45,7 +54,7 @@ git pull
|
||||
|
||||
### Building
|
||||
|
||||
Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided below.
|
||||
Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided [below](#contributing).
|
||||
|
||||
> Visual Studio Code users must run the `Restore` task before any build attempt.
|
||||
|
||||
@@ -63,7 +72,7 @@ If the build fails, try to restore nuget packages with `dotnet restore`.
|
||||
|
||||
On Linux, the environment variable `LD_LIBRARY_PATH` must point to the build directory, located at `osu.Desktop/bin/Debug/$NETCORE_VERSION`.
|
||||
|
||||
`$NETCORE_VERSION` is the version of .NET Core SDK. You can have it with `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`.
|
||||
`$NETCORE_VERSION` is the version of the targeted .NET Core SDK. You can check it by running `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`.
|
||||
|
||||
For example, you can run osu! with the following command:
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ platform :ios do
|
||||
changelog.gsub!('$BUILD_ID', options[:build])
|
||||
|
||||
pilot(
|
||||
wait_processing_interval: 900,
|
||||
wait_processing_interval: 1800,
|
||||
changelog: changelog,
|
||||
ipa: './osu.iOS/bin/iPhone/Release/osu.iOS.ipa'
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Desktop.Overlays;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osuTK.Input;
|
||||
@@ -56,7 +55,7 @@ namespace osu.Desktop
|
||||
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v =>
|
||||
{
|
||||
Add(v);
|
||||
v.State = Visibility.Visible;
|
||||
v.Show();
|
||||
});
|
||||
|
||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
|
||||
@@ -74,13 +73,11 @@ namespace osu.Desktop
|
||||
{
|
||||
case Intro _:
|
||||
case MainMenu _:
|
||||
if (versionManager != null)
|
||||
versionManager.State = Visibility.Visible;
|
||||
versionManager?.Show();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (versionManager != null)
|
||||
versionManager.State = Visibility.Hidden;
|
||||
versionManager?.Hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -25,15 +23,13 @@ namespace osu.Desktop.Overlays
|
||||
private OsuConfigManager config;
|
||||
private OsuGameBase game;
|
||||
private NotificationOverlay notificationOverlay;
|
||||
private GameHost host;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host)
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config)
|
||||
{
|
||||
notificationOverlay = notification;
|
||||
this.config = config;
|
||||
this.game = game;
|
||||
this.host = host;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.BottomCentre;
|
||||
@@ -65,7 +61,7 @@ namespace osu.Desktop.Overlays
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Colour = DebugUtils.IsDebug ? colours.Red : Color4.White,
|
||||
Colour = DebugUtils.IsDebugBuild ? colours.Red : Color4.White,
|
||||
Text = game.Version
|
||||
},
|
||||
}
|
||||
@@ -102,27 +98,31 @@ namespace osu.Desktop.Overlays
|
||||
|
||||
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
|
||||
if (!string.IsNullOrEmpty(lastVersion))
|
||||
notificationOverlay.Post(new UpdateCompleteNotification(version, host.OpenUrlExternally));
|
||||
notificationOverlay.Post(new UpdateCompleteNotification(version));
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateCompleteNotification : SimpleNotification
|
||||
{
|
||||
public UpdateCompleteNotification(string version, Action<string> openUrl = null)
|
||||
private readonly string version;
|
||||
|
||||
public UpdateCompleteNotification(string version)
|
||||
{
|
||||
this.version = version;
|
||||
Text = $"You are now running osu!lazer {version}.\nClick to see what's new!";
|
||||
Icon = FontAwesome.Solid.CheckSquare;
|
||||
Activated = delegate
|
||||
{
|
||||
openUrl?.Invoke($"https://osu.ppy.sh/home/changelog/lazer/{version}");
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
private void load(OsuColour colours, ChangelogOverlay changelog)
|
||||
{
|
||||
Icon = FontAwesome.Solid.CheckSquare;
|
||||
IconBackgound.Colour = colours.BlueDark;
|
||||
|
||||
Activated = delegate
|
||||
{
|
||||
changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using osu.Framework.Development;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Tournament;
|
||||
|
||||
namespace osu.Desktop
|
||||
{
|
||||
@@ -46,6 +47,10 @@ namespace osu.Desktop
|
||||
default:
|
||||
host.Run(new OsuGameDesktop(args));
|
||||
break;
|
||||
|
||||
case "--tournament":
|
||||
host.Run(new TournamentGame());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -169,23 +167,19 @@ namespace osu.Desktop.Updater
|
||||
|
||||
private class SquirrelLogger : Splat.ILogger, IDisposable
|
||||
{
|
||||
private readonly string path;
|
||||
private readonly object locker = new object();
|
||||
public LogLevel Level { get; set; } = LogLevel.Info;
|
||||
|
||||
public SquirrelLogger()
|
||||
{
|
||||
var file = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? Directory.GetCurrentDirectory()), "SquirrelSetupUpdater.log");
|
||||
if (File.Exists(file)) File.Delete(file);
|
||||
path = file;
|
||||
}
|
||||
private Logger logger;
|
||||
|
||||
public void Write(string message, LogLevel logLevel)
|
||||
{
|
||||
if (logLevel < Level)
|
||||
return;
|
||||
|
||||
lock (locker) File.AppendAllText(path, message + "\r\n");
|
||||
if (logger == null)
|
||||
logger = Logger.GetLogger("updater");
|
||||
|
||||
logger.Add(message);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<StartupObject>osu.Desktop.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<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" />
|
||||
|
||||
+4
-4
@@ -13,21 +13,21 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class TestCaseAutoJuiceStream : PlayerTestCase
|
||||
public class TestSceneAutoJuiceStream : PlayerTestScene
|
||||
{
|
||||
public TestCaseAutoJuiceStream()
|
||||
public TestSceneAutoJuiceStream()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
+4
-4
@@ -13,7 +13,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseBananaShower : PlayerTestCase
|
||||
public class TestSceneBananaShower : PlayerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -24,19 +24,19 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
typeof(DrawableCatchRuleset),
|
||||
};
|
||||
|
||||
public TestCaseBananaShower()
|
||||
public TestSceneBananaShower()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseCatchPlayer : PlayerTestCase
|
||||
public class TestSceneCatchPlayer : PlayerTestScene
|
||||
{
|
||||
public TestCaseCatchPlayer()
|
||||
public TestSceneCatchPlayer()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
+4
-4
@@ -9,21 +9,21 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseCatchStacker : PlayerTestCase
|
||||
public class TestSceneCatchStacker : PlayerTestScene
|
||||
{
|
||||
public TestCaseCatchStacker()
|
||||
public TestSceneCatchStacker()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Tests.Visual;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCatcher : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CatcherSprite),
|
||||
};
|
||||
|
||||
private readonly Container container;
|
||||
|
||||
public TestSceneCatcher()
|
||||
{
|
||||
Child = container = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddStep("show default catcher implementation", () => { container.Child = new CatcherSprite(); });
|
||||
|
||||
AddStep("show custom catcher implementation", () =>
|
||||
{
|
||||
container.Child = new CatchCustomSkinSourceContainer
|
||||
{
|
||||
Child = new CatcherSprite()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private class CatcherCustomSkin : Container
|
||||
{
|
||||
public CatcherCustomSkin()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Blue
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = "custom"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Cached(typeof(ISkinSource))]
|
||||
private class CatchCustomSkinSourceContainer : Container, ISkinSource
|
||||
{
|
||||
public event Action SourceChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
switch (componentName)
|
||||
{
|
||||
case "Play/Catch/fruit-catcher-idle":
|
||||
return new CatcherCustomSkin();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SampleChannel GetSample(string sampleName) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
public Texture GetTexture(string componentName) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration =>
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -13,7 +13,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseCatcherArea : OsuTestCase
|
||||
public class TestSceneCatcherArea : OsuTestScene
|
||||
{
|
||||
private RulesetInfo catchRuleset;
|
||||
private TestCatcherArea catcherArea;
|
||||
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
typeof(CatcherArea),
|
||||
};
|
||||
|
||||
public TestCaseCatcherArea()
|
||||
public TestSceneCatcherArea()
|
||||
{
|
||||
AddSliderStep<float>("CircleSize", 0, 8, 5, createCatcher);
|
||||
AddToggleStep("Hyperdash", t => catcherArea.ToggleHyperDash(t));
|
||||
+2
-2
@@ -15,7 +15,7 @@ using osuTK;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseFruitObjects : OsuTestCase
|
||||
public class TestSceneFruitObjects : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
typeof(Pulp),
|
||||
};
|
||||
|
||||
public TestCaseFruitObjects()
|
||||
public TestSceneFruitObjects()
|
||||
{
|
||||
Add(new GridContainer
|
||||
{
|
||||
+6
-7
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Tests.Visual;
|
||||
@@ -10,26 +9,26 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseHyperDash : PlayerTestCase
|
||||
public class TestSceneHyperDash : PlayerTestScene
|
||||
{
|
||||
public TestCaseHyperDash()
|
||||
public TestSceneHyperDash()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
[Test]
|
||||
public void TestHyperDash()
|
||||
{
|
||||
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
Ruleset = ruleset.RulesetInfo,
|
||||
Ruleset = ruleset,
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f }
|
||||
}
|
||||
};
|
||||
@@ -2,8 +2,8 @@
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||
{
|
||||
if (beatmap.HitObjects.Count == 0)
|
||||
return new CatchDifficultyAttributes { Mods = mods };
|
||||
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
|
||||
|
||||
// this is the same as osu!, so there's potential to share the implementation... maybe
|
||||
double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||
@@ -41,7 +41,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor,
|
||||
Mods = mods,
|
||||
ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0,
|
||||
MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet))
|
||||
MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)),
|
||||
Skills = skills
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,33 +58,20 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
|
||||
CatchHitObject lastObject = null;
|
||||
|
||||
foreach (var hitObject in beatmap.HitObjects.OfType<CatchHitObject>())
|
||||
// In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream.
|
||||
foreach (var hitObject in beatmap.HitObjects
|
||||
.SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects : new[] { obj })
|
||||
.Cast<CatchHitObject>()
|
||||
.OrderBy(x => x.StartTime))
|
||||
{
|
||||
if (lastObject == null)
|
||||
{
|
||||
lastObject = hitObject;
|
||||
// We want to only consider fruits that contribute to the combo.
|
||||
if (hitObject is BananaShower || hitObject is TinyDroplet)
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (hitObject)
|
||||
{
|
||||
// We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations.
|
||||
case Fruit fruit:
|
||||
yield return new CatchDifficultyHitObject(fruit, lastObject, clockRate, halfCatchWidth);
|
||||
if (lastObject != null)
|
||||
yield return new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatchWidth);
|
||||
|
||||
lastObject = hitObject;
|
||||
break;
|
||||
|
||||
case JuiceStream _:
|
||||
foreach (var nested in hitObject.NestedHitObjects.OfType<CatchHitObject>().Where(o => !(o is TinyDroplet)))
|
||||
{
|
||||
yield return new CatchDifficultyHitObject(nested, lastObject, clockRate, halfCatchWidth);
|
||||
|
||||
lastObject = nested;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
lastObject = hitObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,13 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
float positionChange = Math.Abs(lastPosition - h.X);
|
||||
double timeAvailable = h.StartTime - lastTime;
|
||||
|
||||
//So we can either make it there without a dash or not.
|
||||
double speedRequired = positionChange / timeAvailable;
|
||||
// So we can either make it there without a dash or not.
|
||||
// If positionChange is 0, we don't need to move, so speedRequired should also be 0 (could be NaN if timeAvailable is 0 too)
|
||||
// The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour.
|
||||
double speedRequired = positionChange == 0 ? 0 : positionChange / timeAvailable;
|
||||
|
||||
bool dashRequired = speedRequired > movement_speed && h.StartTime != 0;
|
||||
bool dashRequired = speedRequired > movement_speed;
|
||||
bool impossibleJump = speedRequired > movement_speed * 2;
|
||||
|
||||
// todo: get correct catcher size, based on difficulty CS.
|
||||
const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f;
|
||||
@@ -59,9 +62,8 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
return;
|
||||
}
|
||||
|
||||
if (h is Banana)
|
||||
if (impossibleJump)
|
||||
{
|
||||
// auto bananas unrealistically warp to catch 100% combo.
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
|
||||
}
|
||||
else if (h.HyperDash)
|
||||
|
||||
@@ -6,8 +6,6 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
@@ -141,7 +139,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
caughtFruit = new Container<DrawableHitObject>
|
||||
{
|
||||
@@ -212,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
|
||||
}
|
||||
|
||||
private Sprite createCatcherSprite() => new CatcherSprite();
|
||||
private Drawable createCatcherSprite() => new CatcherSprite();
|
||||
|
||||
/// <summary>
|
||||
/// Add a caught fruit to the catcher's stack.
|
||||
@@ -379,8 +377,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1);
|
||||
|
||||
// Correct overshooting.
|
||||
if (hyperDashDirection > 0 && hyperDashTargetPosition < X ||
|
||||
hyperDashDirection < 0 && hyperDashTargetPosition > X)
|
||||
if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) ||
|
||||
(hyperDashDirection < 0 && hyperDashTargetPosition > X))
|
||||
{
|
||||
X = hyperDashTargetPosition;
|
||||
SetHyperDashState();
|
||||
@@ -444,23 +442,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
fruit.Expire();
|
||||
}
|
||||
|
||||
private class CatcherSprite : Sprite
|
||||
{
|
||||
public CatcherSprite()
|
||||
{
|
||||
Size = new Vector2(CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(-0.02f, 0.06f) * CATCHER_SIZE;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// 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.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherSprite : CompositeDrawable
|
||||
{
|
||||
public CatcherSprite()
|
||||
{
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(-0.02f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new SkinnableSprite(@"Play/Catch/fruit-catcher-idle")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,12 +8,12 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public abstract class ManiaInputTestCase : OsuTestCase
|
||||
public abstract class ManiaInputTestScene : OsuTestScene
|
||||
{
|
||||
private readonly Container<Drawable> content;
|
||||
protected override Container<Drawable> Content => content ?? base.Content;
|
||||
|
||||
protected ManiaInputTestCase(int keys)
|
||||
protected ManiaInputTestScene(int keys)
|
||||
{
|
||||
base.Content.Add(content = new LocalInputManager(keys));
|
||||
}
|
||||
+2
-2
@@ -20,14 +20,14 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[Cached(Type = typeof(IManiaHitObjectComposer))]
|
||||
public abstract class ManiaPlacementBlueprintTestCase : PlacementBlueprintTestCase, IManiaHitObjectComposer
|
||||
public abstract class ManiaPlacementBlueprintTestScene : PlacementBlueprintTestScene, IManiaHitObjectComposer
|
||||
{
|
||||
private readonly Column column;
|
||||
|
||||
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||
|
||||
protected ManiaPlacementBlueprintTestCase()
|
||||
protected ManiaPlacementBlueprintTestScene()
|
||||
{
|
||||
Add(column = new Column(0)
|
||||
{
|
||||
+2
-2
@@ -13,14 +13,14 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[Cached(Type = typeof(IManiaHitObjectComposer))]
|
||||
public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase, IManiaHitObjectComposer
|
||||
public abstract class ManiaSelectionBlueprintTestScene : SelectionBlueprintTestScene, IManiaHitObjectComposer
|
||||
{
|
||||
[Cached(Type = typeof(IAdjustableClock))]
|
||||
private readonly IAdjustableClock clock = new StopwatchClock();
|
||||
|
||||
private readonly Column column;
|
||||
|
||||
protected ManiaSelectionBlueprintTestCase()
|
||||
protected ManiaSelectionBlueprintTestScene()
|
||||
{
|
||||
Add(column = new Column(0)
|
||||
{
|
||||
+1
-1
@@ -12,7 +12,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseAutoGeneration : OsuTestCase
|
||||
public class TestSceneAutoGeneration : OsuTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestSingleNote()
|
||||
+2
-2
@@ -22,7 +22,7 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseColumn : ManiaInputTestCase
|
||||
public class TestSceneColumn : ManiaInputTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
|
||||
private readonly List<Column> columns = new List<Column>();
|
||||
|
||||
public TestCaseColumn()
|
||||
public TestSceneColumn()
|
||||
: base(2)
|
||||
{
|
||||
}
|
||||
+2
-2
@@ -11,11 +11,11 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditor : EditorTestCase
|
||||
public class TestSceneEditor : EditorTestScene
|
||||
{
|
||||
private readonly Bindable<ManiaScrollingDirection> direction = new Bindable<ManiaScrollingDirection>();
|
||||
|
||||
public TestCaseEditor()
|
||||
public TestSceneEditor()
|
||||
: base(new ManiaRuleset())
|
||||
{
|
||||
AddStep("upwards scroll", () => direction.Value = ManiaScrollingDirection.Up);
|
||||
+1
-1
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class TestCaseHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestCase
|
||||
public class TestSceneHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject);
|
||||
protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint();
|
||||
+2
-2
@@ -15,14 +15,14 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class TestCaseHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestCase
|
||||
public class TestSceneHoldNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene
|
||||
{
|
||||
private readonly DrawableHoldNote drawableObject;
|
||||
|
||||
protected override Container<Drawable> Content => content ?? base.Content;
|
||||
private readonly Container content;
|
||||
|
||||
public TestCaseHoldNoteSelectionBlueprint()
|
||||
public TestSceneHoldNoteSelectionBlueprint()
|
||||
{
|
||||
var holdNote = new HoldNote { Column = 0, Duration = 1000 };
|
||||
holdNote.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
+1
-1
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class TestCaseNotePlacementBlueprint : ManiaPlacementBlueprintTestCase
|
||||
public class TestSceneNotePlacementBlueprint : ManiaPlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject);
|
||||
protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint();
|
||||
+2
-2
@@ -15,14 +15,14 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class TestCaseNoteSelectionBlueprint : ManiaSelectionBlueprintTestCase
|
||||
public class TestSceneNoteSelectionBlueprint : ManiaSelectionBlueprintTestScene
|
||||
{
|
||||
private readonly DrawableNote drawableObject;
|
||||
|
||||
protected override Container<Drawable> Content => content ?? base.Content;
|
||||
private readonly Container content;
|
||||
|
||||
public TestCaseNoteSelectionBlueprint()
|
||||
public TestSceneNoteSelectionBlueprint()
|
||||
{
|
||||
var note = new Note { Column = 0 };
|
||||
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
+3
-3
@@ -11,10 +11,10 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@@ -27,7 +27,7 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseNotes : OsuTestCase
|
||||
public class TestSceneNotes : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
content = new Container { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
},
|
||||
new SpriteText
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
+2
-2
@@ -22,7 +22,7 @@ using osuTK;
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseStage : ManiaInputTestCase
|
||||
public class TestSceneStage : ManiaInputTestScene
|
||||
{
|
||||
private const int columns = 4;
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
|
||||
private FillFlowContainer<ScrollingTestContainer> fill;
|
||||
|
||||
public TestCaseStage()
|
||||
public TestSceneStage()
|
||||
: base(columns)
|
||||
{
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||
{
|
||||
if (beatmap.HitObjects.Count == 0)
|
||||
return new ManiaDifficultyAttributes { Mods = mods };
|
||||
return new ManiaDifficultyAttributes { Mods = mods, Skills = skills };
|
||||
|
||||
return new ManiaDifficultyAttributes
|
||||
{
|
||||
@@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
||||
Mods = mods,
|
||||
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||
GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate,
|
||||
Skills = skills
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditor : EditorTestCase
|
||||
public class TestSceneEditor : EditorTestScene
|
||||
{
|
||||
public TestCaseEditor()
|
||||
public TestSceneEditor()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseGameplayCursor : OsuTestCase, IProvideCursor
|
||||
public class TestSceneGameplayCursor : OsuTestScene, IProvideCursor
|
||||
{
|
||||
private GameplayCursorContainer cursorContainer;
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseHitCircle : OsuTestCase
|
||||
public class TestSceneHitCircle : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private int depthIndex;
|
||||
|
||||
public TestCaseHitCircle()
|
||||
public TestSceneHitCircle()
|
||||
{
|
||||
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseHitCircleHidden : TestCaseHitCircle
|
||||
public class TestSceneHitCircleHidden : TestSceneHitCircle
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList();
|
||||
|
||||
public TestCaseHitCircleHidden()
|
||||
public TestSceneHitCircleHidden()
|
||||
{
|
||||
Mods.Value = new[] { new OsuModHidden() };
|
||||
}
|
||||
+4
-4
@@ -10,21 +10,21 @@ using osuTK;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseHitCircleLongCombo : PlayerTestCase
|
||||
public class TestSceneHitCircleLongCombo : PlayerTestScene
|
||||
{
|
||||
public TestCaseHitCircleLongCombo()
|
||||
public TestSceneHitCircleLongCombo()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseHitCirclePlacementBlueprint : PlacementBlueprintTestCase
|
||||
public class TestSceneHitCirclePlacementBlueprint : PlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHitCircle((HitCircle)hitObject);
|
||||
protected override PlacementBlueprint CreateBlueprint() => new HitCirclePlacementBlueprint();
|
||||
+2
-2
@@ -12,11 +12,11 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseHitCircleSelectionBlueprint : SelectionBlueprintTestCase
|
||||
public class TestSceneHitCircleSelectionBlueprint : SelectionBlueprintTestScene
|
||||
{
|
||||
private readonly DrawableHitCircle drawableObject;
|
||||
|
||||
public TestCaseHitCircleSelectionBlueprint()
|
||||
public TestSceneHitCircleSelectionBlueprint()
|
||||
{
|
||||
var hitCircle = new HitCircle { Position = new Vector2(256, 192) };
|
||||
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 2 });
|
||||
+1
-1
@@ -7,7 +7,7 @@ using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseOsuFlashlight : TestCaseOsuPlayer
|
||||
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
||||
{
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
+2
-2
@@ -7,9 +7,9 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseOsuPlayer : PlayerTestCase
|
||||
public class TestSceneOsuPlayer : PlayerTestScene
|
||||
{
|
||||
public TestCaseOsuPlayer()
|
||||
public TestSceneOsuPlayer()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
+4
-4
@@ -12,14 +12,14 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseResumeOverlay : ManualInputManagerTestCase
|
||||
public class TestSceneResumeOverlay : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuResumeOverlay),
|
||||
};
|
||||
|
||||
public TestCaseResumeOverlay()
|
||||
public TestSceneResumeOverlay()
|
||||
{
|
||||
ManualOsuInputManager osuInputManager;
|
||||
CursorContainer cursor;
|
||||
@@ -46,11 +46,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
AddStep("move mouse away", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.TopLeft));
|
||||
AddStep("click", () => osuInputManager.GameClick());
|
||||
AddAssert("not dismissed", () => !resumeFired && resume.State == Visibility.Visible);
|
||||
AddAssert("not dismissed", () => !resumeFired && resume.State.Value == Visibility.Visible);
|
||||
|
||||
AddStep("move mouse back", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("click", () => osuInputManager.GameClick());
|
||||
AddAssert("dismissed", () => resumeFired && resume.State == Visibility.Hidden);
|
||||
AddAssert("dismissed", () => resumeFired && resume.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
private class ManualOsuInputManager : OsuInputManager
|
||||
+1
-1
@@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseShaking : TestCaseHitCircle
|
||||
public class TestSceneShaking : TestSceneHitCircle
|
||||
{
|
||||
public override void Add(Drawable drawable)
|
||||
{
|
||||
+2
-2
@@ -27,7 +27,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseSlider : OsuTestCase
|
||||
public class TestSceneSlider : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private int depthIndex;
|
||||
|
||||
public TestCaseSlider()
|
||||
public TestSceneSlider()
|
||||
{
|
||||
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseSpinnerHidden : TestCaseSpinner
|
||||
public class TestSceneSliderHidden : TestSceneSlider
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList();
|
||||
|
||||
public TestCaseSpinnerHidden()
|
||||
public TestSceneSliderHidden()
|
||||
{
|
||||
Mods.Value = new[] { new OsuModHidden() };
|
||||
}
|
||||
+5
-4
@@ -20,13 +20,12 @@ using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseSliderInput : RateAdjustedBeatmapTestCase
|
||||
public class TestSceneSliderInput : RateAdjustedBeatmapTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -299,7 +298,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
AddStep("load player", () =>
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
@@ -323,7 +322,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 },
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
}, Clock);
|
||||
});
|
||||
|
||||
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
|
||||
|
||||
@@ -353,6 +352,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
protected override bool PauseOnFocusLost => false;
|
||||
|
||||
public ScoreAccessibleReplayPlayer(Score score)
|
||||
: base(score, false, false)
|
||||
{
|
||||
+1
-1
@@ -11,7 +11,7 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseSliderPlacementBlueprint : PlacementBlueprintTestCase
|
||||
public class TestSceneSliderPlacementBlueprint : PlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSlider((Slider)hitObject);
|
||||
protected override PlacementBlueprint CreateBlueprint() => new SliderPlacementBlueprint();
|
||||
+2
-2
@@ -17,7 +17,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseSliderSelectionBlueprint : SelectionBlueprintTestCase
|
||||
public class TestSceneSliderSelectionBlueprint : SelectionBlueprintTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private readonly DrawableSlider drawableObject;
|
||||
|
||||
public TestCaseSliderSelectionBlueprint()
|
||||
public TestSceneSliderSelectionBlueprint()
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
+2
-2
@@ -18,7 +18,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseSpinner : OsuTestCase
|
||||
public class TestSceneSpinner : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private int depthIndex;
|
||||
|
||||
public TestCaseSpinner()
|
||||
public TestSceneSpinner()
|
||||
{
|
||||
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ using osu.Game.Rulesets.Osu.Mods;
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseSliderHidden : TestCaseSlider
|
||||
public class TestSceneSpinnerHidden : TestSceneSpinner
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList();
|
||||
|
||||
public TestCaseSliderHidden()
|
||||
public TestSceneSpinnerHidden()
|
||||
{
|
||||
Mods.Value = new[] { new OsuModHidden() };
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseSpinnerPlacementBlueprint : PlacementBlueprintTestCase
|
||||
public class TestSceneSpinnerPlacementBlueprint : PlacementBlueprintTestScene
|
||||
{
|
||||
protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableSpinner((Spinner)hitObject);
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestCaseSpinnerSelectionBlueprint : SelectionBlueprintTestCase
|
||||
public class TestSceneSpinnerSelectionBlueprint : SelectionBlueprintTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private readonly DrawableSpinner drawableSpinner;
|
||||
|
||||
public TestCaseSpinnerSelectionBlueprint()
|
||||
public TestSceneSpinnerSelectionBlueprint()
|
||||
{
|
||||
var spinner = new Spinner
|
||||
{
|
||||
@@ -2,8 +2,8 @@
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
break;
|
||||
|
||||
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance
|
||||
|| stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance)
|
||||
|| (stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance))
|
||||
{
|
||||
stackBaseIndex = n;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||
{
|
||||
if (beatmap.HitObjects.Count == 0)
|
||||
return new OsuDifficultyAttributes { Mods = mods };
|
||||
return new OsuDifficultyAttributes { Mods = mods, Skills = skills };
|
||||
|
||||
double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier;
|
||||
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
|
||||
@@ -50,7 +50,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
SpeedStrain = speedRating,
|
||||
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
|
||||
OverallDifficulty = (80 - hitWindowGreat) / 6,
|
||||
MaxCombo = maxCombo
|
||||
MaxCombo = maxCombo,
|
||||
Skills = skills
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@@ -48,7 +49,14 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
FlashlightPosition = e.MousePosition;
|
||||
const double follow_delay = 120;
|
||||
|
||||
var position = FlashlightPosition;
|
||||
var destination = e.MousePosition;
|
||||
|
||||
FlashlightPosition = Interpolation.ValueAt(
|
||||
MathHelper.Clamp(Clock.ElapsedFrameTime, 0, follow_delay), position, destination, 0, follow_delay, Easing.Out);
|
||||
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@@ -11,7 +14,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
internal class OsuModGrow : Mod, IApplicableToDrawableHitObjects
|
||||
internal class OsuModGrow : Mod, IReadFromConfig, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override string Name => "Grow";
|
||||
|
||||
@@ -25,9 +28,16 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
private Bindable<bool> increaseFirstObjectVisibility = new Bindable<bool>();
|
||||
|
||||
public void ReadFromConfig(OsuConfigManager config)
|
||||
{
|
||||
increaseFirstObjectVisibility = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility);
|
||||
}
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var drawable in drawables)
|
||||
foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0))
|
||||
{
|
||||
switch (drawable)
|
||||
{
|
||||
|
||||
@@ -37,11 +37,11 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
if (time < osuHit.HitObject.StartTime - relax_leniency) continue;
|
||||
|
||||
if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit)
|
||||
if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit)
|
||||
continue;
|
||||
|
||||
requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime);
|
||||
requiresHold |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner;
|
||||
requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner;
|
||||
}
|
||||
|
||||
if (requiresHit)
|
||||
|
||||
@@ -160,9 +160,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
Body.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour;
|
||||
Body.BorderColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour;
|
||||
Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour;
|
||||
Body.BorderSize = skin.GetValue<SkinConfiguration, float?>(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE;
|
||||
Body.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour;
|
||||
Body.BorderColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White;
|
||||
Ball.AccentColour = skin.GetValue<SkinConfiguration, Color4?>(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour;
|
||||
}
|
||||
|
||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@@ -25,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Child = new SkinnableDrawable("Play/osu/approachcircle", name => new Sprite { Texture = textures.Get(name) });
|
||||
Child = new SkinnableSprite("Play/osu/approachcircle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,20 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Graphics.ES30;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
public abstract class SliderBody : CompositeDrawable
|
||||
{
|
||||
public const float DEFAULT_BORDER_SIZE = 1;
|
||||
|
||||
private readonly SliderPath path;
|
||||
protected Path Path => path;
|
||||
|
||||
private readonly BufferedContainer container;
|
||||
|
||||
public float PathRadius
|
||||
{
|
||||
get => path.PathRadius;
|
||||
@@ -42,8 +39,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
|
||||
path.AccentColour = value;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,23 +54,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
|
||||
path.BorderColour = value;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
public Quad PathDrawQuad => container.ScreenSpaceDrawQuad;
|
||||
/// <summary>
|
||||
/// Used to size the path border.
|
||||
/// </summary>
|
||||
public float BorderSize
|
||||
{
|
||||
get => path.BorderSize;
|
||||
set
|
||||
{
|
||||
if (path.BorderSize == value)
|
||||
return;
|
||||
|
||||
path.BorderSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected SliderBody()
|
||||
{
|
||||
InternalChild = container = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Child = path = new SliderPath { Blending = BlendingMode.None }
|
||||
};
|
||||
|
||||
container.Attach(RenderbufferInternalFormat.DepthComponent16);
|
||||
InternalChild = path = new SliderPath();
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos);
|
||||
@@ -84,14 +83,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
/// Sets the vertices of the path which should be drawn by this <see cref="SliderBody"/>.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices</param>
|
||||
protected void SetVertices(IReadOnlyList<Vector2> vertices)
|
||||
{
|
||||
path.Vertices = vertices;
|
||||
container.ForceRedraw();
|
||||
}
|
||||
protected void SetVertices(IReadOnlyList<Vector2> vertices) => path.Vertices = vertices;
|
||||
|
||||
private class SliderPath : SmoothPath
|
||||
{
|
||||
private const float border_max_size = 8f;
|
||||
private const float border_min_size = 0f;
|
||||
|
||||
private const float border_portion = 0.128f;
|
||||
private const float gradient_portion = 1 - border_portion;
|
||||
|
||||
@@ -130,12 +128,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
private float borderSize = DEFAULT_BORDER_SIZE;
|
||||
|
||||
public float BorderSize
|
||||
{
|
||||
get => borderSize;
|
||||
set
|
||||
{
|
||||
if (borderSize == value)
|
||||
return;
|
||||
|
||||
if (value < border_min_size || value > border_max_size)
|
||||
return;
|
||||
|
||||
borderSize = value;
|
||||
|
||||
InvalidateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private float calculatedBorderPortion => BorderSize * border_portion;
|
||||
|
||||
protected override Color4 ColourAt(float position)
|
||||
{
|
||||
if (position <= border_portion)
|
||||
if (calculatedBorderPortion != 0f && position <= calculatedBorderPortion)
|
||||
return BorderColour;
|
||||
|
||||
position -= border_portion;
|
||||
position -= calculatedBorderPortion;
|
||||
return new Color4(AccentColour.R, AccentColour.G, AccentColour.B, (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * position / gradient_portion) * AccentColour.A);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.OpenGL.Buffers;
|
||||
using osu.Framework.Graphics.Batches;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shaders;
|
||||
@@ -54,8 +54,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
for (int i = 0; i < max_sprites; i++)
|
||||
{
|
||||
parts[i].InvalidationID = 0;
|
||||
parts[i].WasUpdated = true;
|
||||
// InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node
|
||||
// This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms
|
||||
parts[i].InvalidationID = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +148,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
public Vector2 Position;
|
||||
public float Time;
|
||||
public long InvalidationID;
|
||||
public bool WasUpdated;
|
||||
}
|
||||
|
||||
private class TrailDrawNode : DrawNode
|
||||
@@ -162,16 +162,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Vector2 size;
|
||||
|
||||
private readonly VertexBuffer<TexturedTrailVertex> vertexBuffer = new QuadVertexBuffer<TexturedTrailVertex>(max_sprites, BufferUsageHint.DynamicDraw);
|
||||
private readonly VertexBatch<TexturedTrailVertex> vertexBatch = new QuadBatch<TexturedTrailVertex>(max_sprites, 1);
|
||||
|
||||
public TrailDrawNode(CursorTrail source)
|
||||
: base(source)
|
||||
{
|
||||
for (int i = 0; i < max_sprites; i++)
|
||||
{
|
||||
parts[i].InvalidationID = 0;
|
||||
parts[i].WasUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyState()
|
||||
@@ -192,55 +189,29 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
shader.GetUniform<float>("g_FadeClock").UpdateValue(ref time);
|
||||
|
||||
int updateStart = -1, updateEnd = 0;
|
||||
|
||||
for (int i = 0; i < parts.Length; ++i)
|
||||
{
|
||||
if (parts[i].WasUpdated)
|
||||
{
|
||||
if (updateStart == -1)
|
||||
updateStart = i;
|
||||
updateEnd = i + 1;
|
||||
|
||||
int start = i * 4;
|
||||
int end = start;
|
||||
|
||||
Vector2 pos = parts[i].Position;
|
||||
float localTime = parts[i].Time;
|
||||
|
||||
texture.DrawQuad(
|
||||
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
|
||||
DrawColourInfo.Colour,
|
||||
null,
|
||||
v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
||||
{
|
||||
Position = v.Position,
|
||||
TexturePosition = v.TexturePosition,
|
||||
Time = localTime + 1,
|
||||
Colour = v.Colour,
|
||||
});
|
||||
|
||||
parts[i].WasUpdated = false;
|
||||
}
|
||||
else if (updateStart != -1)
|
||||
{
|
||||
vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4);
|
||||
updateStart = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update all remaining vertices that have been changed.
|
||||
if (updateStart != -1)
|
||||
vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4);
|
||||
|
||||
base.Draw(vertexAction);
|
||||
|
||||
shader.Bind();
|
||||
shader.GetUniform<float>("g_FadeClock").UpdateValue(ref time);
|
||||
|
||||
texture.TextureGL.Bind();
|
||||
vertexBuffer.Draw();
|
||||
for (int i = 0; i < parts.Length; ++i)
|
||||
{
|
||||
Vector2 pos = parts[i].Position;
|
||||
float localTime = parts[i].Time;
|
||||
|
||||
DrawQuad(
|
||||
texture,
|
||||
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
|
||||
DrawColourInfo.Colour,
|
||||
null,
|
||||
v => vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = v.Position,
|
||||
TexturePosition = v.TexturePosition,
|
||||
Time = localTime + 1,
|
||||
Colour = v.Colour,
|
||||
}));
|
||||
}
|
||||
|
||||
shader.Unbind();
|
||||
}
|
||||
@@ -249,7 +220,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
vertexBuffer.Dispose();
|
||||
vertexBatch.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -73,7 +74,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
// Todo: Math.Max() is required as a temporary measure to address https://github.com/ppy/osu-framework/issues/2576
|
||||
downCount = Math.Max(0, downCount - 1);
|
||||
|
||||
if (downCount == 0)
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -63,8 +63,10 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
get
|
||||
{
|
||||
var first = (OsuHitObject)Objects.First();
|
||||
return first.StartTime - Math.Max(2000, first.TimePreempt);
|
||||
if (Objects.FirstOrDefault() is OsuHitObject first)
|
||||
return first.StartTime - Math.Max(2000, first.TimePreempt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private GameplayCursorContainer localCursorContainer;
|
||||
|
||||
public override CursorContainer LocalCursor => State == Visibility.Visible ? localCursorContainer : null;
|
||||
public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null;
|
||||
|
||||
protected override string Message => "Click the orange cursor to resume";
|
||||
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ using osu.Game.Tests.Visual;
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseInputDrum : OsuTestCase
|
||||
public class TestSceneInputDrum : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
typeof(SampleControlPoint)
|
||||
};
|
||||
|
||||
public TestCaseInputDrum()
|
||||
public TestSceneInputDrum()
|
||||
{
|
||||
Add(new TaikoInputManager(new RulesetInfo { ID = 1 })
|
||||
{
|
||||
+3
-4
@@ -18,7 +18,6 @@ using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
@@ -26,7 +25,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseTaikoPlayfield : OsuTestCase
|
||||
public class TestSceneTaikoPlayfield : OsuTestScene
|
||||
{
|
||||
private const double default_duration = 1000;
|
||||
private const float scroll_time = 1000;
|
||||
@@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
var controlPointInfo = new ControlPointInfo();
|
||||
controlPointInfo.TimingPoints.Add(new TimingControlPoint());
|
||||
|
||||
WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
|
||||
WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject> { new CentreHit() },
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
@@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
Ruleset = new TaikoRuleset().RulesetInfo
|
||||
},
|
||||
ControlPointInfo = controlPointInfo
|
||||
}, Clock);
|
||||
});
|
||||
|
||||
Add(playfieldContainer = new Container
|
||||
{
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TestSceneTaikoSuddenDeath : PlayerTestScene
|
||||
{
|
||||
public TestSceneTaikoSuddenDeath()
|
||||
: base(new TaikoRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
||||
new TaikoBeatmap
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
new Swell { StartTime = 1500 },
|
||||
new Hit { StartTime = 100000 },
|
||||
},
|
||||
BeatmapInfo =
|
||||
{
|
||||
Ruleset = new TaikoRuleset().RulesetInfo
|
||||
}
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestSpinnerDoesNotFail()
|
||||
{
|
||||
bool judged = false;
|
||||
AddStep("Setup judgements", () =>
|
||||
{
|
||||
judged = false;
|
||||
((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
|
||||
});
|
||||
AddUntilStep("swell judged", () => judged);
|
||||
AddAssert("not failed", () => !Player.HasFailed);
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||
{
|
||||
if (beatmap.HitObjects.Count == 0)
|
||||
return new TaikoDifficultyAttributes { Mods = mods };
|
||||
return new TaikoDifficultyAttributes { Mods = mods, Skills = skills };
|
||||
|
||||
return new TaikoDifficultyAttributes
|
||||
{
|
||||
@@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||
GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate,
|
||||
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
||||
Skills = skills
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -170,27 +170,98 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
var controlPoints = beatmap.ControlPointInfo;
|
||||
|
||||
Assert.AreEqual(4, controlPoints.TimingPoints.Count);
|
||||
var timingPoint = controlPoints.TimingPoints[0];
|
||||
Assert.AreEqual(42, controlPoints.DifficultyPoints.Count);
|
||||
Assert.AreEqual(42, controlPoints.SamplePoints.Count);
|
||||
Assert.AreEqual(42, controlPoints.EffectPoints.Count);
|
||||
|
||||
var timingPoint = controlPoints.TimingPointAt(0);
|
||||
Assert.AreEqual(956, timingPoint.Time);
|
||||
Assert.AreEqual(329.67032967033, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
timingPoint = controlPoints.TimingPointAt(48428);
|
||||
Assert.AreEqual(956, timingPoint.Time);
|
||||
Assert.AreEqual(329.67032967033d, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
Assert.AreEqual(5, controlPoints.DifficultyPoints.Count);
|
||||
var difficultyPoint = controlPoints.DifficultyPoints[0];
|
||||
Assert.AreEqual(116999, difficultyPoint.Time);
|
||||
Assert.AreEqual(0.75000000000000189d, difficultyPoint.SpeedMultiplier);
|
||||
timingPoint = controlPoints.TimingPointAt(119637);
|
||||
Assert.AreEqual(119637, timingPoint.Time);
|
||||
Assert.AreEqual(659.340659340659, timingPoint.BeatLength);
|
||||
Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature);
|
||||
|
||||
Assert.AreEqual(34, controlPoints.SamplePoints.Count);
|
||||
var soundPoint = controlPoints.SamplePoints[0];
|
||||
var difficultyPoint = controlPoints.DifficultyPointAt(0);
|
||||
Assert.AreEqual(0, difficultyPoint.Time);
|
||||
Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier);
|
||||
|
||||
difficultyPoint = controlPoints.DifficultyPointAt(48428);
|
||||
Assert.AreEqual(48428, difficultyPoint.Time);
|
||||
Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier);
|
||||
|
||||
difficultyPoint = controlPoints.DifficultyPointAt(116999);
|
||||
Assert.AreEqual(116999, difficultyPoint.Time);
|
||||
Assert.AreEqual(0.75, difficultyPoint.SpeedMultiplier, 0.1);
|
||||
|
||||
var soundPoint = controlPoints.SamplePointAt(0);
|
||||
Assert.AreEqual(956, soundPoint.Time);
|
||||
Assert.AreEqual("soft", soundPoint.SampleBank);
|
||||
Assert.AreEqual(60, soundPoint.SampleVolume);
|
||||
|
||||
Assert.AreEqual(8, controlPoints.EffectPoints.Count);
|
||||
var effectPoint = controlPoints.EffectPoints[0];
|
||||
soundPoint = controlPoints.SamplePointAt(53373);
|
||||
Assert.AreEqual(53373, soundPoint.Time);
|
||||
Assert.AreEqual("soft", soundPoint.SampleBank);
|
||||
Assert.AreEqual(60, soundPoint.SampleVolume);
|
||||
|
||||
soundPoint = controlPoints.SamplePointAt(119637);
|
||||
Assert.AreEqual(119637, soundPoint.Time);
|
||||
Assert.AreEqual("soft", soundPoint.SampleBank);
|
||||
Assert.AreEqual(80, soundPoint.SampleVolume);
|
||||
|
||||
var effectPoint = controlPoints.EffectPointAt(0);
|
||||
Assert.AreEqual(0, effectPoint.Time);
|
||||
Assert.IsFalse(effectPoint.KiaiMode);
|
||||
Assert.IsFalse(effectPoint.OmitFirstBarLine);
|
||||
|
||||
effectPoint = controlPoints.EffectPointAt(53703);
|
||||
Assert.AreEqual(53703, effectPoint.Time);
|
||||
Assert.IsTrue(effectPoint.KiaiMode);
|
||||
Assert.IsFalse(effectPoint.OmitFirstBarLine);
|
||||
|
||||
effectPoint = controlPoints.EffectPointAt(119637);
|
||||
Assert.AreEqual(119637, effectPoint.Time);
|
||||
Assert.IsFalse(effectPoint.KiaiMode);
|
||||
Assert.IsFalse(effectPoint.OmitFirstBarLine);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDecodeOverlappingTimingPoints()
|
||||
{
|
||||
var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
|
||||
|
||||
using (var resStream = TestResources.OpenResource("overlapping-control-points.osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var controlPoints = decoder.Decode(stream).ControlPointInfo;
|
||||
|
||||
Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
|
||||
Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
|
||||
Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1));
|
||||
Assert.That(controlPoints.DifficultyPointAt(3500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
|
||||
|
||||
Assert.That(controlPoints.EffectPointAt(500).KiaiMode, Is.True);
|
||||
Assert.That(controlPoints.EffectPointAt(1500).KiaiMode, Is.True);
|
||||
Assert.That(controlPoints.EffectPointAt(2500).KiaiMode, Is.False);
|
||||
Assert.That(controlPoints.EffectPointAt(3500).KiaiMode, Is.True);
|
||||
|
||||
Assert.That(controlPoints.SamplePointAt(500).SampleBank, Is.EqualTo("drum"));
|
||||
Assert.That(controlPoints.SamplePointAt(1500).SampleBank, Is.EqualTo("drum"));
|
||||
Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal"));
|
||||
Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum"));
|
||||
|
||||
Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500).Within(0.1));
|
||||
Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500).Within(0.1));
|
||||
Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250).Within(0.1));
|
||||
Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500).Within(0.1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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.IO;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Tests.Resources;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps.Formats
|
||||
{
|
||||
[TestFixture]
|
||||
public class LegacyDecoderTest
|
||||
{
|
||||
[Test]
|
||||
public void TestDecodeComments()
|
||||
{
|
||||
var decoder = new LineLoggingDecoder(14);
|
||||
|
||||
using (var resStream = TestResources.OpenResource("comments.osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
decoder.Decode(stream);
|
||||
|
||||
Assert.That(decoder.ParsedLines, Has.None.EqualTo("// Combo1: 0, 0, 0"));
|
||||
Assert.That(decoder.ParsedLines, Has.None.EqualTo("//Combo2: 0, 0, 0"));
|
||||
Assert.That(decoder.ParsedLines, Has.None.EqualTo(" // Combo3: 0, 0, 0"));
|
||||
Assert.That(decoder.ParsedLines, Has.One.EqualTo("Combo1: 100, 100, 100 // Comment at end of line"));
|
||||
}
|
||||
}
|
||||
|
||||
private class LineLoggingDecoder : LegacyDecoder<TestModel>
|
||||
{
|
||||
public readonly List<string> ParsedLines = new List<string>();
|
||||
|
||||
public LineLoggingDecoder(int version)
|
||||
: base(version)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ShouldSkipLine(string line)
|
||||
{
|
||||
var result = base.ShouldSkipLine(line);
|
||||
|
||||
if (!result)
|
||||
ParsedLines.Add(line);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,9 @@ using NUnit.Framework;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.IPC;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Tests.Resources;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
@@ -21,14 +23,14 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
public class ImportBeatmapTest
|
||||
{
|
||||
[Test]
|
||||
public void TestImportWhenClosed()
|
||||
public async Task TestImportWhenClosed()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenClosed"))
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadOszIntoOsu(loadOsu(host));
|
||||
await LoadOszIntoOsu(loadOsu(host));
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -38,7 +40,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportThenDelete()
|
||||
public async Task TestImportThenDelete()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDelete"))
|
||||
@@ -47,7 +49,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
||||
deleteBeatmapSet(imported, osu);
|
||||
}
|
||||
@@ -59,7 +61,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportThenImport()
|
||||
public async Task TestImportThenImport()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImport"))
|
||||
@@ -68,17 +70,15 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var importedSecondTime = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
var importedSecondTime = await LoadOszIntoOsu(osu);
|
||||
|
||||
// check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
|
||||
Assert.IsTrue(imported.ID == importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
|
||||
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||
checkBeatmapSetCount(osu, 1);
|
||||
checkSingleReferencedFileCount(osu, 18);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -88,30 +88,41 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRollbackOnFailure()
|
||||
public async Task TestRollbackOnFailure()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestRollbackOnFailure"))
|
||||
{
|
||||
try
|
||||
{
|
||||
int itemAddRemoveFireCount = 0;
|
||||
int loggedExceptionCount = 0;
|
||||
|
||||
Logger.NewEntry += l =>
|
||||
{
|
||||
if (l.Target == LoggingTarget.Database && l.Exception != null)
|
||||
Interlocked.Increment(ref loggedExceptionCount);
|
||||
};
|
||||
|
||||
var osu = loadOsu(host);
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
int fireCount = 0;
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
manager.ItemAdded += (_, __) => fireCount++;
|
||||
manager.ItemRemoved += _ => fireCount++;
|
||||
manager.ItemAdded += _ => Interlocked.Increment(ref itemAddRemoveFireCount);
|
||||
manager.ItemRemoved += _ => Interlocked.Increment(ref itemAddRemoveFireCount);
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
||||
Assert.AreEqual(0, fireCount -= 1);
|
||||
Assert.AreEqual(0, itemAddRemoveFireCount -= 1);
|
||||
|
||||
imported.Hash += "-changed";
|
||||
manager.Update(imported);
|
||||
|
||||
Assert.AreEqual(0, fireCount -= 2);
|
||||
Assert.AreEqual(0, itemAddRemoveFireCount -= 2);
|
||||
|
||||
checkBeatmapSetCount(osu, 1);
|
||||
checkBeatmapCount(osu, 12);
|
||||
checkSingleReferencedFileCount(osu, 18);
|
||||
|
||||
var breakTemp = TestResources.GetTestBeatmapForImport();
|
||||
|
||||
@@ -127,19 +138,24 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||
Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count);
|
||||
|
||||
// this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu.
|
||||
manager.Import(breakTemp);
|
||||
try
|
||||
{
|
||||
await manager.Import(breakTemp);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// no events should be fired in the case of a rollback.
|
||||
Assert.AreEqual(0, fireCount);
|
||||
Assert.AreEqual(0, itemAddRemoveFireCount);
|
||||
|
||||
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||
Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count);
|
||||
checkBeatmapSetCount(osu, 1);
|
||||
checkBeatmapCount(osu, 12);
|
||||
|
||||
checkSingleReferencedFileCount(osu, 18);
|
||||
|
||||
Assert.AreEqual(1, loggedExceptionCount);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -149,7 +165,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportThenImportDifferentHash()
|
||||
public async Task TestImportThenImportDifferentHash()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenImportDifferentHash"))
|
||||
@@ -159,19 +175,18 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
var osu = loadOsu(host);
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
||||
imported.Hash += "-changed";
|
||||
manager.Update(imported);
|
||||
|
||||
var importedSecondTime = LoadOszIntoOsu(osu);
|
||||
var importedSecondTime = await LoadOszIntoOsu(osu);
|
||||
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID);
|
||||
|
||||
// only one beatmap will exist as the online set ID matched, causing purging of the first import.
|
||||
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||
checkBeatmapSetCount(osu, 1);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -181,7 +196,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportThenDeleteThenImport()
|
||||
public async Task TestImportThenDeleteThenImport()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportThenDeleteThenImport"))
|
||||
@@ -190,11 +205,11 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
||||
deleteBeatmapSet(imported, osu);
|
||||
|
||||
var importedSecondTime = LoadOszIntoOsu(osu);
|
||||
var importedSecondTime = await LoadOszIntoOsu(osu);
|
||||
|
||||
// check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
|
||||
Assert.IsTrue(imported.ID == importedSecondTime.ID);
|
||||
@@ -209,7 +224,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public void TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set)
|
||||
public async Task TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set)
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"TestImportThenDeleteThenImport-{set}"))
|
||||
@@ -218,7 +233,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
|
||||
var imported = LoadOszIntoOsu(osu);
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
||||
if (set)
|
||||
imported.OnlineBeatmapSetID = 1234;
|
||||
@@ -229,7 +244,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
deleteBeatmapSet(imported, osu);
|
||||
|
||||
var importedSecondTime = LoadOszIntoOsu(osu);
|
||||
var importedSecondTime = await LoadOszIntoOsu(osu);
|
||||
|
||||
// check the newly "imported" beatmap has been reimported due to mismatch (even though hashes matched)
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||
@@ -243,7 +258,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportWithDuplicateBeatmapIDs()
|
||||
public async Task TestImportWithDuplicateBeatmapIDs()
|
||||
{
|
||||
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDuplicateBeatmapID"))
|
||||
@@ -284,7 +299,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
var imported = manager.Import(toImport);
|
||||
var imported = await manager.Import(toImport);
|
||||
|
||||
Assert.NotNull(imported);
|
||||
Assert.AreEqual(null, imported.Beatmaps[0].OnlineBeatmapID);
|
||||
@@ -330,7 +345,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportWhenFileOpen()
|
||||
public async Task TestImportWhenFileOpen()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenFileOpen"))
|
||||
{
|
||||
@@ -339,7 +354,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
var osu = loadOsu(host);
|
||||
var temp = TestResources.GetTestBeatmapForImport();
|
||||
using (File.OpenRead(temp))
|
||||
osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||
await osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||
ensureLoaded(osu);
|
||||
File.Delete(temp);
|
||||
Assert.IsFalse(File.Exists(temp), "We likely held a read lock on the file when we shouldn't");
|
||||
@@ -351,13 +366,13 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
}
|
||||
}
|
||||
|
||||
public static BeatmapSetInfo LoadOszIntoOsu(OsuGameBase osu, string path = null)
|
||||
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null)
|
||||
{
|
||||
var temp = path ?? TestResources.GetTestBeatmapForImport();
|
||||
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
manager.Import(temp);
|
||||
await manager.Import(temp);
|
||||
|
||||
var imported = manager.GetAllUsableBeatmapSets();
|
||||
|
||||
@@ -373,11 +388,32 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
manager.Delete(imported);
|
||||
|
||||
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 0);
|
||||
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||
checkBeatmapSetCount(osu, 0);
|
||||
checkBeatmapSetCount(osu, 1, true);
|
||||
checkSingleReferencedFileCount(osu, 0);
|
||||
|
||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending);
|
||||
}
|
||||
|
||||
private void checkBeatmapSetCount(OsuGameBase osu, int expected, bool includeDeletePending = false)
|
||||
{
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
Assert.AreEqual(expected, includeDeletePending
|
||||
? manager.QueryBeatmapSets(_ => true).ToList().Count
|
||||
: manager.GetAllUsableBeatmapSets().Count);
|
||||
}
|
||||
|
||||
private void checkBeatmapCount(OsuGameBase osu, int expected)
|
||||
{
|
||||
Assert.AreEqual(expected, osu.Dependencies.Get<BeatmapManager>().QueryBeatmaps(_ => true).ToList().Count);
|
||||
}
|
||||
|
||||
private void checkSingleReferencedFileCount(OsuGameBase osu, int expected)
|
||||
{
|
||||
Assert.AreEqual(expected, osu.Dependencies.Get<FileStore>().QueryFiles(f => f.ReferenceCount == 1).Count());
|
||||
}
|
||||
|
||||
private OsuGameBase loadOsu(GameHost host)
|
||||
{
|
||||
var osu = new OsuGameBase();
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace osu.Game.Tests.Chat
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCaseInsensitiveLinks()
|
||||
public void TestInsensitiveLinks()
|
||||
{
|
||||
Message result = MessageFormatter.FormatMessage(new Message { Content = "look: http://puu.sh/7Ggh8xcC6/asf0asd9876.NEF" });
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
osu file format v14
|
||||
|
||||
[Colours]
|
||||
|
||||
// Combo1: 0, 0, 0
|
||||
//Combo2: 0, 0, 0
|
||||
// Combo3: 0, 0, 0
|
||||
|
||||
Combo1: 100, 100, 100 // Comment at end of line
|
||||
@@ -0,0 +1,19 @@
|
||||
osu file format v14
|
||||
|
||||
[TimingPoints]
|
||||
|
||||
// Timing then inherited
|
||||
0,500,4,2,0,100,1,0
|
||||
0,-66.6666666666667,4,3,0,100,0,1
|
||||
|
||||
// Inherited then timing (equivalent to previous)
|
||||
1000,-66.6666666666667,4,3,0,100,0,1
|
||||
1000,500,4,2,0,100,1,0
|
||||
|
||||
// Inherited then timing (different to previous)
|
||||
2000,-133.333333333333,4,1,0,100,0,0
|
||||
2000,250,4,2,0,100,1,0
|
||||
|
||||
// Timing then inherited (different to previous)
|
||||
3000,500,4,2,0,100,1,0
|
||||
3000,-66.6666666666667,4,3,0,100,0,1
|
||||
@@ -23,13 +23,13 @@ namespace osu.Game.Tests.Scores.IO
|
||||
public class ImportScoreTest
|
||||
{
|
||||
[Test]
|
||||
public void TestBasicImport()
|
||||
public async Task TestBasicImport()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestBasicImport"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
var osu = await loadOsu(host);
|
||||
|
||||
var toImport = new ScoreInfo
|
||||
{
|
||||
@@ -43,7 +43,7 @@ namespace osu.Game.Tests.Scores.IO
|
||||
OnlineScoreID = 12345,
|
||||
};
|
||||
|
||||
var imported = loadIntoOsu(osu, toImport);
|
||||
var imported = await loadIntoOsu(osu, toImport);
|
||||
|
||||
Assert.AreEqual(toImport.Rank, imported.Rank);
|
||||
Assert.AreEqual(toImport.TotalScore, imported.TotalScore);
|
||||
@@ -62,20 +62,20 @@ namespace osu.Game.Tests.Scores.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportMods()
|
||||
public async Task TestImportMods()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportMods"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
var osu = await loadOsu(host);
|
||||
|
||||
var toImport = new ScoreInfo
|
||||
{
|
||||
Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() },
|
||||
};
|
||||
|
||||
var imported = loadIntoOsu(osu, toImport);
|
||||
var imported = await loadIntoOsu(osu, toImport);
|
||||
|
||||
Assert.IsTrue(imported.Mods.Any(m => m is OsuModHardRock));
|
||||
Assert.IsTrue(imported.Mods.Any(m => m is OsuModDoubleTime));
|
||||
@@ -88,13 +88,13 @@ namespace osu.Game.Tests.Scores.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestImportStatistics()
|
||||
public async Task TestImportStatistics()
|
||||
{
|
||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportStatistics"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var osu = loadOsu(host);
|
||||
var osu = await loadOsu(host);
|
||||
|
||||
var toImport = new ScoreInfo
|
||||
{
|
||||
@@ -105,7 +105,7 @@ namespace osu.Game.Tests.Scores.IO
|
||||
}
|
||||
};
|
||||
|
||||
var imported = loadIntoOsu(osu, toImport);
|
||||
var imported = await loadIntoOsu(osu, toImport);
|
||||
|
||||
Assert.AreEqual(toImport.Statistics[HitResult.Perfect], imported.Statistics[HitResult.Perfect]);
|
||||
Assert.AreEqual(toImport.Statistics[HitResult.Miss], imported.Statistics[HitResult.Miss]);
|
||||
@@ -117,7 +117,7 @@ namespace osu.Game.Tests.Scores.IO
|
||||
}
|
||||
}
|
||||
|
||||
private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score)
|
||||
private async Task<ScoreInfo> loadIntoOsu(OsuGameBase osu, ScoreInfo score)
|
||||
{
|
||||
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
@@ -125,20 +125,24 @@ namespace osu.Game.Tests.Scores.IO
|
||||
score.Ruleset = new OsuRuleset().RulesetInfo;
|
||||
|
||||
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
||||
scoreManager.Import(score);
|
||||
await scoreManager.Import(score);
|
||||
|
||||
return scoreManager.GetAllUsableScores().First();
|
||||
}
|
||||
|
||||
private OsuGameBase loadOsu(GameHost host)
|
||||
private async Task<OsuGameBase> loadOsu(GameHost host)
|
||||
{
|
||||
var osu = new OsuGameBase();
|
||||
|
||||
#pragma warning disable 4014
|
||||
Task.Run(() => host.Run(osu));
|
||||
#pragma warning restore 4014
|
||||
|
||||
waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time");
|
||||
|
||||
var beatmapFile = TestResources.GetTestBeatmapForImport();
|
||||
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
||||
beatmapManager.Import(beatmapFile);
|
||||
await beatmapManager.Import(beatmapFile);
|
||||
|
||||
return osu;
|
||||
}
|
||||
|
||||
+8
-7
@@ -7,9 +7,9 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.Platform;
|
||||
@@ -19,6 +19,7 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Scoring;
|
||||
@@ -35,7 +36,7 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseBackgroundScreenBeatmap : ManualInputManagerTestCase
|
||||
public class TestSceneBackgroundScreenBeatmap : ManualInputManagerTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -54,7 +55,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
private RulesetStore rulesets;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host)
|
||||
private void load(GameHost host, AudioManager audio)
|
||||
{
|
||||
factory = new DatabaseContextFactory(LocalStorage);
|
||||
factory.ResetDatabase();
|
||||
@@ -68,10 +69,10 @@ namespace osu.Game.Tests.Visual.Background
|
||||
usage.Migrate();
|
||||
|
||||
Dependencies.Cache(rulesets = new RulesetStore(factory));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, Beatmap.Default));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default));
|
||||
Dependencies.Cache(new OsuConfigManager(LocalStorage));
|
||||
|
||||
manager.Import(TestResources.GetTestBeatmapForImport());
|
||||
manager.Import(TestResources.GetTestBeatmapForImport()).Wait();
|
||||
|
||||
Beatmap.SetDefault();
|
||||
}
|
||||
@@ -240,7 +241,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
player.StoryboardEnabled.Value = false;
|
||||
player.ReplacesBackground.Value = false;
|
||||
player.CurrentStoryboardContainer.Add(new SpriteText
|
||||
player.CurrentStoryboardContainer.Add(new OsuSpriteText
|
||||
{
|
||||
Size = new Vector2(250, 50),
|
||||
Alpha = 1,
|
||||
@@ -328,7 +329,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||
}
|
||||
|
||||
private class TestPlayer : Player
|
||||
private class TestPlayer : Visual.TestPlayer
|
||||
{
|
||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
||||
|
||||
+72
-34
@@ -12,96 +12,134 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Tests.Visual.Components
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseIdleTracker : ManualInputManagerTestCase
|
||||
public class TestSceneIdleTracker : ManualInputManagerTestScene
|
||||
{
|
||||
private readonly IdleTrackingBox box1;
|
||||
private readonly IdleTrackingBox box2;
|
||||
private readonly IdleTrackingBox box3;
|
||||
private readonly IdleTrackingBox box4;
|
||||
private IdleTrackingBox box1;
|
||||
private IdleTrackingBox box2;
|
||||
private IdleTrackingBox box3;
|
||||
private IdleTrackingBox box4;
|
||||
|
||||
public TestCaseIdleTracker()
|
||||
private IdleTrackingBox[] boxes;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
InputManager.MoveMouseTo(Vector2.Zero);
|
||||
|
||||
Children = boxes = new[]
|
||||
{
|
||||
box1 = new IdleTrackingBox(1000)
|
||||
box1 = new IdleTrackingBox(2000)
|
||||
{
|
||||
Name = "TopLeft",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Red,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
},
|
||||
box2 = new IdleTrackingBox(2000)
|
||||
box2 = new IdleTrackingBox(4000)
|
||||
{
|
||||
Name = "TopRight",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Green,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
box3 = new IdleTrackingBox(3000)
|
||||
box3 = new IdleTrackingBox(6000)
|
||||
{
|
||||
Name = "BottomLeft",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Blue,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
},
|
||||
box4 = new IdleTrackingBox(4000)
|
||||
box4 = new IdleTrackingBox(8000)
|
||||
{
|
||||
Name = "BottomRight",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Orange,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestNudge()
|
||||
{
|
||||
AddStep("move mouse to top left", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to top left", () => InputManager.MoveMouseTo(box1));
|
||||
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
waitForAllIdle();
|
||||
|
||||
AddStep("nudge mouse", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre + new Vector2(1)));
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle);
|
||||
AddAssert("check idle", () => box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
checkIdleStatus(1, false);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMovement()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to top right", () => InputManager.MoveMouseTo(box2));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, true);
|
||||
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box4.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to bottom left", () => InputManager.MoveMouseTo(box3));
|
||||
AddStep("move to bottom right", () => InputManager.MoveMouseTo(box4));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => !box3.IsIdle);
|
||||
AddAssert("check idle", () => !box4.IsIdle);
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
waitForAllIdle();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTimings()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to centre", () => InputManager.MoveMouseTo(Content));
|
||||
|
||||
checkIdleStatus(1, false);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle && !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
AddUntilStep("Wait for idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for idle", () => box2.IsIdle);
|
||||
AddAssert("check not idle", () => !box3.IsIdle && !box4.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for idle", () => box3.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
waitForAllIdle();
|
||||
}
|
||||
|
||||
private void checkIdleStatus(int box, bool expectedIdle)
|
||||
{
|
||||
AddAssert($"box {box} is {(expectedIdle ? "idle" : "active")}", () => boxes[box - 1].IsIdle == expectedIdle);
|
||||
}
|
||||
|
||||
private void waitForAllIdle()
|
||||
{
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Components
|
||||
{
|
||||
public class TestCasePollingComponent : OsuTestCase
|
||||
public class TestScenePollingComponent : OsuTestScene
|
||||
{
|
||||
private Container pollBox;
|
||||
private TestPoller poller;
|
||||
+7
-4
@@ -10,7 +10,7 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Components
|
||||
{
|
||||
public class TestCasePreviewTrackManager : OsuTestCase, IPreviewTrackOwner
|
||||
public class TestScenePreviewTrackManager : OsuTestScene, IPreviewTrackOwner
|
||||
{
|
||||
private readonly PreviewTrackManager trackManager = new TestPreviewTrackManager();
|
||||
|
||||
@@ -111,16 +111,19 @@ namespace osu.Game.Tests.Visual.Components
|
||||
|
||||
private class TestPreviewTrackManager : PreviewTrackManager
|
||||
{
|
||||
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TestPreviewTrack(beatmapSetInfo, trackManager);
|
||||
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore);
|
||||
|
||||
protected class TestPreviewTrack : TrackManagerPreviewTrack
|
||||
{
|
||||
public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager)
|
||||
private readonly ITrackStore trackManager;
|
||||
|
||||
public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager)
|
||||
: base(beatmapSetInfo, trackManager)
|
||||
{
|
||||
this.trackManager = trackManager;
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => new TrackVirtual { Length = 100000 };
|
||||
protected override Track GetTrack() => trackManager.GetVirtual(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
public class TestCaseBeatDivisorControl : OsuTestCase
|
||||
public class TestSceneBeatDivisorControl : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BindableBeatDivisor) };
|
||||
|
||||
+2
-3
@@ -7,19 +7,18 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit.Compose;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditorCompose : EditorClockTestCase
|
||||
public class TestSceneEditorCompose : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ComposeScreen) };
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
Child = new ComposeScreen();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -10,11 +10,11 @@ using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditorComposeRadioButtons : OsuTestCase
|
||||
public class TestSceneEditorComposeRadioButtons : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableRadioButton) };
|
||||
|
||||
public TestCaseEditorComposeRadioButtons()
|
||||
public TestSceneEditorComposeRadioButtons()
|
||||
{
|
||||
RadioButtonCollection collection;
|
||||
Add(collection = new RadioButtonCollection
|
||||
+4
-3
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -19,7 +20,7 @@ using osuTK.Graphics;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditorComposeTimeline : EditorClockTestCase
|
||||
public class TestSceneEditorComposeTimeline : EditorClockTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -30,9 +31,9 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
Beatmap.Value = new WaveformTestBeatmap();
|
||||
Beatmap.Value = new WaveformTestBeatmap(audio);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
+2
-2
@@ -13,11 +13,11 @@ using osu.Game.Screens.Edit.Components.Menus;
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditorMenuBar : OsuTestCase
|
||||
public class TestSceneEditorMenuBar : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(EditorMenuBar), typeof(ScreenSelectionTabControl) };
|
||||
|
||||
public TestCaseEditorMenuBar()
|
||||
public TestSceneEditorMenuBar()
|
||||
{
|
||||
Add(new Container
|
||||
{
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// 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;
|
||||
@@ -10,16 +10,15 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseEditorSeekSnapping : EditorClockTestCase
|
||||
public class TestSceneEditorSeekSnapping : EditorClockTestScene
|
||||
{
|
||||
public TestCaseEditorSeekSnapping()
|
||||
public TestSceneEditorSeekSnapping()
|
||||
{
|
||||
BeatDivisor.Value = 4;
|
||||
}
|
||||
@@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
}
|
||||
};
|
||||
|
||||
Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(testBeatmap);
|
||||
|
||||
Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock };
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user