mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 17:52:56 +08:00
Merge branch 'master' into fix-skin-dropdown-update-crash
This commit is contained in:
commit
1ce383fc20
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Benchmarks" type="DotNetProject" factoryName=".NET Project">
|
<configuration default="false" name="Benchmarks" type="DotNetProject" factoryName=".NET Project">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Release/netcoreapp3.1/osu.Game.Benchmarks.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Release/net5.0/osu.Game.Benchmarks.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="--filter *" />
|
<option name="PROGRAM_PARAMETERS" value="--filter *" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Release/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Benchmarks/bin/Release/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" enabled="true" />
|
<option name="Build" enabled="true" />
|
||||||
</method>
|
</method>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="CatchRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="CatchRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Catch.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net5.0/osu.Game.Rulesets.Catch.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<browser url="http://localhost:5000" />
|
<browser url="http://localhost:5000" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="ManiaRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="ManiaRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Mania.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net5.0/osu.Game.Rulesets.Mania.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<browser url="http://localhost:5000" />
|
<browser url="http://localhost:5000" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="OsuRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="OsuRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Osu.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net5.0/osu.Game.Rulesets.Osu.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<browser url="http://localhost:5000" />
|
<browser url="http://localhost:5000" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="TaikoRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="TaikoRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Taiko.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net5.0/osu.Game.Rulesets.Taiko.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<browser url="http://localhost:5000" />
|
<browser url="http://localhost:5000" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Tournament" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="Tournament" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0/osu!.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="--tournament" />
|
<option name="PROGRAM_PARAMETERS" value="--tournament" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="Tournament (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="Tournament (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Tournament" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1/osu.Game.Tournament.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net5.0/osu.Game.Tournament.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<browser url="http://localhost:5000" />
|
<browser url="http://localhost:5000" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0/osu!.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="osu! (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="osu! (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp3.1/osu.Game.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net5.0/osu.Game.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="osu! (legacy osuTK)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
<configuration default="false" name="osu! (legacy osuTK)" type="DotNetProject" factoryName=".NET Project" folderName="osu!" activateToolWindowBeforeRun="false">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0/osu!.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="--tk" />
|
<option name="PROGRAM_PARAMETERS" value="--tk" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp3.1" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net5.0" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||||
<option name="USE_MONO" value="0" />
|
<option name="USE_MONO" value="0" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
<option name="PROJECT_TFM" value="net5.0" />
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="Build" />
|
<option name="Build" />
|
||||||
</method>
|
</method>
|
||||||
|
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll"
|
"${workspaceRoot}/osu.Desktop/bin/Debug/net5.0/osu!.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Debug)",
|
"preLaunchTask": "Build osu! (Debug)",
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1/osu!.dll"
|
"${workspaceRoot}/osu.Desktop/bin/Release/net5.0/osu!.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build osu! (Release)",
|
"preLaunchTask": "Build osu! (Release)",
|
||||||
@ -31,7 +31,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp3.1/osu.Game.Tests.dll"
|
"${workspaceRoot}/osu.Game.Tests/bin/Debug/net5.0/osu.Game.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tests (Debug)",
|
"preLaunchTask": "Build tests (Debug)",
|
||||||
@ -43,7 +43,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp3.1/osu.Game.Tests.dll"
|
"${workspaceRoot}/osu.Game.Tests/bin/Release/net5.0/osu.Game.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build tests (Release)",
|
"preLaunchTask": "Build tests (Release)",
|
||||||
@ -55,7 +55,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1/osu!.dll",
|
"${workspaceRoot}/osu.Desktop/bin/Debug/net5.0/osu!.dll",
|
||||||
"--tournament"
|
"--tournament"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
@ -68,7 +68,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1/osu!.dll",
|
"${workspaceRoot}/osu.Desktop/bin/Release/net5.0/osu!.dll",
|
||||||
"--tournament"
|
"--tournament"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
@ -81,7 +81,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1/osu.Game.Tournament.Tests.dll",
|
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net5.0/osu.Game.Tournament.Tests.dll",
|
||||||
"--tournament"
|
"--tournament"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
@ -94,7 +94,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1/osu.Game.Tournament.Tests.dll",
|
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/net5.0/osu.Game.Tournament.Tests.dll",
|
||||||
"--tournament"
|
"--tournament"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
@ -105,7 +105,7 @@
|
|||||||
"name": "Benchmark",
|
"name": "Benchmark",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/netcoreapp3.1/osu.Game.Benchmarks.dll",
|
"program": "${workspaceRoot}/osu.Game.Benchmarks/bin/Release/net5.0/osu.Game.Benchmarks.dll",
|
||||||
"args": [
|
"args": [
|
||||||
"--filter",
|
"--filter",
|
||||||
"*"
|
"*"
|
||||||
|
@ -36,8 +36,7 @@ If you are looking to install or test osu! without setting up a development envi
|
|||||||
|
|
||||||
- The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets.
|
- The iOS testflight link may fill up (Apple has a hard limit of 10,000 users). We reset it occasionally when this happens. Please do not ask about this. Check back regularly for link resets or follow [peppy](https://twitter.com/ppy) on twitter for announcements of link resets.
|
||||||
|
|
||||||
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore31&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
|
- When running on Windows 7 or 8.1, *[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/windows?tabs=net50&pivots=os-windows#dependencies)** may be required to correctly run .NET 5 applications if your operating system is not up-to-date with the latest service packs.
|
||||||
|
|
||||||
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
||||||
|
|
||||||
## Developing a custom ruleset
|
## Developing a custom ruleset
|
||||||
@ -50,7 +49,7 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir
|
|||||||
|
|
||||||
Please make sure you have the following prerequisites:
|
Please make sure you have the following prerequisites:
|
||||||
|
|
||||||
- A desktop platform with the [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download) or higher installed.
|
- A desktop platform with the [.NET 5.0 SDK](https://dotnet.microsoft.com/download) or higher installed.
|
||||||
- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).
|
- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).
|
||||||
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
|
||||||
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
|
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
|
||||||
|
@ -1,21 +1,68 @@
|
|||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{build}'
|
version: '{build}'
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2019
|
||||||
dotnet_csproj:
|
|
||||||
patch: true
|
|
||||||
file: 'osu.Game\osu.Game.csproj' # Use wildcard when it's able to exclude Xamarin projects
|
|
||||||
version: $(APPVEYOR_REPO_TAG_NAME)
|
|
||||||
before_build:
|
|
||||||
- ps: dotnet --info # Useful when version mismatch between CI and local
|
|
||||||
- ps: nuget restore -verbosity quiet # Only nuget.exe knows both new (.NET Core) and old (Xamarin) projects
|
|
||||||
test: off
|
test: off
|
||||||
skip_non_tags: true
|
skip_non_tags: true
|
||||||
configuration: Release
|
configuration: Release
|
||||||
build:
|
|
||||||
project: build\Desktop.proj # Skipping Xamarin Release that's slow and covered by fastlane
|
environment:
|
||||||
parallel: true
|
matrix:
|
||||||
verbosity: minimal
|
- job_name: osu-game
|
||||||
publish_nuget: true
|
- job_name: osu-ruleset
|
||||||
|
job_depends_on: osu-game
|
||||||
|
- job_name: taiko-ruleset
|
||||||
|
job_depends_on: osu-game
|
||||||
|
- job_name: catch-ruleset
|
||||||
|
job_depends_on: osu-game
|
||||||
|
- job_name: mania-ruleset
|
||||||
|
job_depends_on: osu-game
|
||||||
|
|
||||||
|
nuget:
|
||||||
|
project_feed: true
|
||||||
|
|
||||||
|
for:
|
||||||
|
-
|
||||||
|
matrix:
|
||||||
|
only:
|
||||||
|
- job_name: osu-game
|
||||||
|
build_script:
|
||||||
|
- cmd: dotnet pack osu.Game\osu.Game.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
-
|
||||||
|
matrix:
|
||||||
|
only:
|
||||||
|
- job_name: osu-ruleset
|
||||||
|
build_script:
|
||||||
|
- cmd: dotnet remove osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj reference osu.Game\osu.Game.csproj
|
||||||
|
- cmd: dotnet add osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||||
|
- cmd: dotnet pack osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
-
|
||||||
|
matrix:
|
||||||
|
only:
|
||||||
|
- job_name: taiko-ruleset
|
||||||
|
build_script:
|
||||||
|
- cmd: dotnet remove osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj reference osu.Game\osu.Game.csproj
|
||||||
|
- cmd: dotnet add osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||||
|
- cmd: dotnet pack osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
-
|
||||||
|
matrix:
|
||||||
|
only:
|
||||||
|
- job_name: catch-ruleset
|
||||||
|
build_script:
|
||||||
|
- cmd: dotnet remove osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj reference osu.Game\osu.Game.csproj
|
||||||
|
- cmd: dotnet add osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||||
|
- cmd: dotnet pack osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
-
|
||||||
|
matrix:
|
||||||
|
only:
|
||||||
|
- job_name: mania-ruleset
|
||||||
|
build_script:
|
||||||
|
- cmd: dotnet remove osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj reference osu.Game\osu.Game.csproj
|
||||||
|
- cmd: dotnet add osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj package ppy.osu.Game -v %APPVEYOR_REPO_TAG_NAME%
|
||||||
|
- cmd: dotnet pack osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj /p:Version=%APPVEYOR_REPO_TAG_NAME%
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: '**\*.nupkg'
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: Environment
|
- provider: Environment
|
||||||
name: nuget
|
name: nuget
|
@ -48,9 +48,12 @@ desc 'Deploy to play store'
|
|||||||
|
|
||||||
desc 'Compile the project'
|
desc 'Compile the project'
|
||||||
lane :build do |options|
|
lane :build do |options|
|
||||||
nuget_restore(
|
nuget_restore(project_path: 'osu.Android/osu.Android.csproj')
|
||||||
project_path: 'osu.sln'
|
nuget_restore(project_path: 'osu.Game/osu.Game.csproj')
|
||||||
)
|
nuget_restore(project_path: 'osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj')
|
||||||
|
|
||||||
souyuz(
|
souyuz(
|
||||||
build_configuration: 'Release',
|
build_configuration: 'Release',
|
||||||
@ -107,9 +110,12 @@ platform :ios do
|
|||||||
|
|
||||||
desc 'Compile the project'
|
desc 'Compile the project'
|
||||||
lane :build do
|
lane :build do
|
||||||
nuget_restore(
|
nuget_restore(project_path: 'osu.iOS/osu.iOS.csproj')
|
||||||
project_path: 'osu.sln'
|
nuget_restore(project_path: 'osu.Game/osu.Game.csproj')
|
||||||
)
|
nuget_restore(project_path: 'osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj')
|
||||||
|
nuget_restore(project_path: 'osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj')
|
||||||
|
|
||||||
souyuz(
|
souyuz(
|
||||||
platform: "ios",
|
platform: "ios",
|
||||||
|
10
global.json
10
global.json
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"sdk": {
|
|
||||||
"allowPrerelease": false,
|
|
||||||
"rollForward": "minor",
|
|
||||||
"version": "3.1.100"
|
|
||||||
},
|
|
||||||
"msbuild-sdks": {
|
|
||||||
"Microsoft.Build.Traversal": "3.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1202.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.1202.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.106.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.128.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -12,13 +13,14 @@ using Android.OS;
|
|||||||
using Android.Provider;
|
using Android.Provider;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
using osu.Framework.Android;
|
using osu.Framework.Android;
|
||||||
|
using osu.Game.Database;
|
||||||
|
|
||||||
namespace osu.Android
|
namespace osu.Android
|
||||||
{
|
{
|
||||||
[Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.FullUser, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = false, LaunchMode = LaunchMode.SingleInstance)]
|
[Activity(Theme = "@android:style/Theme.NoTitleBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.FullUser, SupportsPictureInPicture = false, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, HardwareAccelerated = false, LaunchMode = LaunchMode.SingleInstance)]
|
||||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*", DataMimeType = "*/*")]
|
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osz", DataHost = "*", DataMimeType = "*/*")]
|
||||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*", DataMimeType = "*/*")]
|
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "content", DataPathPattern = ".*\\\\.osk", DataHost = "*", DataMimeType = "*/*")]
|
||||||
[IntentFilter(new[] { Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] { "application/zip", "application/octet-stream" })]
|
[IntentFilter(new[] { Intent.ActionSend, Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeTypes = new[] { "application/zip", "application/octet-stream" })]
|
||||||
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataSchemes = new[] { "osu", "osump" })]
|
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataSchemes = new[] { "osu", "osump" })]
|
||||||
public class OsuGameActivity : AndroidGameActivity
|
public class OsuGameActivity : AndroidGameActivity
|
||||||
{
|
{
|
||||||
@ -54,43 +56,59 @@ namespace osu.Android
|
|||||||
{
|
{
|
||||||
case Intent.ActionDefault:
|
case Intent.ActionDefault:
|
||||||
if (intent.Scheme == ContentResolver.SchemeContent)
|
if (intent.Scheme == ContentResolver.SchemeContent)
|
||||||
handleImportFromUri(intent.Data);
|
handleImportFromUris(intent.Data);
|
||||||
else if (osu_url_schemes.Contains(intent.Scheme))
|
else if (osu_url_schemes.Contains(intent.Scheme))
|
||||||
game.HandleLink(intent.DataString);
|
game.HandleLink(intent.DataString);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Intent.ActionSend:
|
case Intent.ActionSend:
|
||||||
|
case Intent.ActionSendMultiple:
|
||||||
{
|
{
|
||||||
var content = intent.ClipData?.GetItemAt(0);
|
var uris = new List<Uri>();
|
||||||
if (content != null)
|
for (int i = 0; i < intent.ClipData?.ItemCount; i++)
|
||||||
handleImportFromUri(content.Uri);
|
{
|
||||||
|
var content = intent.ClipData?.GetItemAt(i);
|
||||||
|
if (content != null)
|
||||||
|
uris.Add(content.Uri);
|
||||||
|
}
|
||||||
|
handleImportFromUris(uris.ToArray());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleImportFromUri(Uri uri) => Task.Factory.StartNew(async () =>
|
private void handleImportFromUris(params Uri[] uris) => Task.Factory.StartNew(async () =>
|
||||||
{
|
{
|
||||||
// there are more performant overloads of this method, but this one is the most backwards-compatible
|
var tasks = new List<ImportTask>();
|
||||||
// (dates back to API 1).
|
|
||||||
var cursor = ContentResolver?.Query(uri, null, null, null, null);
|
|
||||||
|
|
||||||
if (cursor == null)
|
await Task.WhenAll(uris.Select(async uri =>
|
||||||
return;
|
{
|
||||||
|
// there are more performant overloads of this method, but this one is the most backwards-compatible
|
||||||
|
// (dates back to API 1).
|
||||||
|
var cursor = ContentResolver?.Query(uri, null, null, null, null);
|
||||||
|
|
||||||
cursor.MoveToFirst();
|
if (cursor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName);
|
cursor.MoveToFirst();
|
||||||
string filename = cursor.GetString(filenameColumn);
|
|
||||||
|
|
||||||
// SharpCompress requires archive streams to be seekable, which the stream opened by
|
var filenameColumn = cursor.GetColumnIndex(OpenableColumns.DisplayName);
|
||||||
// OpenInputStream() seems to not necessarily be.
|
string filename = cursor.GetString(filenameColumn);
|
||||||
// copy to an arbitrary-access memory stream to be able to proceed with the import.
|
|
||||||
var copy = new MemoryStream();
|
|
||||||
using (var stream = ContentResolver.OpenInputStream(uri))
|
|
||||||
await stream.CopyToAsync(copy);
|
|
||||||
|
|
||||||
await game.Import(copy, filename);
|
// SharpCompress requires archive streams to be seekable, which the stream opened by
|
||||||
|
// OpenInputStream() seems to not necessarily be.
|
||||||
|
// copy to an arbitrary-access memory stream to be able to proceed with the import.
|
||||||
|
var copy = new MemoryStream();
|
||||||
|
using (var stream = ContentResolver.OpenInputStream(uri))
|
||||||
|
await stream.CopyToAsync(copy);
|
||||||
|
|
||||||
|
lock (tasks)
|
||||||
|
{
|
||||||
|
tasks.Add(new ImportTask(copy, filename));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
await game.Import(tasks.ToArray());
|
||||||
}, TaskCreationOptions.LongRunning);
|
}, TaskCreationOptions.LongRunning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using osu.Desktop.Overlays;
|
using osu.Desktop.Overlays;
|
||||||
@ -56,16 +57,16 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
string stableInstallPath;
|
string stableInstallPath;
|
||||||
|
|
||||||
try
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
try
|
||||||
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
{
|
||||||
|
stableInstallPath = getStableInstallPathFromRegistry();
|
||||||
|
|
||||||
if (checkExists(stableInstallPath))
|
if (!string.IsNullOrEmpty(stableInstallPath) && checkExists(stableInstallPath))
|
||||||
return stableInstallPath;
|
return stableInstallPath;
|
||||||
}
|
}
|
||||||
catch
|
catch { }
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
||||||
@ -79,6 +80,13 @@ namespace osu.Desktop
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("windows")]
|
||||||
|
private string getStableInstallPathFromRegistry()
|
||||||
|
{
|
||||||
|
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||||
|
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
|
||||||
|
}
|
||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager()
|
protected override UpdateManager CreateUpdateManager()
|
||||||
{
|
{
|
||||||
switch (RuntimeInfo.OS)
|
switch (RuntimeInfo.OS)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
<Description>A free-to-win rhythm game. Rhythm is just a *click* away!</Description>
|
||||||
@ -24,16 +24,13 @@
|
|||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
|
<PackageReference Include="Microsoft.NETCore.Targets" Version="5.0.0" />
|
||||||
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
|
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
|
||||||
<PackageReference Include="ppy.squirrel.windows" Version="1.9.0.4" />
|
<PackageReference Include="ppy.squirrel.windows" Version="1.9.0.5" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
<PackageReference Include="DiscordRichPresence" Version="1.0.169" />
|
<PackageReference Include="DiscordRichPresence" Version="1.0.169" />
|
||||||
<!-- .NET 3.1 SDK seems to cause issues with a runtime specification. This will likely be resolved in .NET 5. -->
|
|
||||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Runtime.Handles" Version="4.3.0" />
|
|
||||||
<PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<EmbeddedResource Include="lazer.ico" />
|
<EmbeddedResource Include="lazer.ico" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Catch.Tests.dll"
|
"${workspaceRoot}/bin/Debug/net5.0/osu.Game.Rulesets.Catch.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug)",
|
"preLaunchTask": "Build (Debug)",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Catch.Tests.dll"
|
"${workspaceRoot}/bin/Release/net5.0/osu.Game.Rulesets.Catch.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release)",
|
"preLaunchTask": "Build (Release)",
|
||||||
|
151
osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs
Normal file
151
osu.Game.Rulesets.Catch.Tests/TestSceneLegacyBeatmapSkin.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
using osu.Game.Rulesets.Catch.Skinning;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private AudioManager audio { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager config)
|
||||||
|
{
|
||||||
|
config.BindWith(OsuSetting.BeatmapSkins, BeatmapSkins);
|
||||||
|
config.BindWith(OsuSetting.BeatmapColours, BeatmapColours);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, true)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin);
|
||||||
|
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true)]
|
||||||
|
[TestCase(false)]
|
||||||
|
public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColoursOverride(useBeatmapSkin);
|
||||||
|
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true)]
|
||||||
|
[TestCase(false)]
|
||||||
|
public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin);
|
||||||
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true, true)]
|
||||||
|
[TestCase(false, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
||||||
|
base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour);
|
||||||
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true, true)]
|
||||||
|
[TestCase(false, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, false);
|
||||||
|
base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour);
|
||||||
|
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true)]
|
||||||
|
[TestCase(false)]
|
||||||
|
public void TestBeatmapHyperDashColours(bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
ConfigureTest(useBeatmapSkin, true, true);
|
||||||
|
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestBeatmapSkin.HYPER_DASH_COLOUR);
|
||||||
|
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestBeatmapSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||||
|
AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == TestBeatmapSkin.HYPER_DASH_FRUIT_COLOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true)]
|
||||||
|
[TestCase(false)]
|
||||||
|
public void TestBeatmapHyperDashColoursOverride(bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new CatchCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
ConfigureTest(useBeatmapSkin, false, true);
|
||||||
|
AddAssert("is custom hyper dash colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashColour == TestSkin.HYPER_DASH_COLOUR);
|
||||||
|
AddAssert("is custom hyper dash after image colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashAfterImageColour == TestSkin.HYPER_DASH_AFTER_IMAGE_COLOUR);
|
||||||
|
AddAssert("is custom hyper dash fruit colours", () => ((CatchExposedPlayer)TestPlayer).UsableHyperDashFruitColour == TestSkin.HYPER_DASH_FRUIT_COLOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ExposedPlayer CreateTestPlayer(bool userHasCustomColours) => new CatchExposedPlayer(userHasCustomColours);
|
||||||
|
|
||||||
|
private class CatchExposedPlayer : ExposedPlayer
|
||||||
|
{
|
||||||
|
public CatchExposedPlayer(bool userHasCustomColours)
|
||||||
|
: base(userHasCustomColours)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color4 UsableHyperDashColour =>
|
||||||
|
GameplayClockContainer.ChildrenOfType<BeatmapSkinProvidingContainer>()
|
||||||
|
.First()
|
||||||
|
.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup(CatchSkinColour.HyperDash))?
|
||||||
|
.Value ?? Color4.Red;
|
||||||
|
|
||||||
|
public Color4 UsableHyperDashAfterImageColour =>
|
||||||
|
GameplayClockContainer.ChildrenOfType<BeatmapSkinProvidingContainer>()
|
||||||
|
.First()
|
||||||
|
.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup(CatchSkinColour.HyperDashAfterImage))?
|
||||||
|
.Value ?? Color4.Red;
|
||||||
|
|
||||||
|
public Color4 UsableHyperDashFruitColour =>
|
||||||
|
GameplayClockContainer.ChildrenOfType<BeatmapSkinProvidingContainer>()
|
||||||
|
.First()
|
||||||
|
.GetConfig<SkinCustomColourLookup, Color4>(new SkinCustomColourLookup(CatchSkinColour.HyperDashFruit))?
|
||||||
|
.Value ?? Color4.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CatchCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap
|
||||||
|
{
|
||||||
|
public CatchCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours)
|
||||||
|
: base(createBeatmap(), audio, hasColours)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IBeatmap createBeatmap() =>
|
||||||
|
new Beatmap
|
||||||
|
{
|
||||||
|
BeatmapInfo =
|
||||||
|
{
|
||||||
|
BeatmapSet = new BeatmapSetInfo(),
|
||||||
|
Ruleset = new CatchRuleset().RulesetInfo
|
||||||
|
},
|
||||||
|
HitObjects = { new Fruit { StartTime = 1816, X = 56, NewCombo = true } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -45,6 +45,11 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
float positionChange = Math.Abs(lastPosition - h.EffectiveX);
|
float positionChange = Math.Abs(lastPosition - h.EffectiveX);
|
||||||
double timeAvailable = h.StartTime - lastTime;
|
double timeAvailable = h.StartTime - lastTime;
|
||||||
|
|
||||||
|
if (timeAvailable < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// So we can either make it there without a dash or not.
|
// 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)
|
// 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.
|
// The case where positionChange > 0 and timeAvailable == 0 results in PositiveInfinity which provides expected beheaviour.
|
||||||
|
@ -5,6 +5,13 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>catch the fruit. to the beat.</Description>
|
<Description>catch the fruit. to the beat.</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="Nuget">
|
||||||
|
<Title>osu!catch (ruleset)</Title>
|
||||||
|
<PackageId>ppy.osu.Game.Rulesets.Catch</PackageId>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Mania.Tests.dll"
|
"${workspaceRoot}/bin/Debug/net5.0/osu.Game.Rulesets.Mania.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug)",
|
"preLaunchTask": "Build (Debug)",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Mania.Tests.dll"
|
"${workspaceRoot}/bin/Release/net5.0/osu.Game.Rulesets.Mania.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release)",
|
"preLaunchTask": "Build (Release)",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||||
|
@ -5,6 +5,13 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>smash the keys. to the beat.</Description>
|
<Description>smash the keys. to the beat.</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="Nuget">
|
||||||
|
<Title>osu!mania (ruleset)</Title>
|
||||||
|
<PackageId>ppy.osu.Game.Rulesets.Mania</PackageId>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Osu.Tests.dll"
|
"${workspaceRoot}/bin/Debug/net5.0/osu.Game.Rulesets.Osu.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug)",
|
"preLaunchTask": "Build (Debug)",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Osu.Tests.dll"
|
"${workspaceRoot}/bin/Release/net5.0/osu.Game.Rulesets.Osu.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release)",
|
"preLaunchTask": "Build (Release)",
|
||||||
|
@ -1,107 +1,91 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.IO.Stores;
|
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
{
|
{
|
||||||
public class TestSceneLegacyBeatmapSkin : ScreenTestScene
|
public class TestSceneLegacyBeatmapSkin : LegacyBeatmapSkinColourTest
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private AudioManager audio { get; set; }
|
private AudioManager audio { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager config)
|
||||||
|
{
|
||||||
|
config.BindWith(OsuSetting.BeatmapSkins, BeatmapSkins);
|
||||||
|
config.BindWith(OsuSetting.BeatmapColours, BeatmapColours);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(true, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, true)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapComboColours(bool userHasCustomColours, bool useBeatmapSkin)
|
||||||
|
{
|
||||||
|
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColours(userHasCustomColours, useBeatmapSkin);
|
||||||
|
AddAssert("is beatmap skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
[TestCase(false)]
|
[TestCase(false)]
|
||||||
public void TestBeatmapComboColours(bool customSkinColoursPresent)
|
public override void TestBeatmapComboColoursOverride(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
ExposedPlayer player = null;
|
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColoursOverride(useBeatmapSkin);
|
||||||
AddStep("load coloured beatmap", () => player = loadBeatmap(customSkinColoursPresent, true));
|
AddAssert("is user custom skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
AddUntilStep("wait for player", () => player.IsLoaded);
|
|
||||||
|
|
||||||
AddAssert("is beatmap skin colours", () => player.UsableComboColours.SequenceEqual(TestBeatmapSkin.Colours));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCase(true)]
|
||||||
public void TestBeatmapNoComboColours()
|
[TestCase(false)]
|
||||||
|
public override void TestBeatmapComboColoursOverrideWithDefaultColours(bool useBeatmapSkin)
|
||||||
{
|
{
|
||||||
ExposedPlayer player = null;
|
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, true);
|
||||||
|
base.TestBeatmapComboColoursOverrideWithDefaultColours(useBeatmapSkin);
|
||||||
AddStep("load no-colour beatmap", () => player = loadBeatmap(false, false));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
AddUntilStep("wait for player", () => player.IsLoaded);
|
|
||||||
|
|
||||||
AddAssert("is default user skin colours", () => player.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCase(true, true)]
|
||||||
public void TestBeatmapNoComboColoursSkinOverride()
|
[TestCase(false, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapNoComboColours(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
ExposedPlayer player = null;
|
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false);
|
||||||
|
base.TestBeatmapNoComboColours(useBeatmapSkin, useBeatmapColour);
|
||||||
AddStep("load custom-skin colour", () => player = loadBeatmap(true, false));
|
AddAssert("is default user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(SkinConfiguration.DefaultComboColours));
|
||||||
AddUntilStep("wait for player", () => player.IsLoaded);
|
|
||||||
|
|
||||||
AddAssert("is custom user skin colours", () => player.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExposedPlayer loadBeatmap(bool userHasCustomColours, bool beatmapHasColours)
|
[TestCase(true, true)]
|
||||||
|
[TestCase(false, true)]
|
||||||
|
[TestCase(true, false)]
|
||||||
|
[TestCase(false, false)]
|
||||||
|
public override void TestBeatmapNoComboColoursSkinOverride(bool useBeatmapSkin, bool useBeatmapColour)
|
||||||
{
|
{
|
||||||
ExposedPlayer player;
|
TestBeatmap = new OsuCustomSkinWorkingBeatmap(audio, false);
|
||||||
|
base.TestBeatmapNoComboColoursSkinOverride(useBeatmapSkin, useBeatmapColour);
|
||||||
Beatmap.Value = new CustomSkinWorkingBeatmap(audio, beatmapHasColours);
|
AddAssert("is custom user skin colours", () => TestPlayer.UsableComboColours.SequenceEqual(TestSkin.Colours));
|
||||||
|
|
||||||
LoadScreen(player = new ExposedPlayer(userHasCustomColours));
|
|
||||||
|
|
||||||
return player;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExposedPlayer : Player
|
private class OsuCustomSkinWorkingBeatmap : CustomSkinWorkingBeatmap
|
||||||
{
|
{
|
||||||
private readonly bool userHasCustomColours;
|
public OsuCustomSkinWorkingBeatmap(AudioManager audio, bool hasColours)
|
||||||
|
: base(createBeatmap(), audio, hasColours)
|
||||||
public ExposedPlayer(bool userHasCustomColours)
|
|
||||||
: base(new PlayerConfiguration
|
|
||||||
{
|
|
||||||
AllowPause = false,
|
|
||||||
ShowResults = false,
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
this.userHasCustomColours = userHasCustomColours;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
private static IBeatmap createBeatmap() =>
|
||||||
{
|
new Beatmap
|
||||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
|
||||||
dependencies.CacheAs<ISkinSource>(new TestSkin(userHasCustomColours));
|
|
||||||
return dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<Color4> UsableComboColours =>
|
|
||||||
GameplayClockContainer.ChildrenOfType<BeatmapSkinProvidingContainer>()
|
|
||||||
.First()
|
|
||||||
.GetConfig<GlobalSkinColours, IReadOnlyList<Color4>>(GlobalSkinColours.ComboColours)?.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap
|
|
||||||
{
|
|
||||||
private readonly bool hasColours;
|
|
||||||
|
|
||||||
public CustomSkinWorkingBeatmap(AudioManager audio, bool hasColours)
|
|
||||||
: base(new Beatmap
|
|
||||||
{
|
{
|
||||||
BeatmapInfo =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
@ -109,50 +93,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Ruleset = new OsuRuleset().RulesetInfo,
|
Ruleset = new OsuRuleset().RulesetInfo,
|
||||||
},
|
},
|
||||||
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
|
HitObjects = { new HitCircle { Position = new Vector2(256, 192) } }
|
||||||
}, null, null, audio)
|
};
|
||||||
{
|
|
||||||
this.hasColours = hasColours;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ISkin GetSkin() => new TestBeatmapSkin(BeatmapInfo, hasColours);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestBeatmapSkin : LegacyBeatmapSkin
|
|
||||||
{
|
|
||||||
public static Color4[] Colours { get; } =
|
|
||||||
{
|
|
||||||
new Color4(50, 100, 150, 255),
|
|
||||||
new Color4(40, 80, 120, 255),
|
|
||||||
};
|
|
||||||
|
|
||||||
public TestBeatmapSkin(BeatmapInfo beatmap, bool hasColours)
|
|
||||||
: base(beatmap, new ResourceStore<byte[]>(), null)
|
|
||||||
{
|
|
||||||
if (hasColours)
|
|
||||||
Configuration.AddComboColours(Colours);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestSkin : LegacySkin, ISkinSource
|
|
||||||
{
|
|
||||||
public static Color4[] Colours { get; } =
|
|
||||||
{
|
|
||||||
new Color4(150, 100, 50, 255),
|
|
||||||
new Color4(20, 20, 20, 255),
|
|
||||||
};
|
|
||||||
|
|
||||||
public TestSkin(bool hasCustomColours)
|
|
||||||
: base(new SkinInfo(), null, null, string.Empty)
|
|
||||||
{
|
|
||||||
if (hasCustomColours)
|
|
||||||
Configuration.AddComboColours(Colours);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event Action SourceChanged
|
|
||||||
{
|
|
||||||
add { }
|
|
||||||
remove { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,31 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
checkNextHitObject(null);
|
checkNextHitObject(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBeatmapColourDefault()
|
||||||
|
{
|
||||||
|
AddStep("enable user provider", () => testUserSkin.Enabled = true);
|
||||||
|
|
||||||
|
AddStep("enable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, true));
|
||||||
|
AddStep("enable beatmap colours", () => LocalConfig.Set<bool>(OsuSetting.BeatmapColours, true));
|
||||||
|
checkNextHitObject("beatmap");
|
||||||
|
|
||||||
|
AddStep("enable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, true));
|
||||||
|
AddStep("disable beatmap colours", () => LocalConfig.Set<bool>(OsuSetting.BeatmapColours, false));
|
||||||
|
checkNextHitObject("beatmap");
|
||||||
|
|
||||||
|
AddStep("disable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, false));
|
||||||
|
AddStep("enable beatmap colours", () => LocalConfig.Set<bool>(OsuSetting.BeatmapColours, true));
|
||||||
|
checkNextHitObject("user");
|
||||||
|
|
||||||
|
AddStep("disable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, false));
|
||||||
|
AddStep("disable beatmap colours", () => LocalConfig.Set<bool>(OsuSetting.BeatmapColours, false));
|
||||||
|
checkNextHitObject("user");
|
||||||
|
|
||||||
|
AddStep("disable user provider", () => testUserSkin.Enabled = false);
|
||||||
|
checkNextHitObject(null);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkNextHitObject(string skin) =>
|
private void checkNextHitObject(string skin) =>
|
||||||
AddUntilStep($"check skin from {skin}", () =>
|
AddUntilStep($"check skin from {skin}", () =>
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@ -34,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase(true)]
|
[TestCase(true)]
|
||||||
public void TestLongSpinner(bool autoplay)
|
public void TestLongSpinner(bool autoplay)
|
||||||
{
|
{
|
||||||
AddStep("Very short spinner", () => SetContents(() => testSingle(5, autoplay, 2000)));
|
AddStep("Very long spinner", () => SetContents(() => testSingle(5, autoplay, 4000)));
|
||||||
AddUntilStep("Wait for completion", () => drawableSpinner.Result.HasResult);
|
AddUntilStep("Wait for completion", () => drawableSpinner.Result.HasResult);
|
||||||
AddUntilStep("Check correct progress", () => drawableSpinner.Progress == (autoplay ? 1 : 0));
|
AddUntilStep("Check correct progress", () => drawableSpinner.Progress == (autoplay ? 1 : 0));
|
||||||
}
|
}
|
||||||
@ -55,7 +57,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
var spinner = new Spinner
|
var spinner = new Spinner
|
||||||
{
|
{
|
||||||
StartTime = Time.Current + delay,
|
StartTime = Time.Current + delay,
|
||||||
EndTime = Time.Current + delay + length
|
EndTime = Time.Current + delay + length,
|
||||||
|
Samples = new List<HitSampleInfo>
|
||||||
|
{
|
||||||
|
new HitSampleInfo("hitnormal")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -30,6 +30,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles
|
|||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos);
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos);
|
||||||
|
|
||||||
public override Quad SelectionQuad => DrawableObject.HitArea.ScreenSpaceDrawQuad;
|
public override Quad SelectionQuad => CirclePiece.ScreenSpaceDrawQuad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
|||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private IEditorChangeHandler changeHandler { get; set; }
|
private IEditorChangeHandler changeHandler { get; set; }
|
||||||
|
|
||||||
|
public override Quad SelectionQuad => BodyPiece.ScreenSpaceDrawQuad;
|
||||||
|
|
||||||
private readonly BindableList<PathControlPoint> controlPoints = new BindableList<PathControlPoint>();
|
private readonly BindableList<PathControlPoint> controlPoints = new BindableList<PathControlPoint>();
|
||||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||||
|
|
||||||
|
@ -236,7 +236,20 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObjects">The hit objects to calculate a quad for.</param>
|
/// <param name="hitObjects">The hit objects to calculate a quad for.</param>
|
||||||
private Quad getSurroundingQuad(OsuHitObject[] hitObjects) =>
|
private Quad getSurroundingQuad(OsuHitObject[] hitObjects) =>
|
||||||
getSurroundingQuad(hitObjects.SelectMany(h => new[] { h.Position, h.EndPosition }));
|
getSurroundingQuad(hitObjects.SelectMany(h =>
|
||||||
|
{
|
||||||
|
if (h is IHasPath path)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
h.Position,
|
||||||
|
// can't use EndPosition for reverse slider cases.
|
||||||
|
h.Position + path.Path.PositionAt(1)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new[] { h.Position };
|
||||||
|
}));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a gamefield-space quad surrounding the provided points.
|
/// Returns a gamefield-space quad surrounding the provided points.
|
||||||
|
@ -130,12 +130,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
if (tracking.NewValue)
|
if (tracking.NewValue)
|
||||||
{
|
{
|
||||||
spinningSample?.Play();
|
spinningSample?.Play(!spinningSample.IsPlaying);
|
||||||
spinningSample?.VolumeTo(1, 200);
|
spinningSample?.VolumeTo(1, 300);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spinningSample?.VolumeTo(0, 200).Finally(_ => spinningSample.Stop());
|
spinningSample?.VolumeTo(0, 300).OnComplete(_ => spinningSample.Stop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,13 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>click the circles. to the beat.</Description>
|
<Description>click the circles. to the beat.</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="Nuget">
|
||||||
|
<Title>osu! (ruleset)</Title>
|
||||||
|
<PackageId>ppy.osu.Game.Rulesets.Osu</PackageId>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp3.1/osu.Game.Rulesets.Taiko.Tests.dll"
|
"${workspaceRoot}/bin/Debug/net5.0/osu.Game.Rulesets.Taiko.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug)",
|
"preLaunchTask": "Build (Debug)",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Release/netcoreapp3.1/osu.Game.Rulesets.Taiko.Tests.dll"
|
"${workspaceRoot}/bin/Release/net5.0/osu.Game.Rulesets.Taiko.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release)",
|
"preLaunchTask": "Build (Release)",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Mods
|
namespace osu.Game.Rulesets.Taiko.Mods
|
||||||
@ -8,5 +9,16 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
|||||||
public class TaikoModEasy : ModEasy
|
public class TaikoModEasy : ModEasy
|
||||||
{
|
{
|
||||||
public override string Description => @"Beats move slower, and less accuracy required!";
|
public override string Description => @"Beats move slower, and less accuracy required!";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplier factor added to the scrolling speed.
|
||||||
|
/// </summary>
|
||||||
|
private const double slider_multiplier = 0.8;
|
||||||
|
|
||||||
|
public override void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
base.ApplyToDifficulty(difficulty);
|
||||||
|
difficulty.SliderMultiplier *= slider_multiplier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Mods
|
namespace osu.Game.Rulesets.Taiko.Mods
|
||||||
@ -9,5 +10,21 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
|||||||
{
|
{
|
||||||
public override double ScoreMultiplier => 1.06;
|
public override double ScoreMultiplier => 1.06;
|
||||||
public override bool Ranked => true;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplier factor added to the scrolling speed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This factor is made up of two parts: the base part (1.4) and the aspect ratio adjustment (4/3).
|
||||||
|
/// Stable applies the latter by dividing the width of the user's display by the width of a display with the same height, but 4:3 aspect ratio.
|
||||||
|
/// TODO: Revisit if taiko playfield ever changes away from a hard-coded 16:9 (see https://github.com/ppy/osu/issues/5685).
|
||||||
|
/// </remarks>
|
||||||
|
private const double slider_multiplier = 1.4 * 4 / 3;
|
||||||
|
|
||||||
|
public override void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
base.ApplyToDifficulty(difficulty);
|
||||||
|
difficulty.SliderMultiplier *= slider_multiplier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,13 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Description>bash the drum. to the beat.</Description>
|
<Description>bash the drum. to the beat.</Description>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="Nuget">
|
||||||
|
<Title>osu!taiko (ruleset)</Title>
|
||||||
|
<PackageId>ppy.osu.Game.Rulesets.Taiko</PackageId>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
62
osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs
Normal file
62
osu.Game.Tests/NonVisual/OngoingOperationTrackerTest.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Screens.OnlinePlay;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.NonVisual
|
||||||
|
{
|
||||||
|
[HeadlessTest]
|
||||||
|
public class OngoingOperationTrackerTest : OsuTestScene
|
||||||
|
{
|
||||||
|
private OngoingOperationTracker tracker;
|
||||||
|
private IBindable<bool> operationInProgress;
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
AddStep("create tracker", () => Child = tracker = new OngoingOperationTracker());
|
||||||
|
AddStep("bind to operation status", () => operationInProgress = tracker.InProgress.GetBoundCopy());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOperationTracking()
|
||||||
|
{
|
||||||
|
IDisposable firstOperation = null;
|
||||||
|
IDisposable secondOperation = null;
|
||||||
|
|
||||||
|
AddStep("begin first operation", () => firstOperation = tracker.BeginOperation());
|
||||||
|
AddAssert("first operation in progress", () => operationInProgress.Value);
|
||||||
|
|
||||||
|
AddStep("cannot start another operation",
|
||||||
|
() => Assert.Throws<InvalidOperationException>(() => tracker.BeginOperation()));
|
||||||
|
|
||||||
|
AddStep("end first operation", () => firstOperation.Dispose());
|
||||||
|
AddAssert("first operation is ended", () => !operationInProgress.Value);
|
||||||
|
|
||||||
|
AddStep("start second operation", () => secondOperation = tracker.BeginOperation());
|
||||||
|
AddAssert("second operation in progress", () => operationInProgress.Value);
|
||||||
|
|
||||||
|
AddStep("dispose first operation again", () => firstOperation.Dispose());
|
||||||
|
AddAssert("second operation still in progress", () => operationInProgress.Value);
|
||||||
|
|
||||||
|
AddStep("dispose second operation", () => secondOperation.Dispose());
|
||||||
|
AddAssert("second operation is ended", () => !operationInProgress.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOperationDisposalAfterTracker()
|
||||||
|
{
|
||||||
|
IDisposable operation = null;
|
||||||
|
|
||||||
|
AddStep("begin operation", () => operation = tracker.BeginOperation());
|
||||||
|
AddStep("dispose tracker", () => tracker.Expire());
|
||||||
|
AddStep("end operation", () => operation.Dispose());
|
||||||
|
AddAssert("operation is ended", () => !operationInProgress.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
@ -5,7 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Configuration.Tracking;
|
using osu.Framework.Configuration.Tracking;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
|
@ -5,6 +5,8 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -13,6 +15,9 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
public class TestSceneEditorSummaryTimeline : EditorClockTestScene
|
||||||
{
|
{
|
||||||
|
[Cached(typeof(EditorBeatmap))]
|
||||||
|
private readonly EditorBeatmap editorBeatmap = new EditorBeatmap(new OsuBeatmap());
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
|
@ -17,10 +17,12 @@ using osu.Framework.Utils;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Objects.Legacy;
|
using osu.Game.Rulesets.Objects.Legacy;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -129,6 +131,31 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddUntilStep("no DHOs shown", () => !this.ChildrenOfType<DrawableTestHitObject>().Any());
|
AddUntilStep("no DHOs shown", () => !this.ChildrenOfType<DrawableTestHitObject>().Any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestApplyHitResultOnKilled()
|
||||||
|
{
|
||||||
|
ManualClock clock = null;
|
||||||
|
bool anyJudged = false;
|
||||||
|
|
||||||
|
void onNewResult(JudgementResult _) => anyJudged = true;
|
||||||
|
|
||||||
|
var beatmap = new Beatmap();
|
||||||
|
beatmap.HitObjects.Add(new TestKilledHitObject { Duration = 20 });
|
||||||
|
|
||||||
|
createTest(beatmap, 10, () => new FramedClock(clock = new ManualClock()));
|
||||||
|
|
||||||
|
AddStep("subscribe to new result", () =>
|
||||||
|
{
|
||||||
|
anyJudged = false;
|
||||||
|
drawableRuleset.NewResult += onNewResult;
|
||||||
|
});
|
||||||
|
AddStep("skip past object", () => clock.CurrentTime = beatmap.HitObjects[0].GetEndTime() + 1000);
|
||||||
|
|
||||||
|
AddAssert("object judged", () => anyJudged);
|
||||||
|
|
||||||
|
AddStep("clean up", () => drawableRuleset.NewResult -= onNewResult);
|
||||||
|
}
|
||||||
|
|
||||||
private void createTest(IBeatmap beatmap, int poolSize, Func<IFrameBasedClock> createClock = null) => AddStep("create test", () =>
|
private void createTest(IBeatmap beatmap, int poolSize, Func<IFrameBasedClock> createClock = null) => AddStep("create test", () =>
|
||||||
{
|
{
|
||||||
var ruleset = new TestPoolingRuleset();
|
var ruleset = new TestPoolingRuleset();
|
||||||
@ -192,6 +219,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
RegisterPool<TestHitObject, DrawableTestHitObject>(poolSize);
|
RegisterPool<TestHitObject, DrawableTestHitObject>(poolSize);
|
||||||
|
RegisterPool<TestKilledHitObject, DrawableTestKilledHitObject>(poolSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObjectLifetimeEntry CreateLifetimeEntry(HitObject hitObject) => new TestHitObjectLifetimeEntry(hitObject);
|
protected override HitObjectLifetimeEntry CreateLifetimeEntry(HitObject hitObject) => new TestHitObjectLifetimeEntry(hitObject);
|
||||||
@ -220,19 +248,30 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken)
|
protected override IEnumerable<TestHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
yield return new TestHitObject
|
switch (original)
|
||||||
{
|
{
|
||||||
StartTime = original.StartTime,
|
case TestKilledHitObject h:
|
||||||
Duration = 250
|
yield return h;
|
||||||
};
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
yield return new TestHitObject
|
||||||
|
{
|
||||||
|
StartTime = original.StartTime,
|
||||||
|
Duration = 250
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region HitObject
|
#region HitObjects
|
||||||
|
|
||||||
private class TestHitObject : ConvertHitObject
|
private class TestHitObject : ConvertHitObject, IHasDuration
|
||||||
{
|
{
|
||||||
public double EndTime => StartTime + Duration;
|
public double EndTime => StartTime + Duration;
|
||||||
|
|
||||||
@ -287,6 +326,30 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestKilledHitObject : TestHitObject
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DrawableTestKilledHitObject : DrawableHitObject<TestKilledHitObject>
|
||||||
|
{
|
||||||
|
public DrawableTestKilledHitObject()
|
||||||
|
: base(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||||
|
{
|
||||||
|
base.UpdateHitStateTransforms(state);
|
||||||
|
Expire();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnKilled()
|
||||||
|
{
|
||||||
|
base.OnKilled();
|
||||||
|
ApplyResult(r => r.Type = r.Judgement.MinResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -179,7 +179,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -74,6 +75,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
switch (args.Action)
|
switch (args.Action)
|
||||||
{
|
{
|
||||||
case NotifyCollectionChangedAction.Add:
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
Debug.Assert(args.NewItems != null);
|
||||||
|
|
||||||
foreach (int user in args.NewItems)
|
foreach (int user in args.NewItems)
|
||||||
{
|
{
|
||||||
if (user == api.LocalUser.Value.Id)
|
if (user == api.LocalUser.Value.Id)
|
||||||
@ -83,6 +86,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NotifyCollectionChangedAction.Remove:
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
Debug.Assert(args.OldItems != null);
|
||||||
|
|
||||||
foreach (int user in args.OldItems)
|
foreach (int user in args.OldItems)
|
||||||
{
|
{
|
||||||
if (user == api.LocalUser.Value.Id)
|
if (user == api.LocalUser.Value.Id)
|
||||||
@ -298,7 +303,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
internal class TestKeyBindingContainer : KeyBindingContainer<TestAction>
|
||||||
{
|
{
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => new[]
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => new[]
|
||||||
{
|
{
|
||||||
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
new KeyBinding(InputKey.MouseLeft, TestAction.Down),
|
||||||
};
|
};
|
||||||
|
@ -201,11 +201,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDownloadButtonHiddenInitiallyWhenBeatmapExists()
|
public void TestDownloadButtonHiddenWhenBeatmapExists()
|
||||||
{
|
{
|
||||||
createPlaylist(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo);
|
createPlaylist(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo);
|
||||||
|
|
||||||
AddAssert("download button hidden", () => !playlist.ChildrenOfType<BeatmapDownloadTrackingComposite>().Single().IsPresent);
|
assertDownloadButtonVisible(false);
|
||||||
|
|
||||||
|
AddStep("delete beatmap set", () => manager.Delete(manager.QueryBeatmapSets(_ => true).Single()));
|
||||||
|
assertDownloadButtonVisible(true);
|
||||||
|
|
||||||
|
AddStep("undelete beatmap set", () => manager.Undelete(manager.QueryBeatmapSets(_ => true).Single()));
|
||||||
|
assertDownloadButtonVisible(false);
|
||||||
|
|
||||||
|
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
|
||||||
|
() => playlist.ChildrenOfType<BeatmapDownloadTrackingComposite>().Single().Alpha == (visible ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -222,6 +231,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddAssert("download buttons shown", () => playlist.ChildrenOfType<BeatmapDownloadTrackingComposite>().All(d => d.IsPresent));
|
AddAssert("download buttons shown", () => playlist.ChildrenOfType<BeatmapDownloadTrackingComposite>().All(d => d.IsPresent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExplicitBeatmapItem()
|
||||||
|
{
|
||||||
|
var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo;
|
||||||
|
beatmap.BeatmapSet.OnlineInfo.HasExplicitContent = true;
|
||||||
|
|
||||||
|
createPlaylist(beatmap);
|
||||||
|
}
|
||||||
|
|
||||||
private void moveToItem(int index, Vector2? offset = null)
|
private void moveToItem(int index, Vector2? offset = null)
|
||||||
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<OsuRearrangeableListItem<PlaylistItem>>().ElementAt(index), offset));
|
=> AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType<OsuRearrangeableListItem<PlaylistItem>>().ElementAt(index), offset));
|
||||||
|
|
||||||
|
@ -1,32 +1,81 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using osu.Game.Overlays;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
public class TestSceneBeatmapListingOverlay : OsuTestScene
|
public class TestSceneBeatmapListingOverlay : OsuTestScene
|
||||||
{
|
{
|
||||||
protected override bool UseOnlineAPI => true;
|
private readonly List<APIBeatmapSet> setsForResponse = new List<APIBeatmapSet>();
|
||||||
|
|
||||||
private readonly BeatmapListingOverlay overlay;
|
private BeatmapListingOverlay overlay;
|
||||||
|
|
||||||
public TestSceneBeatmapListingOverlay()
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
{
|
{
|
||||||
Add(overlay = new BeatmapListingOverlay());
|
Child = overlay = new BeatmapListingOverlay { State = { Value = Visibility.Visible } };
|
||||||
|
|
||||||
|
((DummyAPIAccess)API).HandleRequest = req =>
|
||||||
|
{
|
||||||
|
if (req is SearchBeatmapSetsRequest searchBeatmapSetsRequest)
|
||||||
|
{
|
||||||
|
searchBeatmapSetsRequest.TriggerSuccess(new SearchBeatmapSetsResponse
|
||||||
|
{
|
||||||
|
BeatmapSets = setsForResponse,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestShow()
|
public void TestNoBeatmapsPlaceholder()
|
||||||
{
|
{
|
||||||
AddStep("Show", overlay.Show);
|
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||||
|
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||||
|
|
||||||
|
AddStep("fetch for 1 beatmap", () => fetchFor(CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet));
|
||||||
|
AddUntilStep("placeholder hidden", () => !overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().Any());
|
||||||
|
|
||||||
|
AddStep("fetch for 0 beatmaps", () => fetchFor());
|
||||||
|
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||||
|
|
||||||
|
// fetch once more to ensure nothing happens in displaying placeholder again when it already is present.
|
||||||
|
AddStep("fetch for 0 beatmaps again", () => fetchFor());
|
||||||
|
AddUntilStep("placeholder shown", () => overlay.ChildrenOfType<BeatmapListingOverlay.NotFoundDrawable>().SingleOrDefault()?.IsPresent == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
private void fetchFor(params BeatmapSetInfo[] beatmaps)
|
||||||
public void TestHide()
|
|
||||||
{
|
{
|
||||||
AddStep("Hide", overlay.Hide);
|
setsForResponse.Clear();
|
||||||
|
setsForResponse.AddRange(beatmaps.Select(b => new TestAPIBeatmapSet(b)));
|
||||||
|
|
||||||
|
// trigger arbitrary change for fetching.
|
||||||
|
overlay.ChildrenOfType<BeatmapListingSearchControl>().Single().Query.TriggerChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestAPIBeatmapSet : APIBeatmapSet
|
||||||
|
{
|
||||||
|
private readonly BeatmapSetInfo beatmapSet;
|
||||||
|
|
||||||
|
public TestAPIBeatmapSet(BeatmapSetInfo beatmapSet)
|
||||||
|
{
|
||||||
|
this.beatmapSet = beatmapSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) => beatmapSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,8 +231,19 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
AddAssert("shown beatmaps of current ruleset", () => overlay.Header.HeaderContent.Picker.Difficulties.All(b => b.Beatmap.Ruleset.Equals(overlay.Header.RulesetSelector.Current.Value)));
|
||||||
AddAssert("left-most beatmap selected", () => overlay.Header.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
AddAssert("left-most beatmap selected", () => overlay.Header.HeaderContent.Picker.Difficulties.First().State == BeatmapPicker.DifficultySelectorState.Selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExplicitBeatmap()
|
||||||
|
{
|
||||||
|
AddStep("show explicit map", () =>
|
||||||
|
{
|
||||||
|
var beatmapSet = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||||
|
beatmapSet.OnlineInfo.HasExplicitContent = true;
|
||||||
|
overlay.ShowBeatmapSet(beatmapSet);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -299,12 +310,12 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private void downloadAssert(bool shown)
|
private void downloadAssert(bool shown)
|
||||||
{
|
{
|
||||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.DownloadButtonsVisible == shown);
|
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.Header.HeaderContent.DownloadButtonsVisible == shown);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
||||||
{
|
{
|
||||||
public new Header Header => base.Header;
|
public new BeatmapSetHeader Header => base.Header;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,13 +99,16 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(RulesetStore rulesets)
|
private void load(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
var normal = CreateWorkingBeatmap(Ruleset.Value).BeatmapSetInfo;
|
var normal = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||||
normal.OnlineInfo.HasVideo = true;
|
normal.OnlineInfo.HasVideo = true;
|
||||||
normal.OnlineInfo.HasStoryboard = true;
|
normal.OnlineInfo.HasStoryboard = true;
|
||||||
|
|
||||||
var undownloadable = getUndownloadableBeatmapSet();
|
var undownloadable = getUndownloadableBeatmapSet();
|
||||||
var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets);
|
var manyDifficulties = getManyDifficultiesBeatmapSet(rulesets);
|
||||||
|
|
||||||
|
var explicitMap = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet;
|
||||||
|
explicitMap.OnlineInfo.HasExplicitContent = true;
|
||||||
|
|
||||||
Child = new BasicScrollContainer
|
Child = new BasicScrollContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
@ -121,9 +124,11 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
new GridBeatmapPanel(normal),
|
new GridBeatmapPanel(normal),
|
||||||
new GridBeatmapPanel(undownloadable),
|
new GridBeatmapPanel(undownloadable),
|
||||||
new GridBeatmapPanel(manyDifficulties),
|
new GridBeatmapPanel(manyDifficulties),
|
||||||
|
new GridBeatmapPanel(explicitMap),
|
||||||
new ListBeatmapPanel(normal),
|
new ListBeatmapPanel(normal),
|
||||||
new ListBeatmapPanel(undownloadable),
|
new ListBeatmapPanel(undownloadable),
|
||||||
new ListBeatmapPanel(manyDifficulties),
|
new ListBeatmapPanel(manyDifficulties),
|
||||||
|
new ListBeatmapPanel(explicitMap)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -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.Game.Overlays;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
[Description("uses online API")]
|
||||||
|
public class TestSceneOnlineBeatmapListingOverlay : OsuTestScene
|
||||||
|
{
|
||||||
|
protected override bool UseOnlineAPI => true;
|
||||||
|
|
||||||
|
private readonly BeatmapListingOverlay overlay;
|
||||||
|
|
||||||
|
public TestSceneOnlineBeatmapListingOverlay()
|
||||||
|
{
|
||||||
|
Add(overlay = new BeatmapListingOverlay());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestShow()
|
||||||
|
{
|
||||||
|
AddStep("Show", overlay.Show);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHide()
|
||||||
|
{
|
||||||
|
AddStep("Hide", overlay.Hide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,8 @@ using osu.Game.Overlays.Comments;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -16,13 +18,33 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Cached]
|
[Cached]
|
||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
private VotePill votePill;
|
[Cached]
|
||||||
|
private LoginOverlay login;
|
||||||
|
|
||||||
|
private TestPill votePill;
|
||||||
|
private readonly Container pillContainer;
|
||||||
|
|
||||||
|
public TestSceneVotePill()
|
||||||
|
{
|
||||||
|
AddRange(new Drawable[]
|
||||||
|
{
|
||||||
|
pillContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
login = new LoginOverlay()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestUserCommentPill()
|
public void TestUserCommentPill()
|
||||||
{
|
{
|
||||||
|
AddStep("Hide login overlay", () => login.Hide());
|
||||||
AddStep("Log in", logIn);
|
AddStep("Log in", logIn);
|
||||||
AddStep("User comment", () => addVotePill(getUserComment()));
|
AddStep("User comment", () => addVotePill(getUserComment()));
|
||||||
|
AddAssert("Background is transparent", () => votePill.Background.Alpha == 0);
|
||||||
AddStep("Click", () => votePill.Click());
|
AddStep("Click", () => votePill.Click());
|
||||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
AddAssert("Not loading", () => !votePill.IsLoading);
|
||||||
}
|
}
|
||||||
@ -30,8 +52,10 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestRandomCommentPill()
|
public void TestRandomCommentPill()
|
||||||
{
|
{
|
||||||
|
AddStep("Hide login overlay", () => login.Hide());
|
||||||
AddStep("Log in", logIn);
|
AddStep("Log in", logIn);
|
||||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||||
|
AddAssert("Background is visible", () => votePill.Background.Alpha == 1);
|
||||||
AddStep("Click", () => votePill.Click());
|
AddStep("Click", () => votePill.Click());
|
||||||
AddAssert("Loading", () => votePill.IsLoading);
|
AddAssert("Loading", () => votePill.IsLoading);
|
||||||
}
|
}
|
||||||
@ -39,10 +63,11 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestOfflineRandomCommentPill()
|
public void TestOfflineRandomCommentPill()
|
||||||
{
|
{
|
||||||
|
AddStep("Hide login overlay", () => login.Hide());
|
||||||
AddStep("Log out", API.Logout);
|
AddStep("Log out", API.Logout);
|
||||||
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
AddStep("Random comment", () => addVotePill(getRandomComment()));
|
||||||
AddStep("Click", () => votePill.Click());
|
AddStep("Click", () => votePill.Click());
|
||||||
AddAssert("Not loading", () => !votePill.IsLoading);
|
AddAssert("Login overlay is visible", () => login.State.Value == Visibility.Visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logIn() => API.Login("localUser", "password");
|
private void logIn() => API.Login("localUser", "password");
|
||||||
@ -63,12 +88,22 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private void addVotePill(Comment comment)
|
private void addVotePill(Comment comment)
|
||||||
{
|
{
|
||||||
Clear();
|
pillContainer.Clear();
|
||||||
Add(votePill = new VotePill(comment)
|
pillContainer.Child = votePill = new TestPill(comment)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestPill : VotePill
|
||||||
|
{
|
||||||
|
public new Box Background => base.Background;
|
||||||
|
|
||||||
|
public TestPill(Comment comment)
|
||||||
|
: base(comment)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,10 @@ using osu.Framework.Platform;
|
|||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Screens.OnlinePlay;
|
using osu.Game.Screens.OnlinePlay;
|
||||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
|
||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -85,8 +83,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
|
|
||||||
AddStep("move mouse to create button", () =>
|
AddStep("move mouse to create button", () =>
|
||||||
{
|
{
|
||||||
var footer = match.ChildrenOfType<Footer>().Single();
|
InputManager.MoveMouseTo(this.ChildrenOfType<PlaylistsMatchSettingsOverlay.CreateRoomButton>().Single());
|
||||||
InputManager.MoveMouseTo(footer.ChildrenOfType<OsuButton>().Single());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.BeatmapListing;
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
@ -19,9 +20,18 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
[Cached]
|
[Cached]
|
||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
private readonly BeatmapListingSearchControl control;
|
private BeatmapListingSearchControl control;
|
||||||
|
|
||||||
public TestSceneBeatmapListingSearchControl()
|
private OsuConfigManager localConfig;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Dependencies.Cache(localConfig = new OsuConfigManager(LocalStorage));
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
OsuSpriteText query;
|
OsuSpriteText query;
|
||||||
OsuSpriteText ruleset;
|
OsuSpriteText ruleset;
|
||||||
@ -31,30 +41,34 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
OsuSpriteText extra;
|
OsuSpriteText extra;
|
||||||
OsuSpriteText ranks;
|
OsuSpriteText ranks;
|
||||||
OsuSpriteText played;
|
OsuSpriteText played;
|
||||||
|
OsuSpriteText explicitMap;
|
||||||
|
|
||||||
Add(control = new BeatmapListingSearchControl
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
control = new BeatmapListingSearchControl
|
||||||
Origin = Anchor.Centre,
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new FillFlowContainer
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Spacing = new Vector2(0, 5),
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
query = new OsuSpriteText(),
|
Anchor = Anchor.Centre,
|
||||||
ruleset = new OsuSpriteText(),
|
Origin = Anchor.Centre,
|
||||||
category = new OsuSpriteText(),
|
},
|
||||||
genre = new OsuSpriteText(),
|
new FillFlowContainer
|
||||||
language = new OsuSpriteText(),
|
{
|
||||||
extra = new OsuSpriteText(),
|
AutoSizeAxes = Axes.Both,
|
||||||
ranks = new OsuSpriteText(),
|
Direction = FillDirection.Vertical,
|
||||||
played = new OsuSpriteText()
|
Spacing = new Vector2(0, 5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
query = new OsuSpriteText(),
|
||||||
|
ruleset = new OsuSpriteText(),
|
||||||
|
category = new OsuSpriteText(),
|
||||||
|
genre = new OsuSpriteText(),
|
||||||
|
language = new OsuSpriteText(),
|
||||||
|
extra = new OsuSpriteText(),
|
||||||
|
ranks = new OsuSpriteText(),
|
||||||
|
played = new OsuSpriteText(),
|
||||||
|
explicitMap = new OsuSpriteText(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
|
control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
|
||||||
control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
|
control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
|
||||||
@ -64,7 +78,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
control.Extra.BindCollectionChanged((u, v) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true);
|
control.Extra.BindCollectionChanged((u, v) => extra.Text = $"Extra: {(control.Extra.Any() ? string.Join('.', control.Extra.Select(i => i.ToString().ToLowerInvariant())) : "")}", true);
|
||||||
control.Ranks.BindCollectionChanged((u, v) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true);
|
control.Ranks.BindCollectionChanged((u, v) => ranks.Text = $"Ranks: {(control.Ranks.Any() ? string.Join('.', control.Ranks.Select(i => i.ToString())) : "")}", true);
|
||||||
control.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true);
|
control.Played.BindValueChanged(p => played.Text = $"Played: {p.NewValue}", true);
|
||||||
}
|
control.ExplicitContent.BindValueChanged(e => explicitMap.Text = $"Explicit Maps: {e.NewValue}", true);
|
||||||
|
});
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCovers()
|
public void TestCovers()
|
||||||
@ -74,6 +89,22 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
AddStep("Set null beatmap", () => control.BeatmapSet = null);
|
AddStep("Set null beatmap", () => control.BeatmapSet = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExplicitConfig()
|
||||||
|
{
|
||||||
|
AddStep("configure explicit content to allowed", () => localConfig.Set(OsuSetting.ShowOnlineExplicitContent, true));
|
||||||
|
AddAssert("explicit control set to show", () => control.ExplicitContent.Value == SearchExplicit.Show);
|
||||||
|
|
||||||
|
AddStep("configure explicit content to disallowed", () => localConfig.Set(OsuSetting.ShowOnlineExplicitContent, false));
|
||||||
|
AddAssert("explicit control set to hide", () => control.ExplicitContent.Value == SearchExplicit.Hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
localConfig?.Dispose();
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
|
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
|
||||||
{
|
{
|
||||||
OnlineInfo = new BeatmapSetOnlineInfo
|
OnlineInfo = new BeatmapSetOnlineInfo
|
||||||
|
@ -40,6 +40,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
{
|
{
|
||||||
|
SelectedMods.Value = Array.Empty<Mod>();
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
modSelect = new TestModSelectOverlay
|
modSelect = new TestModSelectOverlay
|
||||||
@ -134,6 +135,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestExternallySetCustomizedMod()
|
public void TestExternallySetCustomizedMod()
|
||||||
{
|
{
|
||||||
|
changeRuleset(0);
|
||||||
|
|
||||||
AddStep("set customized mod externally", () => SelectedMods.Value = new[] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } });
|
AddStep("set customized mod externally", () => SelectedMods.Value = new[] { new OsuModDoubleTime { SpeedChange = { Value = 1.01 } } });
|
||||||
|
|
||||||
AddAssert("ensure button is selected and customized accordingly", () =>
|
AddAssert("ensure button is selected and customized accordingly", () =>
|
||||||
|
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public class TestSceneSectionsContainer : OsuManualInputManagerTestScene
|
||||||
|
{
|
||||||
|
private readonly SectionsContainer<TestSection> container;
|
||||||
|
private float custom;
|
||||||
|
private const float header_height = 100;
|
||||||
|
|
||||||
|
public TestSceneSectionsContainer()
|
||||||
|
{
|
||||||
|
container = new SectionsContainer<TestSection>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 300,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
FixedHeader = new Box
|
||||||
|
{
|
||||||
|
Alpha = 0.5f,
|
||||||
|
Width = 300,
|
||||||
|
Height = header_height,
|
||||||
|
Colour = Color4.Red
|
||||||
|
}
|
||||||
|
};
|
||||||
|
container.SelectedSection.ValueChanged += section =>
|
||||||
|
{
|
||||||
|
if (section.OldValue != null)
|
||||||
|
section.OldValue.Selected = false;
|
||||||
|
if (section.NewValue != null)
|
||||||
|
section.NewValue.Selected = true;
|
||||||
|
};
|
||||||
|
Add(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSelection()
|
||||||
|
{
|
||||||
|
AddStep("clear", () => container.Clear());
|
||||||
|
AddStep("add 1/8th", () => append(1 / 8.0f));
|
||||||
|
AddStep("add third", () => append(1 / 3.0f));
|
||||||
|
AddStep("add half", () => append(1 / 2.0f));
|
||||||
|
AddStep("add full", () => append(1));
|
||||||
|
AddSliderStep("set custom", 0.1f, 1.1f, 0.5f, i => custom = i);
|
||||||
|
AddStep("add custom", () => append(custom));
|
||||||
|
AddStep("scroll to previous", () => container.ScrollTo(
|
||||||
|
container.Children.Reverse().SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.First()
|
||||||
|
));
|
||||||
|
AddStep("scroll to next", () => container.ScrollTo(
|
||||||
|
container.Children.SkipWhile(s => s != container.SelectedSection.Value).Skip(1).FirstOrDefault() ?? container.Children.Last()
|
||||||
|
));
|
||||||
|
AddStep("scroll up", () => triggerUserScroll(1));
|
||||||
|
AddStep("scroll down", () => triggerUserScroll(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCorrectSectionSelected()
|
||||||
|
{
|
||||||
|
const int sections_count = 11;
|
||||||
|
float[] alternating = { 0.07f, 0.33f, 0.16f, 0.33f };
|
||||||
|
AddStep("clear", () => container.Clear());
|
||||||
|
AddStep("fill with sections", () =>
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sections_count; i++)
|
||||||
|
append(alternating[i % alternating.Length]);
|
||||||
|
});
|
||||||
|
|
||||||
|
void step(int scrollIndex)
|
||||||
|
{
|
||||||
|
AddStep($"scroll to section {scrollIndex + 1}", () => container.ScrollTo(container.Children[scrollIndex]));
|
||||||
|
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[scrollIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < sections_count; i++)
|
||||||
|
step(i);
|
||||||
|
for (int i = sections_count - 2; i >= 0; i--)
|
||||||
|
step(i);
|
||||||
|
|
||||||
|
AddStep("scroll almost to end", () => container.ScrollTo(container.Children[sections_count - 2]));
|
||||||
|
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 2]);
|
||||||
|
AddStep("scroll down", () => triggerUserScroll(-1));
|
||||||
|
AddUntilStep("correct section selected", () => container.SelectedSection.Value == container.Children[sections_count - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ColourInfo selected_colour = ColourInfo.GradientVertical(Color4.Yellow, Color4.Gold);
|
||||||
|
private static readonly ColourInfo default_colour = ColourInfo.GradientVertical(Color4.White, Color4.DarkGray);
|
||||||
|
|
||||||
|
private void append(float multiplier)
|
||||||
|
{
|
||||||
|
container.Add(new TestSection
|
||||||
|
{
|
||||||
|
Width = 300,
|
||||||
|
Height = (container.ChildSize.Y - header_height) * multiplier,
|
||||||
|
Colour = default_colour
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerUserScroll(float direction)
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(container);
|
||||||
|
InputManager.ScrollVerticalBy(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestSection : Box
|
||||||
|
{
|
||||||
|
public bool Selected
|
||||||
|
{
|
||||||
|
set => Colour = value ? selected_colour : default_colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Tournament.Tests.dll"
|
"${workspaceRoot}/bin/Debug/net5.0/osu.Game.Tournament.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug)",
|
"preLaunchTask": "Build (Debug)",
|
||||||
@ -20,7 +20,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Tournament.Tests.dll"
|
"${workspaceRoot}/bin/Release/net5.0/osu.Game.Tournament.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release)",
|
"preLaunchTask": "Build (Release)",
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Tournament.Components;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Tests.Components
|
||||||
|
{
|
||||||
|
public class TestSceneTournamentModDisplay : TournamentTestScene
|
||||||
|
{
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
|
private FillFlowContainer<TournamentBeatmapPanel> fillFlow;
|
||||||
|
|
||||||
|
private BeatmapInfo beatmap;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 490154 });
|
||||||
|
req.Success += success;
|
||||||
|
api.Queue(req);
|
||||||
|
|
||||||
|
Add(fillFlow = new FillFlowContainer<TournamentBeatmapPanel>
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Direction = FillDirection.Full,
|
||||||
|
Spacing = new osuTK.Vector2(10)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void success(APIBeatmap apiBeatmap)
|
||||||
|
{
|
||||||
|
beatmap = apiBeatmap.ToBeatmap(rulesets);
|
||||||
|
var mods = rulesets.GetRuleset(Ladder.Ruleset.Value.ID ?? 0).CreateInstance().GetAllMods();
|
||||||
|
|
||||||
|
foreach (var mod in mods)
|
||||||
|
{
|
||||||
|
fillFlow.Add(new TournamentBeatmapPanel(beatmap, mod.Acronym)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Tournament.Components;
|
using osu.Game.Tournament.Components;
|
||||||
@ -16,5 +18,23 @@ namespace osu.Game.Tournament.Tests.Screens
|
|||||||
Add(new TourneyVideo("main") { RelativeSizeAxes = Axes.Both });
|
Add(new TourneyVideo("main") { RelativeSizeAxes = Axes.Both });
|
||||||
Add(new ScheduleScreen());
|
Add(new ScheduleScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCurrentMatchTime()
|
||||||
|
{
|
||||||
|
setMatchDate(TimeSpan.FromDays(-1));
|
||||||
|
setMatchDate(TimeSpan.FromSeconds(5));
|
||||||
|
setMatchDate(TimeSpan.FromMinutes(4));
|
||||||
|
setMatchDate(TimeSpan.FromHours(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMatchDate(TimeSpan relativeTime)
|
||||||
|
// Humanizer cannot handle negative timespans.
|
||||||
|
=> AddStep($"start time is {relativeTime}", () =>
|
||||||
|
{
|
||||||
|
var match = CreateSampleMatch();
|
||||||
|
match.Date.Value = DateTimeOffset.Now + relativeTime;
|
||||||
|
Ladder.CurrentMatch.Value = match;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -9,7 +9,6 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -23,7 +22,7 @@ namespace osu.Game.Tournament.Components
|
|||||||
public class TournamentBeatmapPanel : CompositeDrawable
|
public class TournamentBeatmapPanel : CompositeDrawable
|
||||||
{
|
{
|
||||||
public readonly BeatmapInfo Beatmap;
|
public readonly BeatmapInfo Beatmap;
|
||||||
private readonly string mods;
|
private readonly string mod;
|
||||||
|
|
||||||
private const float horizontal_padding = 10;
|
private const float horizontal_padding = 10;
|
||||||
private const float vertical_padding = 10;
|
private const float vertical_padding = 10;
|
||||||
@ -33,12 +32,12 @@ namespace osu.Game.Tournament.Components
|
|||||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||||
private Box flash;
|
private Box flash;
|
||||||
|
|
||||||
public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null)
|
public TournamentBeatmapPanel(BeatmapInfo beatmap, string mod = null)
|
||||||
{
|
{
|
||||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
||||||
|
|
||||||
Beatmap = beatmap;
|
Beatmap = beatmap;
|
||||||
this.mods = mods;
|
this.mod = mod;
|
||||||
Width = 400;
|
Width = 400;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
}
|
}
|
||||||
@ -122,23 +121,15 @@ namespace osu.Game.Tournament.Components
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(mods))
|
if (!string.IsNullOrEmpty(mod))
|
||||||
{
|
{
|
||||||
AddInternal(new Container
|
AddInternal(new TournamentModIcon(mod)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = 60,
|
|
||||||
Anchor = Anchor.CentreRight,
|
Anchor = Anchor.CentreRight,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
Margin = new MarginPadding(10),
|
Margin = new MarginPadding(10),
|
||||||
Child = new Sprite
|
Width = 60,
|
||||||
{
|
RelativeSizeAxes = Axes.Y,
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
Texture = textures.Get($"mods/{mods}"),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
osu.Game.Tournament/Components/TournamentModIcon.cs
Normal file
65
osu.Game.Tournament/Components/TournamentModIcon.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Tournament.Models;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tournament.Components
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Mod icon displayed in tournament usages, allowing user overridden graphics.
|
||||||
|
/// </summary>
|
||||||
|
public class TournamentModIcon : CompositeDrawable
|
||||||
|
{
|
||||||
|
private readonly string modAcronym;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
|
public TournamentModIcon(string modAcronym)
|
||||||
|
{
|
||||||
|
this.modAcronym = modAcronym;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures, LadderInfo ladderInfo)
|
||||||
|
{
|
||||||
|
var customTexture = textures.Get($"mods/{modAcronym}");
|
||||||
|
|
||||||
|
if (customTexture != null)
|
||||||
|
{
|
||||||
|
AddInternal(new Sprite
|
||||||
|
{
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Texture = customTexture
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ruleset = rulesets.GetRuleset(ladderInfo.Ruleset.Value?.ID ?? 0);
|
||||||
|
var modIcon = ruleset?.CreateInstance().GetAllMods().FirstOrDefault(mod => mod.Acronym == modAcronym);
|
||||||
|
|
||||||
|
if (modIcon == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddInternal(new ModIcon(modIcon, false)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(0.5f)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -192,12 +192,7 @@ namespace osu.Game.Tournament.Screens.Schedule
|
|||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new TournamentSpriteText
|
new ScheduleMatchDate(match.NewValue.Date.Value)
|
||||||
{
|
|
||||||
Text = "Starting ",
|
|
||||||
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.Regular)
|
|
||||||
},
|
|
||||||
new DrawableDate(match.NewValue.Date.Value)
|
|
||||||
{
|
{
|
||||||
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.Regular)
|
Font = OsuFont.Torus.With(size: 24, weight: FontWeight.Regular)
|
||||||
}
|
}
|
||||||
@ -251,6 +246,18 @@ namespace osu.Game.Tournament.Screens.Schedule
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ScheduleMatchDate : DrawableDate
|
||||||
|
{
|
||||||
|
public ScheduleMatchDate(DateTimeOffset date, float textSize = OsuFont.DEFAULT_FONT_SIZE, bool italic = true)
|
||||||
|
: base(date, textSize, italic)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string Format() => Date < DateTimeOffset.Now
|
||||||
|
? $"Started {base.Format()}"
|
||||||
|
: $"Starting {base.Format()}";
|
||||||
|
}
|
||||||
|
|
||||||
public class ScheduleContainer : Container
|
public class ScheduleContainer : Container
|
||||||
{
|
{
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
|
@ -50,15 +50,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
IBeatmap IBeatmap.Clone() => Clone();
|
IBeatmap IBeatmap.Clone() => Clone();
|
||||||
|
|
||||||
public Beatmap<T> Clone()
|
public Beatmap<T> Clone() => (Beatmap<T>)MemberwiseClone();
|
||||||
{
|
|
||||||
var clone = (Beatmap<T>)MemberwiseClone();
|
|
||||||
|
|
||||||
clone.ControlPointInfo = ControlPointInfo.CreateCopy();
|
|
||||||
// todo: deep clone other elements as required.
|
|
||||||
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Beatmap : Beatmap<HitObject>
|
public class Beatmap : Beatmap<HitObject>
|
||||||
|
@ -7,7 +7,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Dapper;
|
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using osu.Framework.Development;
|
using osu.Framework.Development;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
@ -154,20 +153,31 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
using (var db = new SqliteConnection(storage.GetDatabaseConnectionString("online")))
|
using (var db = new SqliteConnection(storage.GetDatabaseConnectionString("online")))
|
||||||
{
|
{
|
||||||
var found = db.QuerySingleOrDefault<CachedOnlineBeatmapLookup>(
|
db.Open();
|
||||||
"SELECT * FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path", beatmap);
|
|
||||||
|
|
||||||
if (found != null)
|
using (var cmd = db.CreateCommand())
|
||||||
{
|
{
|
||||||
var status = (BeatmapSetOnlineStatus)found.approved;
|
cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineBeatmapID OR filename = @Path";
|
||||||
|
|
||||||
beatmap.Status = status;
|
cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmap.MD5Hash));
|
||||||
beatmap.BeatmapSet.Status = status;
|
cmd.Parameters.Add(new SqliteParameter("@OnlineBeatmapID", beatmap.OnlineBeatmapID));
|
||||||
beatmap.BeatmapSet.OnlineBeatmapSetID = found.beatmapset_id;
|
cmd.Parameters.Add(new SqliteParameter("@Path", beatmap.Path));
|
||||||
beatmap.OnlineBeatmapID = found.beatmap_id;
|
|
||||||
|
|
||||||
LogForModel(set, $"Cached local retrieval for {beatmap}.");
|
using (var reader = cmd.ExecuteReader())
|
||||||
return true;
|
{
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
var status = (BeatmapSetOnlineStatus)reader.GetByte(2);
|
||||||
|
|
||||||
|
beatmap.Status = status;
|
||||||
|
beatmap.BeatmapSet.Status = status;
|
||||||
|
beatmap.BeatmapSet.OnlineBeatmapSetID = reader.GetInt32(0);
|
||||||
|
beatmap.OnlineBeatmapID = reader.GetInt32(1);
|
||||||
|
|
||||||
|
LogForModel(set, $"Cached local retrieval for {beatmap}.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,11 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public BeatmapSetOnlineStatus Status { get; set; }
|
public BeatmapSetOnlineStatus Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this beatmap set has explicit content.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasExplicitContent { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not this beatmap set has a background video.
|
/// Whether or not this beatmap set has a background video.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The control points in this beatmap.
|
/// The control points in this beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ControlPointInfo ControlPointInfo { get; }
|
ControlPointInfo ControlPointInfo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The breaks in this beatmap.
|
/// The breaks in this beatmap.
|
||||||
|
@ -60,6 +60,8 @@ namespace osu.Game.Configuration
|
|||||||
Set(OsuSetting.ExternalLinkWarning, true);
|
Set(OsuSetting.ExternalLinkWarning, true);
|
||||||
Set(OsuSetting.PreferNoVideo, false);
|
Set(OsuSetting.PreferNoVideo, false);
|
||||||
|
|
||||||
|
Set(OsuSetting.ShowOnlineExplicitContent, false);
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01);
|
Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01);
|
||||||
|
|
||||||
@ -82,6 +84,7 @@ namespace osu.Game.Configuration
|
|||||||
|
|
||||||
Set(OsuSetting.ShowStoryboard, true);
|
Set(OsuSetting.ShowStoryboard, true);
|
||||||
Set(OsuSetting.BeatmapSkins, true);
|
Set(OsuSetting.BeatmapSkins, true);
|
||||||
|
Set(OsuSetting.BeatmapColours, true);
|
||||||
Set(OsuSetting.BeatmapHitsounds, true);
|
Set(OsuSetting.BeatmapHitsounds, true);
|
||||||
|
|
||||||
Set(OsuSetting.CursorRotation, true);
|
Set(OsuSetting.CursorRotation, true);
|
||||||
@ -250,6 +253,7 @@ namespace osu.Game.Configuration
|
|||||||
ScreenshotCaptureMenuCursor,
|
ScreenshotCaptureMenuCursor,
|
||||||
SongSelectRightMouseScroll,
|
SongSelectRightMouseScroll,
|
||||||
BeatmapSkins,
|
BeatmapSkins,
|
||||||
|
BeatmapColours,
|
||||||
BeatmapHitsounds,
|
BeatmapHitsounds,
|
||||||
IncreaseFirstObjectVisibility,
|
IncreaseFirstObjectVisibility,
|
||||||
ScoreDisplayMode,
|
ScoreDisplayMode,
|
||||||
@ -270,5 +274,6 @@ namespace osu.Game.Configuration
|
|||||||
EditorWaveformOpacity,
|
EditorWaveformOpacity,
|
||||||
DiscordRichPresence,
|
DiscordRichPresence,
|
||||||
AutomaticallyDownloadWhenSpectating,
|
AutomaticallyDownloadWhenSpectating,
|
||||||
|
ShowOnlineExplicitContent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,13 +115,13 @@ namespace osu.Game.Database
|
|||||||
return Import(notification, paths.Select(p => new ImportTask(p)).ToArray());
|
return Import(notification, paths.Select(p => new ImportTask(p)).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Import(Stream stream, string filename)
|
public Task Import(params ImportTask[] tasks)
|
||||||
{
|
{
|
||||||
var notification = new ProgressNotification { State = ProgressNotificationState.Active };
|
var notification = new ProgressNotification { State = ProgressNotificationState.Active };
|
||||||
|
|
||||||
PostNotification?.Invoke(notification);
|
PostNotification?.Invoke(notification);
|
||||||
|
|
||||||
return Import(notification, new ImportTask(stream, filename));
|
return Import(notification, tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<IEnumerable<TModel>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
protected async Task<IEnumerable<TModel>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
@ -19,11 +18,10 @@ namespace osu.Game.Database
|
|||||||
Task Import(params string[] paths);
|
Task Import(params string[] paths);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Import the provided stream as a simple item.
|
/// Import the specified files from the given import tasks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">The stream to import files from. Should be in a supported archive format.</param>
|
/// <param name="tasks">The import tasks from which the files should be imported.</param>
|
||||||
/// <param name="filename">The filename of the archive being imported.</param>
|
Task Import(params ImportTask[] tasks);
|
||||||
Task Import(Stream stream, string filename);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An array of accepted file extensions (in the standard format of ".abc").
|
/// An array of accepted file extensions (in the standard format of ".abc").
|
||||||
|
@ -135,6 +135,8 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => new { b.RulesetID, b.Variant });
|
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => new { b.RulesetID, b.Variant });
|
||||||
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => b.IntAction);
|
modelBuilder.Entity<DatabasedKeyBinding>().HasIndex(b => b.IntAction);
|
||||||
|
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.KeyCombination);
|
||||||
|
modelBuilder.Entity<DatabasedKeyBinding>().Ignore(b => b.Action);
|
||||||
|
|
||||||
modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant });
|
modelBuilder.Entity<DatabasedSetting>().HasIndex(b => new { b.RulesetID, b.Variant });
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
private Bindable<bool> parallaxEnabled;
|
private Bindable<bool> parallaxEnabled;
|
||||||
|
|
||||||
|
private const float parallax_duration = 100;
|
||||||
|
|
||||||
|
private bool firstUpdate = true;
|
||||||
|
|
||||||
public ParallaxContainer()
|
public ParallaxContainer()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
@ -60,17 +64,27 @@ namespace osu.Game.Graphics.Containers
|
|||||||
input = GetContainingInputManager();
|
input = GetContainingInputManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool firstUpdate = true;
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (parallaxEnabled.Value)
|
if (parallaxEnabled.Value)
|
||||||
{
|
{
|
||||||
Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.Position) - DrawSize / 2) * ParallaxAmount;
|
Vector2 offset = Vector2.Zero;
|
||||||
|
|
||||||
const float parallax_duration = 100;
|
if (input.CurrentState.Mouse != null)
|
||||||
|
{
|
||||||
|
var sizeDiv2 = DrawSize / 2;
|
||||||
|
|
||||||
|
Vector2 relativeAmount = ToLocalSpace(input.CurrentState.Mouse.Position) - sizeDiv2;
|
||||||
|
|
||||||
|
const float base_factor = 0.999f;
|
||||||
|
|
||||||
|
relativeAmount.X = (float)(Math.Sign(relativeAmount.X) * Interpolation.Damp(0, 1, base_factor, Math.Abs(relativeAmount.X)));
|
||||||
|
relativeAmount.Y = (float)(Math.Sign(relativeAmount.Y) * Interpolation.Damp(0, 1, base_factor, Math.Abs(relativeAmount.Y)));
|
||||||
|
|
||||||
|
offset = relativeAmount * sizeDiv2 * ParallaxAmount;
|
||||||
|
}
|
||||||
|
|
||||||
double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration);
|
double elapsed = Math.Clamp(Clock.ElapsedFrameTime, 0, parallax_duration);
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -9,6 +10,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Layout;
|
using osu.Framework.Layout;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers
|
namespace osu.Game.Graphics.Containers
|
||||||
{
|
{
|
||||||
@ -20,6 +22,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
where T : Drawable
|
where T : Drawable
|
||||||
{
|
{
|
||||||
public Bindable<T> SelectedSection { get; } = new Bindable<T>();
|
public Bindable<T> SelectedSection { get; } = new Bindable<T>();
|
||||||
|
private Drawable lastClickedSection;
|
||||||
|
|
||||||
public Drawable ExpandableHeader
|
public Drawable ExpandableHeader
|
||||||
{
|
{
|
||||||
@ -36,7 +39,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
|
|
||||||
AddInternal(expandableHeader);
|
AddInternal(expandableHeader);
|
||||||
lastKnownScroll = float.NaN;
|
lastKnownScroll = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +55,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
|
|
||||||
AddInternal(fixedHeader);
|
AddInternal(fixedHeader);
|
||||||
lastKnownScroll = float.NaN;
|
lastKnownScroll = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +74,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
footer.Anchor |= Anchor.y2;
|
footer.Anchor |= Anchor.y2;
|
||||||
footer.Origin |= Anchor.y2;
|
footer.Origin |= Anchor.y2;
|
||||||
scrollContainer.Add(footer);
|
scrollContainer.Add(footer);
|
||||||
lastKnownScroll = float.NaN;
|
lastKnownScroll = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,21 +92,26 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
headerBackgroundContainer.Add(headerBackground);
|
headerBackgroundContainer.Add(headerBackground);
|
||||||
|
|
||||||
lastKnownScroll = float.NaN;
|
lastKnownScroll = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Container<T> Content => scrollContentContainer;
|
protected override Container<T> Content => scrollContentContainer;
|
||||||
|
|
||||||
private readonly OsuScrollContainer scrollContainer;
|
private readonly UserTrackingScrollContainer scrollContainer;
|
||||||
private readonly Container headerBackgroundContainer;
|
private readonly Container headerBackgroundContainer;
|
||||||
private readonly MarginPadding originalSectionsMargin;
|
private readonly MarginPadding originalSectionsMargin;
|
||||||
private Drawable expandableHeader, fixedHeader, footer, headerBackground;
|
private Drawable expandableHeader, fixedHeader, footer, headerBackground;
|
||||||
private FlowContainer<T> scrollContentContainer;
|
private FlowContainer<T> scrollContentContainer;
|
||||||
|
|
||||||
private float headerHeight, footerHeight;
|
private float? headerHeight, footerHeight;
|
||||||
|
|
||||||
private float lastKnownScroll;
|
private float? lastKnownScroll;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The percentage of the container to consider the centre-point for deciding the active section (and scrolling to a requested section).
|
||||||
|
/// </summary>
|
||||||
|
private const float scroll_y_centre = 0.1f;
|
||||||
|
|
||||||
public SectionsContainer()
|
public SectionsContainer()
|
||||||
{
|
{
|
||||||
@ -128,18 +136,24 @@ namespace osu.Game.Graphics.Containers
|
|||||||
public override void Add(T drawable)
|
public override void Add(T drawable)
|
||||||
{
|
{
|
||||||
base.Add(drawable);
|
base.Add(drawable);
|
||||||
lastKnownScroll = float.NaN;
|
|
||||||
headerHeight = float.NaN;
|
Debug.Assert(drawable != null);
|
||||||
footerHeight = float.NaN;
|
|
||||||
|
lastKnownScroll = null;
|
||||||
|
headerHeight = null;
|
||||||
|
footerHeight = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScrollTo(Drawable section) =>
|
public void ScrollTo(Drawable section)
|
||||||
scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - (FixedHeader?.BoundingBox.Height ?? 0));
|
{
|
||||||
|
lastClickedSection = section;
|
||||||
|
scrollContainer.ScrollTo(scrollContainer.GetChildPosInContent(section) - scrollContainer.DisplayableContent * scroll_y_centre - (FixedHeader?.BoundingBox.Height ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
public void ScrollToTop() => scrollContainer.ScrollTo(0);
|
public void ScrollToTop() => scrollContainer.ScrollTo(0);
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
protected virtual OsuScrollContainer CreateScrollContainer() => new OsuScrollContainer();
|
protected virtual UserTrackingScrollContainer CreateScrollContainer() => new UserTrackingScrollContainer();
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
protected virtual FlowContainer<T> CreateScrollContentContainer() =>
|
protected virtual FlowContainer<T> CreateScrollContentContainer() =>
|
||||||
@ -156,7 +170,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0)
|
if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0)
|
||||||
{
|
{
|
||||||
lastKnownScroll = -1;
|
lastKnownScroll = null;
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +181,10 @@ namespace osu.Game.Graphics.Containers
|
|||||||
{
|
{
|
||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
float headerH = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0);
|
float fixedHeaderSize = FixedHeader?.LayoutSize.Y ?? 0;
|
||||||
|
float expandableHeaderSize = ExpandableHeader?.LayoutSize.Y ?? 0;
|
||||||
|
|
||||||
|
float headerH = expandableHeaderSize + fixedHeaderSize;
|
||||||
float footerH = Footer?.LayoutSize.Y ?? 0;
|
float footerH = Footer?.LayoutSize.Y ?? 0;
|
||||||
|
|
||||||
if (headerH != headerHeight || footerH != footerHeight)
|
if (headerH != headerHeight || footerH != footerHeight)
|
||||||
@ -183,28 +200,39 @@ namespace osu.Game.Graphics.Containers
|
|||||||
{
|
{
|
||||||
lastKnownScroll = currentScroll;
|
lastKnownScroll = currentScroll;
|
||||||
|
|
||||||
|
// reset last clicked section because user started scrolling themselves
|
||||||
|
if (scrollContainer.UserScrolling)
|
||||||
|
lastClickedSection = null;
|
||||||
|
|
||||||
if (ExpandableHeader != null && FixedHeader != null)
|
if (ExpandableHeader != null && FixedHeader != null)
|
||||||
{
|
{
|
||||||
float offset = Math.Min(ExpandableHeader.LayoutSize.Y, currentScroll);
|
float offset = Math.Min(expandableHeaderSize, currentScroll);
|
||||||
|
|
||||||
ExpandableHeader.Y = -offset;
|
ExpandableHeader.Y = -offset;
|
||||||
FixedHeader.Y = -offset + ExpandableHeader.LayoutSize.Y;
|
FixedHeader.Y = -offset + expandableHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
headerBackgroundContainer.Height = (ExpandableHeader?.LayoutSize.Y ?? 0) + (FixedHeader?.LayoutSize.Y ?? 0);
|
headerBackgroundContainer.Height = expandableHeaderSize + fixedHeaderSize;
|
||||||
headerBackgroundContainer.Y = ExpandableHeader?.Y ?? 0;
|
headerBackgroundContainer.Y = ExpandableHeader?.Y ?? 0;
|
||||||
|
|
||||||
float scrollOffset = FixedHeader?.LayoutSize.Y ?? 0;
|
var smallestSectionHeight = Children.Count > 0 ? Children.Min(d => d.Height) : 0;
|
||||||
Func<T, float> diff = section => scrollContainer.GetChildPosInContent(section) - currentScroll - scrollOffset;
|
|
||||||
|
|
||||||
if (scrollContainer.IsScrolledToEnd())
|
// scroll offset is our fixed header height if we have it plus 10% of content height
|
||||||
{
|
// plus 5% to fix floating point errors and to not have a section instantly unselect when scrolling upwards
|
||||||
SelectedSection.Value = Children.LastOrDefault();
|
// but the 5% can't be bigger than our smallest section height, otherwise it won't get selected correctly
|
||||||
}
|
float selectionLenienceAboveSection = Math.Min(smallestSectionHeight / 2.0f, scrollContainer.DisplayableContent * 0.05f);
|
||||||
|
|
||||||
|
float scrollCentre = fixedHeaderSize + scrollContainer.DisplayableContent * scroll_y_centre + selectionLenienceAboveSection;
|
||||||
|
|
||||||
|
if (Precision.AlmostBigger(0, scrollContainer.Current))
|
||||||
|
SelectedSection.Value = lastClickedSection as T ?? Children.FirstOrDefault();
|
||||||
|
else if (Precision.AlmostBigger(scrollContainer.Current, scrollContainer.ScrollableExtent))
|
||||||
|
SelectedSection.Value = lastClickedSection as T ?? Children.LastOrDefault();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectedSection.Value = Children.TakeWhile(section => diff(section) <= 0).LastOrDefault()
|
SelectedSection.Value = Children
|
||||||
?? Children.FirstOrDefault();
|
.TakeWhile(section => scrollContainer.GetChildPosInContent(section) - currentScroll - scrollCentre <= 0)
|
||||||
|
.LastOrDefault() ?? Children.FirstOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,8 +242,9 @@ namespace osu.Game.Graphics.Containers
|
|||||||
if (!Children.Any()) return;
|
if (!Children.Any()) return;
|
||||||
|
|
||||||
var newMargin = originalSectionsMargin;
|
var newMargin = originalSectionsMargin;
|
||||||
newMargin.Top += headerHeight;
|
|
||||||
newMargin.Bottom += footerHeight;
|
newMargin.Top += (headerHeight ?? 0);
|
||||||
|
newMargin.Bottom += (footerHeight ?? 0);
|
||||||
|
|
||||||
scrollContentContainer.Margin = newMargin;
|
scrollContentContainer.Margin = newMargin;
|
||||||
}
|
}
|
||||||
|
49
osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs
Normal file
49
osu.Game/Graphics/Containers/UserTrackingScrollContainer.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
public class UserTrackingScrollContainer : UserTrackingScrollContainer<Drawable>
|
||||||
|
{
|
||||||
|
public UserTrackingScrollContainer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserTrackingScrollContainer(Direction direction)
|
||||||
|
: base(direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserTrackingScrollContainer<T> : OsuScrollContainer<T>
|
||||||
|
where T : Drawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the last scroll event was user triggered, directly on the scroll container.
|
||||||
|
/// </summary>
|
||||||
|
public bool UserScrolling { get; private set; }
|
||||||
|
|
||||||
|
public UserTrackingScrollContainer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserTrackingScrollContainer(Direction direction)
|
||||||
|
: base(direction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default)
|
||||||
|
{
|
||||||
|
UserScrolling = true;
|
||||||
|
base.OnUserScroll(value, animated, distanceDecay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null)
|
||||||
|
{
|
||||||
|
UserScrolling = false;
|
||||||
|
base.ScrollTo(value, animated, distanceDecay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
|
|
||||||
private KeyBindingStore store;
|
private KeyBindingStore store;
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0);
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance.
|
/// Create a new instance.
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
handler = game;
|
handler = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings);
|
public override IEnumerable<IKeyBinding> DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings).Concat(AudioControlKeyBindings).Concat(EditorKeyBindings);
|
||||||
|
|
||||||
public IEnumerable<KeyBinding> GlobalKeyBindings => new[]
|
public IEnumerable<KeyBinding> GlobalKeyBindings => new[]
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertDefaults(IEnumerable<KeyBinding> defaults, int? rulesetId = null, int? variant = null)
|
private void insertDefaults(IEnumerable<IKeyBinding> defaults, int? rulesetId = null, int? variant = null)
|
||||||
{
|
{
|
||||||
using (var usage = ContextFactory.GetForWrite())
|
using (var usage = ContextFactory.GetForWrite())
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
@ -13,16 +14,20 @@ using osu.Game.Rulesets.Mods;
|
|||||||
|
|
||||||
namespace osu.Game.Online.API
|
namespace osu.Game.Online.API
|
||||||
{
|
{
|
||||||
|
[MessagePackObject]
|
||||||
public class APIMod : IMod
|
public class APIMod : IMod
|
||||||
{
|
{
|
||||||
[JsonProperty("acronym")]
|
[JsonProperty("acronym")]
|
||||||
|
[Key(0)]
|
||||||
public string Acronym { get; set; }
|
public string Acronym { get; set; }
|
||||||
|
|
||||||
[JsonProperty("settings")]
|
[JsonProperty("settings")]
|
||||||
|
[Key(1)]
|
||||||
public Dictionary<string, object> Settings { get; set; } = new Dictionary<string, object>();
|
public Dictionary<string, object> Settings { get; set; } = new Dictionary<string, object>();
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
private APIMod()
|
[SerializationConstructor]
|
||||||
|
public APIMod()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
[JsonProperty(@"bpm")]
|
[JsonProperty(@"bpm")]
|
||||||
private double bpm { get; set; }
|
private double bpm { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"nsfw")]
|
||||||
|
private bool hasExplicitContent { get; set; }
|
||||||
|
|
||||||
[JsonProperty(@"video")]
|
[JsonProperty(@"video")]
|
||||||
private bool hasVideo { get; set; }
|
private bool hasVideo { get; set; }
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
[JsonProperty(@"beatmaps")]
|
[JsonProperty(@"beatmaps")]
|
||||||
private IEnumerable<APIBeatmap> beatmaps { get; set; }
|
private IEnumerable<APIBeatmap> beatmaps { get; set; }
|
||||||
|
|
||||||
public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
|
public virtual BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
var beatmapSet = new BeatmapSetInfo
|
var beatmapSet = new BeatmapSetInfo
|
||||||
{
|
{
|
||||||
@ -94,6 +97,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
FavouriteCount = favouriteCount,
|
FavouriteCount = favouriteCount,
|
||||||
BPM = bpm,
|
BPM = bpm,
|
||||||
Status = Status,
|
Status = Status,
|
||||||
|
HasExplicitContent = hasExplicitContent,
|
||||||
HasVideo = hasVideo,
|
HasVideo = hasVideo,
|
||||||
HasStoryboard = hasStoryboard,
|
HasStoryboard = hasStoryboard,
|
||||||
Submitted = submitted,
|
Submitted = submitted,
|
||||||
|
@ -30,6 +30,8 @@ namespace osu.Game.Online.API.Requests
|
|||||||
|
|
||||||
public SearchPlayed Played { get; }
|
public SearchPlayed Played { get; }
|
||||||
|
|
||||||
|
public SearchExplicit ExplicitContent { get; }
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
public IReadOnlyCollection<ScoreRank> Ranks { get; }
|
public IReadOnlyCollection<ScoreRank> Ranks { get; }
|
||||||
|
|
||||||
@ -50,7 +52,8 @@ namespace osu.Game.Online.API.Requests
|
|||||||
SearchLanguage language = SearchLanguage.Any,
|
SearchLanguage language = SearchLanguage.Any,
|
||||||
IReadOnlyCollection<SearchExtra> extra = null,
|
IReadOnlyCollection<SearchExtra> extra = null,
|
||||||
IReadOnlyCollection<ScoreRank> ranks = null,
|
IReadOnlyCollection<ScoreRank> ranks = null,
|
||||||
SearchPlayed played = SearchPlayed.Any)
|
SearchPlayed played = SearchPlayed.Any,
|
||||||
|
SearchExplicit explicitContent = SearchExplicit.Hide)
|
||||||
{
|
{
|
||||||
this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query);
|
this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query);
|
||||||
this.ruleset = ruleset;
|
this.ruleset = ruleset;
|
||||||
@ -64,6 +67,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
Extra = extra;
|
Extra = extra;
|
||||||
Ranks = ranks;
|
Ranks = ranks;
|
||||||
Played = played;
|
Played = played;
|
||||||
|
ExplicitContent = explicitContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override WebRequest CreateWebRequest()
|
protected override WebRequest CreateWebRequest()
|
||||||
@ -93,6 +97,8 @@ namespace osu.Game.Online.API.Requests
|
|||||||
if (Played != SearchPlayed.Any)
|
if (Played != SearchPlayed.Any)
|
||||||
req.AddParameter("played", Played.ToString().ToLowerInvariant());
|
req.AddParameter("played", Played.ToString().ToLowerInvariant());
|
||||||
|
|
||||||
|
req.AddParameter("nsfw", ExplicitContent == SearchExplicit.Show ? "true" : "false");
|
||||||
|
|
||||||
req.AddCursor(cursor);
|
req.AddCursor(cursor);
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
|
@ -339,7 +339,7 @@ namespace osu.Game.Online.Chat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Joins a channel if it has not already been joined.
|
/// Joins a channel if it has not already been joined. Must be called from the update thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="channel">The channel to join.</param>
|
/// <param name="channel">The channel to join.</param>
|
||||||
/// <returns>The joined channel. Note that this may not match the parameter channel as it is a backed object.</returns>
|
/// <returns>The joined channel. Note that this may not match the parameter channel as it is a backed object.</returns>
|
||||||
@ -399,7 +399,11 @@ namespace osu.Game.Online.Chat
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LeaveChannel(Channel channel)
|
/// <summary>
|
||||||
|
/// Leave the specified channel. Can be called from any thread.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channel">The channel to leave.</param>
|
||||||
|
public void LeaveChannel(Channel channel) => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (channel == null) return;
|
if (channel == null) return;
|
||||||
|
|
||||||
@ -413,7 +417,7 @@ namespace osu.Game.Online.Chat
|
|||||||
api.Queue(new LeaveChannelRequest(channel));
|
api.Queue(new LeaveChannelRequest(channel));
|
||||||
channel.Joined.Value = false;
|
channel.Joined.Value = false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
private long lastMessageId;
|
private long lastMessageId;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using osu.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
@ -65,13 +66,19 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
if (connection != null)
|
if (connection != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
connection = new HubConnectionBuilder()
|
var builder = new HubConnectionBuilder()
|
||||||
.WithUrl(endpoint, options =>
|
.WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); });
|
||||||
{
|
|
||||||
options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
|
if (RuntimeInfo.SupportsJIT)
|
||||||
})
|
builder.AddMessagePackProtocol();
|
||||||
.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; })
|
else
|
||||||
.Build();
|
{
|
||||||
|
// eventually we will precompile resolvers for messagepack, but this isn't working currently
|
||||||
|
// see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
|
||||||
|
builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
|
||||||
|
}
|
||||||
|
|
||||||
|
connection = builder.Build();
|
||||||
|
|
||||||
// this is kind of SILLY
|
// this is kind of SILLY
|
||||||
// https://github.com/dotnet/aspnetcore/issues/15198
|
// https://github.com/dotnet/aspnetcore/issues/15198
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
@ -13,35 +14,42 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// A multiplayer room.
|
/// A multiplayer room.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class MultiplayerRoom
|
public class MultiplayerRoom
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the room, used for database persistence.
|
/// The ID of the room, used for database persistence.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(0)]
|
||||||
public readonly long RoomID;
|
public readonly long RoomID;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current state of the room (ie. whether it is in progress or otherwise).
|
/// The current state of the room (ie. whether it is in progress or otherwise).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(1)]
|
||||||
public MultiplayerRoomState State { get; set; }
|
public MultiplayerRoomState State { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All currently enforced game settings for this room.
|
/// All currently enforced game settings for this room.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(2)]
|
||||||
public MultiplayerRoomSettings Settings { get; set; } = new MultiplayerRoomSettings();
|
public MultiplayerRoomSettings Settings { get; set; } = new MultiplayerRoomSettings();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All users currently in this room.
|
/// All users currently in this room.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(3)]
|
||||||
public List<MultiplayerRoomUser> Users { get; set; } = new List<MultiplayerRoomUser>();
|
public List<MultiplayerRoomUser> Users { get; set; } = new List<MultiplayerRoomUser>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The host of this room, in control of changing room settings.
|
/// The host of this room, in control of changing room settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(4)]
|
||||||
public MultiplayerRoomUser? Host { get; set; }
|
public MultiplayerRoomUser? Host { get; set; }
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public MultiplayerRoom(in long roomId)
|
[SerializationConstructor]
|
||||||
|
public MultiplayerRoom(long roomId)
|
||||||
{
|
{
|
||||||
RoomID = roomId;
|
RoomID = roomId;
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,29 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using MessagePack;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class MultiplayerRoomSettings : IEquatable<MultiplayerRoomSettings>
|
public class MultiplayerRoomSettings : IEquatable<MultiplayerRoomSettings>
|
||||||
{
|
{
|
||||||
|
[Key(0)]
|
||||||
public int BeatmapID { get; set; }
|
public int BeatmapID { get; set; }
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
public int RulesetID { get; set; }
|
public int RulesetID { get; set; }
|
||||||
|
|
||||||
|
[Key(2)]
|
||||||
public string BeatmapChecksum { get; set; } = string.Empty;
|
public string BeatmapChecksum { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Key(3)]
|
||||||
public string Name { get; set; } = "Unnamed room";
|
public string Name { get; set; } = "Unnamed room";
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
|
[Key(4)]
|
||||||
public IEnumerable<APIMod> Mods { get; set; } = Enumerable.Empty<APIMod>();
|
public IEnumerable<APIMod> Mods { get; set; } = Enumerable.Empty<APIMod>();
|
||||||
|
|
||||||
public bool Equals(MultiplayerRoomSettings other)
|
public bool Equals(MultiplayerRoomSettings other)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -11,21 +12,26 @@ using osu.Game.Users;
|
|||||||
namespace osu.Game.Online.Multiplayer
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class MultiplayerRoomUser : IEquatable<MultiplayerRoomUser>
|
public class MultiplayerRoomUser : IEquatable<MultiplayerRoomUser>
|
||||||
{
|
{
|
||||||
|
[Key(0)]
|
||||||
public readonly int UserID;
|
public readonly int UserID;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle;
|
public MultiplayerUserState State { get; set; } = MultiplayerUserState.Idle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The availability state of the current beatmap.
|
/// The availability state of the current beatmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(2)]
|
||||||
public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable();
|
public BeatmapAvailability BeatmapAvailability { get; set; } = BeatmapAvailability.LocallyAvailable();
|
||||||
|
|
||||||
|
[IgnoreMember]
|
||||||
public User? User { get; set; }
|
public User? User { get; set; }
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public MultiplayerRoomUser(in int userId)
|
public MultiplayerRoomUser(int userId)
|
||||||
{
|
{
|
||||||
UserID = userId;
|
UserID = userId;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -128,7 +127,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
|
|
||||||
Debug.Assert(Room != null);
|
Debug.Assert(Room != null);
|
||||||
|
|
||||||
var users = getRoomUsers();
|
var users = await getRoomUsers();
|
||||||
|
Debug.Assert(users != null);
|
||||||
|
|
||||||
await Task.WhenAll(users.Select(PopulateUser));
|
await Task.WhenAll(users.Select(PopulateUser));
|
||||||
|
|
||||||
@ -437,24 +437,20 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// This should be used whenever accessing users from outside of an Update thread context (ie. when not calling <see cref="Drawable.Schedule"/>).
|
/// This should be used whenever accessing users from outside of an Update thread context (ie. when not calling <see cref="Drawable.Schedule"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A copy of users in the current room, or null if unavailable.</returns>
|
/// <returns>A copy of users in the current room, or null if unavailable.</returns>
|
||||||
private List<MultiplayerRoomUser>? getRoomUsers()
|
private Task<List<MultiplayerRoomUser>?> getRoomUsers()
|
||||||
{
|
{
|
||||||
List<MultiplayerRoomUser>? users = null;
|
var tcs = new TaskCompletionSource<List<MultiplayerRoomUser>?>();
|
||||||
|
|
||||||
ManualResetEventSlim resetEvent = new ManualResetEventSlim();
|
|
||||||
|
|
||||||
// at some point we probably want to replace all these schedule calls with Room.LockForUpdate.
|
// at some point we probably want to replace all these schedule calls with Room.LockForUpdate.
|
||||||
// for now, as this would require quite some consideration due to the number of accesses to the room instance,
|
// for now, as this would require quite some consideration due to the number of accesses to the room instance,
|
||||||
// let's just add a manual schedule for the non-scheduled usages instead.
|
// let's just add a manual schedule for the non-scheduled usages instead.
|
||||||
Scheduler.Add(() =>
|
Scheduler.Add(() =>
|
||||||
{
|
{
|
||||||
users = Room?.Users.ToList();
|
var users = Room?.Users.ToList();
|
||||||
resetEvent.Set();
|
tcs.SetResult(users);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
resetEvent.Wait(100);
|
return tcs.Task;
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
@ -9,20 +10,23 @@ namespace osu.Game.Online.Rooms
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The local availability information about a certain beatmap for the client.
|
/// The local availability information about a certain beatmap for the client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[MessagePackObject]
|
||||||
public class BeatmapAvailability : IEquatable<BeatmapAvailability>
|
public class BeatmapAvailability : IEquatable<BeatmapAvailability>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The beatmap's availability state.
|
/// The beatmap's availability state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(0)]
|
||||||
public readonly DownloadState State;
|
public readonly DownloadState State;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The beatmap's downloading progress, null when not in <see cref="DownloadState.Downloading"/> state.
|
/// The beatmap's downloading progress, null when not in <see cref="DownloadState.Downloading"/> state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(1)]
|
||||||
public readonly double? DownloadProgress;
|
public readonly double? DownloadProgress;
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
private BeatmapAvailability(DownloadState state, double? downloadProgress = null)
|
public BeatmapAvailability(DownloadState state, double? downloadProgress = null)
|
||||||
{
|
{
|
||||||
State = state;
|
State = state;
|
||||||
DownloadProgress = downloadProgress;
|
DownloadProgress = downloadProgress;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -12,10 +13,13 @@ using osu.Game.Scoring;
|
|||||||
namespace osu.Game.Online.Spectator
|
namespace osu.Game.Online.Spectator
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class FrameDataBundle
|
public class FrameDataBundle
|
||||||
{
|
{
|
||||||
|
[Key(0)]
|
||||||
public FrameHeader Header { get; set; }
|
public FrameHeader Header { get; set; }
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
public IEnumerable<LegacyReplayFrame> Frames { get; set; }
|
public IEnumerable<LegacyReplayFrame> Frames { get; set; }
|
||||||
|
|
||||||
public FrameDataBundle(ScoreInfo score, IEnumerable<LegacyReplayFrame> frames)
|
public FrameDataBundle(ScoreInfo score, IEnumerable<LegacyReplayFrame> frames)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MessagePack;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -12,31 +13,37 @@ using osu.Game.Scoring;
|
|||||||
namespace osu.Game.Online.Spectator
|
namespace osu.Game.Online.Spectator
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class FrameHeader
|
public class FrameHeader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current accuracy of the score.
|
/// The current accuracy of the score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(0)]
|
||||||
public double Accuracy { get; set; }
|
public double Accuracy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current combo of the score.
|
/// The current combo of the score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(1)]
|
||||||
public int Combo { get; set; }
|
public int Combo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum combo achieved up to the current point in time.
|
/// The maximum combo achieved up to the current point in time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(2)]
|
||||||
public int MaxCombo { get; set; }
|
public int MaxCombo { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cumulative hit statistics.
|
/// Cumulative hit statistics.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(3)]
|
||||||
public Dictionary<HitResult, int> Statistics { get; set; }
|
public Dictionary<HitResult, int> Statistics { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time at which this frame was received by the server.
|
/// The time at which this frame was received by the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Key(4)]
|
||||||
public DateTimeOffset ReceivedTime { get; set; }
|
public DateTimeOffset ReceivedTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -54,7 +61,8 @@ namespace osu.Game.Online.Spectator
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
public FrameHeader(int combo, int maxCombo, double accuracy, Dictionary<HitResult, int> statistics, DateTimeOffset receivedTime)
|
[SerializationConstructor]
|
||||||
|
public FrameHeader(double accuracy, int combo, int maxCombo, Dictionary<HitResult, int> statistics, DateTimeOffset receivedTime)
|
||||||
{
|
{
|
||||||
Combo = combo;
|
Combo = combo;
|
||||||
MaxCombo = maxCombo;
|
MaxCombo = maxCombo;
|
||||||
|
@ -5,18 +5,23 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MessagePack;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.Spectator
|
namespace osu.Game.Online.Spectator
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[MessagePackObject]
|
||||||
public class SpectatorState : IEquatable<SpectatorState>
|
public class SpectatorState : IEquatable<SpectatorState>
|
||||||
{
|
{
|
||||||
|
[Key(0)]
|
||||||
public int? BeatmapID { get; set; }
|
public int? BeatmapID { get; set; }
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
public int? RulesetID { get; set; }
|
public int? RulesetID { get; set; }
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
|
[Key(2)]
|
||||||
public IEnumerable<APIMod> Mods { get; set; } = Enumerable.Empty<APIMod>();
|
public IEnumerable<APIMod> Mods { get; set; } = Enumerable.Empty<APIMod>();
|
||||||
|
|
||||||
public bool Equals(SpectatorState other) => BeatmapID == other?.BeatmapID && Mods.SequenceEqual(other?.Mods) && RulesetID == other?.RulesetID;
|
public bool Equals(SpectatorState other) => BeatmapID == other?.BeatmapID && Mods.SequenceEqual(other?.Mods) && RulesetID == other?.RulesetID;
|
||||||
|
@ -10,6 +10,7 @@ using JetBrains.Annotations;
|
|||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using osu.Framework;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -116,14 +117,19 @@ namespace osu.Game.Online.Spectator
|
|||||||
if (connection != null)
|
if (connection != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
connection = new HubConnectionBuilder()
|
var builder = new HubConnectionBuilder()
|
||||||
.WithUrl(endpoint, options =>
|
.WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); });
|
||||||
{
|
|
||||||
options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
|
|
||||||
})
|
|
||||||
.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; })
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
|
if (RuntimeInfo.SupportsJIT)
|
||||||
|
builder.AddMessagePackProtocol();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// eventually we will precompile resolvers for messagepack, but this isn't working currently
|
||||||
|
// see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
|
||||||
|
builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
|
||||||
|
}
|
||||||
|
|
||||||
|
connection = builder.Build();
|
||||||
// until strong typed client support is added, each method must be manually bound (see https://github.com/dotnet/aspnetcore/issues/15198)
|
// until strong typed client support is added, each method must be manually bound (see https://github.com/dotnet/aspnetcore/issues/15198)
|
||||||
connection.On<int, SpectatorState>(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying);
|
connection.On<int, SpectatorState>(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying);
|
||||||
connection.On<int, FrameDataBundle>(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames);
|
connection.On<int, FrameDataBundle>(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames);
|
||||||
|
@ -51,7 +51,7 @@ using osu.Game.Screens.Select;
|
|||||||
using osu.Game.Updater;
|
using osu.Game.Updater;
|
||||||
using osu.Game.Utils;
|
using osu.Game.Utils;
|
||||||
using LogLevel = osu.Framework.Logging.LogLevel;
|
using LogLevel = osu.Framework.Logging.LogLevel;
|
||||||
using System.IO;
|
using osu.Game.Database;
|
||||||
|
|
||||||
namespace osu.Game
|
namespace osu.Game
|
||||||
{
|
{
|
||||||
@ -438,10 +438,10 @@ namespace osu.Game
|
|||||||
}, validScreens: new[] { typeof(PlaySongSelect) });
|
}, validScreens: new[] { typeof(PlaySongSelect) });
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task Import(Stream stream, string filename)
|
public override Task Import(params ImportTask[] imports)
|
||||||
{
|
{
|
||||||
// encapsulate task as we don't want to begin the import process until in a ready state.
|
// encapsulate task as we don't want to begin the import process until in a ready state.
|
||||||
var importTask = new Task(async () => await base.Import(stream, filename));
|
var importTask = new Task(async () => await base.Import(imports));
|
||||||
|
|
||||||
waitForReady(() => this, _ => importTask.Start());
|
waitForReady(() => this, _ => importTask.Start());
|
||||||
|
|
||||||
|
@ -327,6 +327,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
if (!SelectedMods.Disabled)
|
if (!SelectedMods.Disabled)
|
||||||
SelectedMods.Value = Array.Empty<Mod>();
|
SelectedMods.Value = Array.Empty<Mod>();
|
||||||
|
|
||||||
AvailableMods.Value = dict;
|
AvailableMods.Value = dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,15 +420,14 @@ namespace osu.Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task Import(Stream stream, string filename)
|
public virtual async Task Import(params ImportTask[] tasks)
|
||||||
{
|
{
|
||||||
var extension = Path.GetExtension(filename)?.ToLowerInvariant();
|
var tasksPerExtension = tasks.GroupBy(t => Path.GetExtension(t.Path).ToLowerInvariant());
|
||||||
|
await Task.WhenAll(tasksPerExtension.Select(taskGroup =>
|
||||||
foreach (var importer in fileImporters)
|
|
||||||
{
|
{
|
||||||
if (importer.HandledExtensions.Contains(extension))
|
var importer = fileImporters.FirstOrDefault(i => i.HandledExtensions.Contains(taskGroup.Key));
|
||||||
await importer.Import(stream, Path.GetFileNameWithoutExtension(filename));
|
return importer?.Import(taskGroup.ToArray()) ?? Task.CompletedTask;
|
||||||
}
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions);
|
public IEnumerable<string> HandledExtensions => fileImporters.SelectMany(i => i.HandledExtensions);
|
||||||
|
@ -141,6 +141,7 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
searchControl.Extra.CollectionChanged += (_, __) => queueUpdateSearch();
|
searchControl.Extra.CollectionChanged += (_, __) => queueUpdateSearch();
|
||||||
searchControl.Ranks.CollectionChanged += (_, __) => queueUpdateSearch();
|
searchControl.Ranks.CollectionChanged += (_, __) => queueUpdateSearch();
|
||||||
searchControl.Played.BindValueChanged(_ => queueUpdateSearch());
|
searchControl.Played.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
searchControl.ExplicitContent.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
|
||||||
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
|
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
|
||||||
sortDirection.BindValueChanged(_ => queueUpdateSearch());
|
sortDirection.BindValueChanged(_ => queueUpdateSearch());
|
||||||
@ -193,7 +194,8 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
searchControl.Language.Value,
|
searchControl.Language.Value,
|
||||||
searchControl.Extra,
|
searchControl.Extra,
|
||||||
searchControl.Ranks,
|
searchControl.Ranks,
|
||||||
searchControl.Played.Value);
|
searchControl.Played.Value,
|
||||||
|
searchControl.ExplicitContent.Value);
|
||||||
|
|
||||||
getSetsRequest.Success += response =>
|
getSetsRequest.Success += response =>
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user