mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 05:22:54 +08:00
Merge branch 'master' into combobreak
This commit is contained in:
commit
d6561531a3
@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (catch)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="CatchRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Catch.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (mania)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="ManiaRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Mania.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (osu!)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="OsuRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Osu.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -1,18 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RulesetTests (taiko)" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="TaikoRuleset (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Ruleset">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/netcoreapp2.2/osu.Game.Rulesets.Taiko.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
20
.idea/.idea.osu/.idea/runConfigurations/Tournament.xml
Normal file
20
.idea/.idea.osu/.idea/runConfigurations/Tournament.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament" type="DotNetProject" factoryName=".NET Project" folderName="Tournament">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="--tournament" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Desktop/osu.Desktop.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -0,0 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Tournament (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="Tournament">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.1/osu.Game.Tournament.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tournament.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<browser url="http://localhost:5000" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="osu!" type="DotNetProject" factoryName=".NET Project" folderName="osu!">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||
|
@ -1,17 +1,20 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="VisualTests" type="DotNetProject" factoryName=".NET Project">
|
||||
<configuration default="false" name="osu! (Tests)" type="DotNetProject" factoryName=".NET Project" folderName="osu!">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Tests/osu.Game.Tests.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||
<method />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.2" />
|
||||
<method v="2">
|
||||
<option name="Build" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
144
.vscode/launch.json
vendored
144
.vscode/launch.json
vendored
@ -1,41 +1,6 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "VisualTests (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "VisualTests (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"configurations": [{
|
||||
"name": "osu! (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
@ -69,6 +34,111 @@
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "osu! (Tests, Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
}, {
|
||||
"name": "osu! (Tests, Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2/osu.Game.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.2/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.2/osu!.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Tests, Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Tournament (Tests, Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2/osu.Game.Tournament.Tests.dll",
|
||||
"--tournament"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp2.2:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Cake: Debug Script",
|
||||
"type": "coreclr",
|
||||
@ -84,4 +154,4 @@
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
33
.vscode/tasks.json
vendored
33
.vscode/tasks.json
vendored
@ -2,8 +2,7 @@
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"tasks": [{
|
||||
"label": "Build osu! (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
@ -65,6 +64,36 @@
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Build tournament tests (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
}, {
|
||||
"label": "Build tournament tests (Release)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests",
|
||||
"/p:Configuration=Release",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Restore (netcoreapp2.2)",
|
||||
"type": "shell",
|
||||
|
@ -24,9 +24,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh
|
||||
|
||||
![](https://puu.sh/DCmvA/f6a74f5fbb.png)
|
||||
|
||||
If you are not interested in developing the game, you can consume our [binary releases](https://github.com/ppy/osu/releases).
|
||||
If you are not interested in developing the game, you can still consume our [binary releases](https://github.com/ppy/osu/releases).
|
||||
|
||||
**Latest build:***
|
||||
**Latest build:**
|
||||
|
||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) |
|
||||
| ------------- | ------------- |
|
||||
@ -72,7 +72,7 @@ If the build fails, try to restore nuget packages with `dotnet restore`.
|
||||
|
||||
On Linux, the environment variable `LD_LIBRARY_PATH` must point to the build directory, located at `osu.Desktop/bin/Debug/$NETCORE_VERSION`.
|
||||
|
||||
`$NETCORE_VERSION` is the version of .NET Core SDK. You can have it with `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`.
|
||||
`$NETCORE_VERSION` is the version of the targeted .NET Core SDK. You can check it by running `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`.
|
||||
|
||||
For example, you can run osu! with the following command:
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@ -12,7 +13,6 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -61,7 +61,7 @@ namespace osu.Desktop.Overlays
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Colour = DebugUtils.IsDebug ? colours.Red : Color4.White,
|
||||
Colour = DebugUtils.IsDebugBuild ? colours.Red : Color4.White,
|
||||
Text = game.Version
|
||||
},
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework.Development;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Tournament;
|
||||
|
||||
namespace osu.Desktop
|
||||
{
|
||||
@ -46,6 +47,10 @@ namespace osu.Desktop
|
||||
default:
|
||||
host.Run(new OsuGameDesktop(args));
|
||||
break;
|
||||
|
||||
case "--tournament":
|
||||
host.Run(new TournamentGame());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
@ -25,11 +25,7 @@ namespace osu.Desktop.Updater
|
||||
private UpdateManager updateManager;
|
||||
private NotificationOverlay notificationOverlay;
|
||||
|
||||
public void PrepareUpdate()
|
||||
{
|
||||
// Squirrel returns execution to us after the update process is started, so it's safe to use Wait() here
|
||||
UpdateManager.RestartAppWhenExited().Wait();
|
||||
}
|
||||
public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(NotificationOverlay notification, OsuGameBase game)
|
||||
@ -46,7 +42,7 @@ namespace osu.Desktop.Updater
|
||||
private async void checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
|
||||
{
|
||||
//should we schedule a retry on completion of this check?
|
||||
bool scheduleRetry = true;
|
||||
bool scheduleRecheck = true;
|
||||
|
||||
try
|
||||
{
|
||||
@ -86,10 +82,11 @@ namespace osu.Desktop.Updater
|
||||
//could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
|
||||
//try again without deltas.
|
||||
checkForUpdateAsync(false, notification);
|
||||
scheduleRetry = false;
|
||||
scheduleRecheck = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
notification.State = ProgressNotificationState.Cancelled;
|
||||
Logger.Error(e, @"update failed!");
|
||||
}
|
||||
}
|
||||
@ -100,11 +97,8 @@ namespace osu.Desktop.Updater
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (scheduleRetry)
|
||||
if (scheduleRecheck)
|
||||
{
|
||||
if (notification != null)
|
||||
notification.State = ProgressNotificationState.Cancelled;
|
||||
|
||||
//check again in 30 minutes.
|
||||
Scheduler.AddDelayed(() => checkForUpdateAsync(), 60000 * 30);
|
||||
}
|
||||
@ -134,8 +128,8 @@ namespace osu.Desktop.Updater
|
||||
Text = @"Update ready to install. Click to restart!",
|
||||
Activated = () =>
|
||||
{
|
||||
updateManager.PrepareUpdate();
|
||||
game.GracefullyExit();
|
||||
updateManager.PrepareUpdateAsync()
|
||||
.ContinueWith(_ => Schedule(() => game.GracefullyExit()));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
<StartupObject>osu.Desktop.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||
|
105
osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs
Normal file
105
osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Tests.Visual;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCatcher : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CatcherSprite),
|
||||
};
|
||||
|
||||
private readonly Container container;
|
||||
|
||||
public TestSceneCatcher()
|
||||
{
|
||||
Child = container = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddStep("show default catcher implementation", () => { container.Child = new CatcherSprite(); });
|
||||
|
||||
AddStep("show custom catcher implementation", () =>
|
||||
{
|
||||
container.Child = new CatchCustomSkinSourceContainer
|
||||
{
|
||||
Child = new CatcherSprite()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private class CatcherCustomSkin : Container
|
||||
{
|
||||
public CatcherCustomSkin()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Blue
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Text = "custom"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Cached(typeof(ISkinSource))]
|
||||
private class CatchCustomSkinSourceContainer : Container, ISkinSource
|
||||
{
|
||||
public event Action SourceChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public Drawable GetDrawableComponent(string componentName)
|
||||
{
|
||||
switch (componentName)
|
||||
{
|
||||
case "Play/Catch/fruit-catcher-idle":
|
||||
return new CatcherCustomSkin();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SampleChannel GetSample(string sampleName) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
public Texture GetTexture(string componentName) =>
|
||||
throw new NotImplementedException();
|
||||
|
||||
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration =>
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Tests.Visual;
|
||||
@ -17,8 +16,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
[Test]
|
||||
public void TestHyperDash()
|
||||
{
|
||||
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -141,7 +139,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
caughtFruit = new Container<DrawableHitObject>
|
||||
{
|
||||
@ -212,7 +210,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
|
||||
}
|
||||
|
||||
private Sprite createCatcherSprite() => new CatcherSprite();
|
||||
private Drawable createCatcherSprite() => new CatcherSprite();
|
||||
|
||||
/// <summary>
|
||||
/// Add a caught fruit to the catcher's stack.
|
||||
@ -444,23 +442,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
fruit.Expire();
|
||||
}
|
||||
|
||||
private class CatcherSprite : Sprite
|
||||
{
|
||||
public CatcherSprite()
|
||||
{
|
||||
Size = new Vector2(CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(-0.02f, 0.06f) * CATCHER_SIZE;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
osu.Game.Rulesets.Catch/UI/CatcherSprite.cs
Normal file
33
osu.Game.Rulesets.Catch/UI/CatcherSprite.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherSprite : CompositeDrawable
|
||||
{
|
||||
public CatcherSprite()
|
||||
{
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
|
||||
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||
OriginPosition = new Vector2(-0.02f, 0.06f) * CatcherArea.CATCHER_SIZE;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new SkinnableSprite(@"Play/Catch/fruit-catcher-idle")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
@ -25,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Child = new SkinnableDrawable("Play/osu/approachcircle", name => new Sprite { Texture = textures.Get(name) });
|
||||
Child = new SkinnableSprite("Play/osu/approachcircle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -73,7 +74,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
// Todo: Math.Max() is required as a temporary measure to address https://github.com/ppy/osu-framework/issues/2576
|
||||
downCount = Math.Max(0, downCount - 1);
|
||||
|
||||
if (downCount == 0)
|
||||
updateExpandedState();
|
||||
break;
|
||||
}
|
||||
|
68
osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs
Normal file
68
osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TestSceneTaikoSuddenDeath : PlayerTestScene
|
||||
{
|
||||
public TestSceneTaikoSuddenDeath()
|
||||
: base(new TaikoRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
||||
new TaikoBeatmap
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
new Swell { StartTime = 1500 },
|
||||
new Hit { StartTime = 100000 },
|
||||
},
|
||||
BeatmapInfo =
|
||||
{
|
||||
Ruleset = new TaikoRuleset().RulesetInfo
|
||||
}
|
||||
};
|
||||
|
||||
[Test]
|
||||
public void TestSpinnerDoesNotFail()
|
||||
{
|
||||
bool judged = false;
|
||||
AddStep("Setup judgements", () =>
|
||||
{
|
||||
judged = false;
|
||||
((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
|
||||
});
|
||||
AddUntilStep("swell judged", () => judged);
|
||||
AddAssert("not failed", () => !Player.HasFailed);
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
}
|
||||
}
|
||||
}
|
@ -108,7 +108,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
manager.ItemAdded += (_, __) => Interlocked.Increment(ref itemAddRemoveFireCount);
|
||||
manager.ItemAdded += _ => Interlocked.Increment(ref itemAddRemoveFireCount);
|
||||
manager.ItemRemoved += _ => Interlocked.Increment(ref itemAddRemoveFireCount);
|
||||
|
||||
var imported = await LoadOszIntoOsu(osu);
|
||||
|
@ -14,94 +14,132 @@ namespace osu.Game.Tests.Visual.Components
|
||||
[TestFixture]
|
||||
public class TestSceneIdleTracker : ManualInputManagerTestScene
|
||||
{
|
||||
private readonly IdleTrackingBox box1;
|
||||
private readonly IdleTrackingBox box2;
|
||||
private readonly IdleTrackingBox box3;
|
||||
private readonly IdleTrackingBox box4;
|
||||
private IdleTrackingBox box1;
|
||||
private IdleTrackingBox box2;
|
||||
private IdleTrackingBox box3;
|
||||
private IdleTrackingBox box4;
|
||||
|
||||
public TestSceneIdleTracker()
|
||||
private IdleTrackingBox[] boxes;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Children = new Drawable[]
|
||||
InputManager.MoveMouseTo(Vector2.Zero);
|
||||
|
||||
Children = boxes = new[]
|
||||
{
|
||||
box1 = new IdleTrackingBox(1000)
|
||||
box1 = new IdleTrackingBox(2000)
|
||||
{
|
||||
Name = "TopLeft",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Red,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
},
|
||||
box2 = new IdleTrackingBox(2000)
|
||||
box2 = new IdleTrackingBox(4000)
|
||||
{
|
||||
Name = "TopRight",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Green,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
box3 = new IdleTrackingBox(3000)
|
||||
box3 = new IdleTrackingBox(6000)
|
||||
{
|
||||
Name = "BottomLeft",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Blue,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
},
|
||||
box4 = new IdleTrackingBox(4000)
|
||||
box4 = new IdleTrackingBox(8000)
|
||||
{
|
||||
Name = "BottomRight",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Orange,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestNudge()
|
||||
{
|
||||
AddStep("move mouse to top left", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to top left", () => InputManager.MoveMouseTo(box1));
|
||||
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
waitForAllIdle();
|
||||
|
||||
AddStep("nudge mouse", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre + new Vector2(1)));
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle);
|
||||
AddAssert("check idle", () => box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
checkIdleStatus(1, false);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMovement()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to top right", () => InputManager.MoveMouseTo(box2));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, true);
|
||||
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box4.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to bottom left", () => InputManager.MoveMouseTo(box3));
|
||||
AddStep("move to bottom right", () => InputManager.MoveMouseTo(box4));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => !box3.IsIdle);
|
||||
AddAssert("check idle", () => !box4.IsIdle);
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
waitForAllIdle();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTimings()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move to centre", () => InputManager.MoveMouseTo(Content));
|
||||
|
||||
checkIdleStatus(1, false);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle && !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
AddUntilStep("Wait for idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, false);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for idle", () => box2.IsIdle);
|
||||
AddAssert("check not idle", () => !box3.IsIdle && !box4.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, false);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
AddUntilStep("Wait for idle", () => box3.IsIdle);
|
||||
|
||||
checkIdleStatus(1, true);
|
||||
checkIdleStatus(2, true);
|
||||
checkIdleStatus(3, true);
|
||||
checkIdleStatus(4, false);
|
||||
|
||||
waitForAllIdle();
|
||||
}
|
||||
|
||||
private void checkIdleStatus(int box, bool expectedIdle)
|
||||
{
|
||||
AddAssert($"box {box} is {(expectedIdle ? "idle" : "active")}", () => boxes[box - 1].IsIdle == expectedIdle);
|
||||
}
|
||||
|
||||
private void waitForAllIdle()
|
||||
{
|
||||
AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
ScoreProcessor.FailConditions += _ => true;
|
||||
ScoreProcessor.FailConditions += (_, __) => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
exitAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitViaHoldToExit()
|
||||
{
|
||||
AddStep("exit", () =>
|
||||
{
|
||||
InputManager.MoveMouseTo(Player.HUDOverlay.HoldToQuit.First(c => c is HoldToConfirmContainer));
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
});
|
||||
|
||||
confirmPaused();
|
||||
|
||||
AddStep("release", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
|
||||
exitAndConfirm();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestExitFromPause()
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
typeof(ToolbarButton),
|
||||
typeof(ToolbarRulesetSelector),
|
||||
typeof(ToolbarRulesetButton),
|
||||
typeof(ToolbarRulesetTabButton),
|
||||
typeof(ToolbarNotificationButton),
|
||||
};
|
||||
|
||||
|
95
osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs
Normal file
95
osu.Game.Tests/Visual/Online/TestSceneBeatmapAvailability.cs
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.BeatmapSet;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneBeatmapAvailability : OsuTestScene
|
||||
{
|
||||
private readonly BeatmapAvailability container;
|
||||
|
||||
public TestSceneBeatmapAvailability()
|
||||
{
|
||||
Add(container = new BeatmapAvailability());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUndownloadableWithLink()
|
||||
{
|
||||
AddStep("set undownloadable beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = true,
|
||||
ExternalLink = @"https://osu.ppy.sh",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
visiblityAssert(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUndownloadableNoLink()
|
||||
{
|
||||
AddStep("set undownloadable beatmapset without link", () => container.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
visiblityAssert(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPartsRemovedWithLink()
|
||||
{
|
||||
AddStep("set parts-removed beatmapset with link", () => container.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = false,
|
||||
ExternalLink = @"https://osu.ppy.sh",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
visiblityAssert(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNormal()
|
||||
{
|
||||
AddStep("set normal beatmapset", () => container.BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
visiblityAssert(false);
|
||||
}
|
||||
|
||||
private void visiblityAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is container {(shown ? "visible" : "hidden")}", () => container.Alpha == (shown ? 1 : 0));
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestFixture]
|
||||
public class TestSceneBeatmapSetOverlay : OsuTestScene
|
||||
{
|
||||
private readonly BeatmapSetOverlay overlay;
|
||||
private readonly TestBeatmapSetOverlay overlay;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@ -39,21 +39,22 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(Info),
|
||||
typeof(PreviewButton),
|
||||
typeof(SuccessRate),
|
||||
typeof(BeatmapAvailability),
|
||||
};
|
||||
|
||||
private RulesetInfo maniaRuleset;
|
||||
private RulesetInfo taikoRuleset;
|
||||
private RulesetInfo maniaRuleset;
|
||||
|
||||
public TestSceneBeatmapSetOverlay()
|
||||
{
|
||||
Add(overlay = new BeatmapSetOverlay());
|
||||
Add(overlay = new TestBeatmapSetOverlay());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
maniaRuleset = rulesets.GetRuleset(3);
|
||||
taikoRuleset = rulesets.GetRuleset(1);
|
||||
maniaRuleset = rulesets.GetRuleset(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -75,159 +76,53 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
overlay.ShowBeatmapSet(new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 1235,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Lachryma <Re:Queen’M>",
|
||||
Artist = @"Kaneko Chiharu",
|
||||
Source = @"SOUND VOLTEX III GRAVITY WARS",
|
||||
Tags = @"sdvx grace the 5th kac original song contest konami bemani",
|
||||
Title = @"an awesome beatmap",
|
||||
Artist = @"naru narusegawa",
|
||||
Source = @"hinata sou",
|
||||
Tags = @"test tag tag more tag",
|
||||
Author = new User
|
||||
{
|
||||
Username = @"Fresh Chicken",
|
||||
Id = 3984370,
|
||||
Username = @"BanchoBot",
|
||||
Id = 3,
|
||||
},
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Preview = @"https://b.ppy.sh/preview/415886.mp3",
|
||||
PlayCount = 681380,
|
||||
FavouriteCount = 356,
|
||||
Submitted = new DateTime(2016, 2, 10),
|
||||
Ranked = new DateTime(2016, 6, 19),
|
||||
Status = BeatmapSetOnlineStatus.Ranked,
|
||||
BPM = 236,
|
||||
Preview = @"https://b.ppy.sh/preview/12345.mp3",
|
||||
PlayCount = 123,
|
||||
FavouriteCount = 456,
|
||||
Submitted = DateTime.Now,
|
||||
Ranked = DateTime.Now,
|
||||
BPM = 111,
|
||||
HasVideo = true,
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/415886/covers/cover.jpg?1465651778",
|
||||
},
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 1.36,
|
||||
Version = @"BASIC",
|
||||
StarDifficulty = 9.99,
|
||||
Version = @"TEST",
|
||||
Ruleset = maniaRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 4,
|
||||
DrainRate = 6.5f,
|
||||
OverallDifficulty = 6.5f,
|
||||
ApproachRate = 5,
|
||||
CircleSize = 1,
|
||||
DrainRate = 2.3f,
|
||||
OverallDifficulty = 4.5f,
|
||||
ApproachRate = 6,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 115000,
|
||||
CircleCount = 265,
|
||||
SliderCount = 71,
|
||||
PlayCount = 47906,
|
||||
PassCount = 19899,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 2.22,
|
||||
Version = @"NOVICE",
|
||||
Ruleset = maniaRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 4,
|
||||
DrainRate = 7,
|
||||
OverallDifficulty = 7,
|
||||
ApproachRate = 5,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 118000,
|
||||
CircleCount = 592,
|
||||
SliderCount = 62,
|
||||
PlayCount = 162021,
|
||||
PassCount = 72116,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 3.49,
|
||||
Version = @"ADVANCED",
|
||||
Ruleset = maniaRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 4,
|
||||
DrainRate = 7.5f,
|
||||
OverallDifficulty = 7.5f,
|
||||
ApproachRate = 5,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 118000,
|
||||
CircleCount = 1042,
|
||||
SliderCount = 79,
|
||||
PlayCount = 225178,
|
||||
PassCount = 73001,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 4.24,
|
||||
Version = @"EXHAUST",
|
||||
Ruleset = maniaRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 4,
|
||||
DrainRate = 8,
|
||||
OverallDifficulty = 8,
|
||||
ApproachRate = 5,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 118000,
|
||||
CircleCount = 1352,
|
||||
SliderCount = 69,
|
||||
PlayCount = 131545,
|
||||
PassCount = 42703,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 5.26,
|
||||
Version = @"GRAVITY",
|
||||
Ruleset = maniaRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 4,
|
||||
DrainRate = 8.5f,
|
||||
OverallDifficulty = 8.5f,
|
||||
ApproachRate = 5,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 118000,
|
||||
CircleCount = 1730,
|
||||
SliderCount = 115,
|
||||
PlayCount = 117673,
|
||||
PassCount = 24241,
|
||||
Length = 456000,
|
||||
CircleCount = 111,
|
||||
SliderCount = 12,
|
||||
PlayCount = 222,
|
||||
PassCount = 21,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
@ -239,162 +134,68 @@ namespace osu.Game.Tests.Visual.Online
|
||||
});
|
||||
});
|
||||
|
||||
AddStep(@"show second", () =>
|
||||
downloadAssert(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAvailability()
|
||||
{
|
||||
AddStep(@"show undownloadable", () =>
|
||||
{
|
||||
overlay.ShowBeatmapSet(new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 1234,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"Soumatou Labyrinth",
|
||||
Artist = @"Yunomi with Momobako&miko",
|
||||
Tags = @"mmbk.com yuzu__rinrin charlotte",
|
||||
Title = @"undownloadable beatmap",
|
||||
Artist = @"no one",
|
||||
Source = @"some source",
|
||||
Tags = @"another test tag tag more test tags",
|
||||
Author = new User
|
||||
{
|
||||
Username = @"komasy",
|
||||
Id = 1980256,
|
||||
Username = @"BanchoBot",
|
||||
Id = 3,
|
||||
},
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Preview = @"https://b.ppy.sh/preview/625493.mp3",
|
||||
PlayCount = 22996,
|
||||
FavouriteCount = 58,
|
||||
Submitted = new DateTime(2016, 6, 11),
|
||||
Ranked = new DateTime(2016, 7, 12),
|
||||
Status = BeatmapSetOnlineStatus.Pending,
|
||||
BPM = 160,
|
||||
HasVideo = false,
|
||||
Covers = new BeatmapSetOnlineCovers
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
Cover = @"https://assets.ppy.sh/beatmaps/625493/covers/cover.jpg?1499167472",
|
||||
DownloadDisabled = true,
|
||||
ExternalLink = "https://osu.ppy.sh",
|
||||
},
|
||||
Preview = @"https://b.ppy.sh/preview/1234.mp3",
|
||||
PlayCount = 123,
|
||||
FavouriteCount = 456,
|
||||
Submitted = DateTime.Now,
|
||||
Ranked = DateTime.Now,
|
||||
BPM = 111,
|
||||
HasVideo = true,
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() },
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 1.40,
|
||||
Version = @"yzrin's Kantan",
|
||||
StarDifficulty = 5.67,
|
||||
Version = @"ANOTHER TEST",
|
||||
Ruleset = taikoRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 2,
|
||||
DrainRate = 7,
|
||||
OverallDifficulty = 3,
|
||||
ApproachRate = 10,
|
||||
CircleSize = 9,
|
||||
DrainRate = 8,
|
||||
OverallDifficulty = 7,
|
||||
ApproachRate = 6,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 193000,
|
||||
CircleCount = 262,
|
||||
SliderCount = 0,
|
||||
PlayCount = 3952,
|
||||
PassCount = 1373,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 2.23,
|
||||
Version = @"Futsuu",
|
||||
Ruleset = taikoRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 2,
|
||||
DrainRate = 6,
|
||||
OverallDifficulty = 4,
|
||||
ApproachRate = 10,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 193000,
|
||||
CircleCount = 464,
|
||||
SliderCount = 0,
|
||||
PlayCount = 4833,
|
||||
PassCount = 920,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 3.19,
|
||||
Version = @"Muzukashii",
|
||||
Ruleset = taikoRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 2,
|
||||
DrainRate = 6,
|
||||
OverallDifficulty = 5,
|
||||
ApproachRate = 10,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 193000,
|
||||
CircleCount = 712,
|
||||
SliderCount = 0,
|
||||
PlayCount = 4405,
|
||||
PassCount = 854,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 3.97,
|
||||
Version = @"Charlotte's Oni",
|
||||
Ruleset = taikoRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 5,
|
||||
DrainRate = 6,
|
||||
OverallDifficulty = 5.5f,
|
||||
ApproachRate = 10,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 193000,
|
||||
CircleCount = 943,
|
||||
SliderCount = 0,
|
||||
PlayCount = 3950,
|
||||
PassCount = 693,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(),
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
StarDifficulty = 5.08,
|
||||
Version = @"Labyrinth Oni",
|
||||
Ruleset = taikoRuleset,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
CircleSize = 5,
|
||||
DrainRate = 5,
|
||||
OverallDifficulty = 6,
|
||||
ApproachRate = 10,
|
||||
},
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Length = 193000,
|
||||
CircleCount = 1068,
|
||||
SliderCount = 0,
|
||||
PlayCount = 5856,
|
||||
PassCount = 1207,
|
||||
Length = 123000,
|
||||
CircleCount = 123,
|
||||
SliderCount = 45,
|
||||
PlayCount = 567,
|
||||
PassCount = 89,
|
||||
},
|
||||
Metrics = new BeatmapMetrics
|
||||
{
|
||||
@ -405,6 +206,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
downloadAssert(false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -418,5 +221,15 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AddStep(@"show without reload", overlay.Show);
|
||||
}
|
||||
|
||||
private void downloadAssert(bool shown)
|
||||
{
|
||||
AddAssert($"is download button {(shown ? "shown" : "hidden")}", () => overlay.DownloadButtonsVisible == shown);
|
||||
}
|
||||
|
||||
private class TestBeatmapSetOverlay : BeatmapSetOverlay
|
||||
{
|
||||
public bool DownloadButtonsVisible => Header.DownloadButtonsVisible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,10 @@ using osu.Game.Overlays.Chat.Tabs;
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[Description("Testing chat api and overlay")]
|
||||
public class TestSceneChatDisplay : OsuTestScene
|
||||
public class TestSceneChatOverlay : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ChatOverlay),
|
||||
typeof(ChatLine),
|
||||
typeof(DrawableChannel),
|
||||
typeof(ChannelSelectorTabItem),
|
158
osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs
Normal file
158
osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs
Normal file
@ -0,0 +1,158 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneDirectDownloadButton : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(DownloadButton)
|
||||
};
|
||||
|
||||
private TestDownloadButton downloadButton;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
|
||||
[Test]
|
||||
public void TestDownloadableBeatmap()
|
||||
{
|
||||
createButton(true);
|
||||
assertEnabled(true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUndownloadableBeatmap()
|
||||
{
|
||||
createButton(false);
|
||||
assertEnabled(false);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDownloadState()
|
||||
{
|
||||
AddUntilStep("ensure manager loaded", () => beatmaps != null);
|
||||
ensureSoleilyRemoved();
|
||||
createButtonWithBeatmap(createSoleily());
|
||||
AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded);
|
||||
AddStep("import soleily", () => beatmaps.Import(new[] { TestResources.GetTestBeatmapForImport() }));
|
||||
AddUntilStep("wait for beatmap import", () => beatmaps.GetAllUsableBeatmapSets().Any(b => b.OnlineBeatmapSetID == 241526));
|
||||
createButtonWithBeatmap(createSoleily());
|
||||
AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable);
|
||||
ensureSoleilyRemoved();
|
||||
AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded);
|
||||
}
|
||||
|
||||
private void ensureSoleilyRemoved()
|
||||
{
|
||||
AddStep("remove soleily", () =>
|
||||
{
|
||||
var beatmap = beatmaps.QueryBeatmapSet(b => b.OnlineBeatmapSetID == 241526);
|
||||
|
||||
if (beatmap != null) beatmaps.Delete(beatmap);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertEnabled(bool enabled)
|
||||
{
|
||||
AddAssert($"button {(enabled ? "enabled" : "disabled")}", () => downloadButton.DownloadEnabled == enabled);
|
||||
}
|
||||
|
||||
private BeatmapSetInfo createSoleily()
|
||||
{
|
||||
return new BeatmapSetInfo
|
||||
{
|
||||
ID = 1,
|
||||
OnlineBeatmapSetID = 241526,
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = false,
|
||||
ExternalLink = string.Empty,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private void createButtonWithBeatmap(BeatmapSetInfo beatmap)
|
||||
{
|
||||
AddStep("create button", () =>
|
||||
{
|
||||
Child = downloadButton = new TestDownloadButton(beatmap)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(75, 50),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void createButton(bool downloadable)
|
||||
{
|
||||
AddStep("create button", () =>
|
||||
{
|
||||
Child = downloadButton = new TestDownloadButton(downloadable ? getDownloadableBeatmapSet() : getUndownloadableBeatmapSet())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(75, 50),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private BeatmapSetInfo getDownloadableBeatmapSet()
|
||||
{
|
||||
var normal = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo;
|
||||
normal.OnlineInfo.HasVideo = true;
|
||||
normal.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
private BeatmapSetInfo getUndownloadableBeatmapSet()
|
||||
{
|
||||
var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo;
|
||||
beatmap.Metadata.Artist = "test";
|
||||
beatmap.Metadata.Title = "undownloadable";
|
||||
beatmap.Metadata.AuthorString = "test";
|
||||
|
||||
beatmap.OnlineInfo.HasVideo = true;
|
||||
beatmap.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
beatmap.OnlineInfo.Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = true,
|
||||
ExternalLink = "http://osu.ppy.sh",
|
||||
};
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private class TestDownloadButton : DownloadButton
|
||||
{
|
||||
public new bool DownloadEnabled => base.DownloadEnabled;
|
||||
|
||||
public DownloadState DownloadState => State.Value;
|
||||
|
||||
public TestDownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
|
||||
: base(beatmapSet, noVideo)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,8 +6,11 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
@ -21,25 +24,74 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(IconPill)
|
||||
};
|
||||
|
||||
private BeatmapSetInfo getUndownloadableBeatmapSet(RulesetInfo ruleset) => new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = 123,
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = "undownloadable beatmap",
|
||||
Artist = "test",
|
||||
Source = "more tests",
|
||||
Author = new User
|
||||
{
|
||||
Username = "BanchoBot",
|
||||
Id = 3,
|
||||
},
|
||||
},
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Availability = new BeatmapSetOnlineAvailability
|
||||
{
|
||||
DownloadDisabled = true,
|
||||
},
|
||||
Preview = @"https://b.ppy.sh/preview/12345.mp3",
|
||||
PlayCount = 123,
|
||||
FavouriteCount = 456,
|
||||
BPM = 111,
|
||||
HasVideo = true,
|
||||
HasStoryboard = true,
|
||||
Covers = new BeatmapSetOnlineCovers(),
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
Version = "Test",
|
||||
StarDifficulty = 6.42,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true;
|
||||
beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true;
|
||||
var ruleset = new OsuRuleset().RulesetInfo;
|
||||
|
||||
Child = new FillFlowContainer
|
||||
var normal = CreateWorkingBeatmap(ruleset).BeatmapSetInfo;
|
||||
normal.OnlineInfo.HasVideo = true;
|
||||
normal.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
var undownloadable = getUndownloadableBeatmapSet(ruleset);
|
||||
|
||||
Child = new BasicScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding(20),
|
||||
Spacing = new Vector2(0, 20),
|
||||
Children = new Drawable[]
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
new DirectGridPanel(beatmap.BeatmapSetInfo),
|
||||
new DirectListPanel(beatmap.BeatmapSetInfo)
|
||||
}
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding(20),
|
||||
Spacing = new Vector2(0, 20),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new DirectGridPanel(normal),
|
||||
new DirectListPanel(normal),
|
||||
new DirectGridPanel(undownloadable),
|
||||
new DirectListPanel(undownloadable),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Profile.Header.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneProfileRulesetSelector : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ProfileRulesetSelector),
|
||||
typeof(ProfileRulesetTabItem),
|
||||
};
|
||||
|
||||
public TestSceneProfileRulesetSelector()
|
||||
{
|
||||
ProfileRulesetSelector selector;
|
||||
|
||||
Child = selector = new ProfileRulesetSelector
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
};
|
||||
|
||||
AddStep("set osu! as default", () => selector.SetDefaultRuleset(new OsuRuleset().RulesetInfo));
|
||||
AddStep("set mania as default", () => selector.SetDefaultRuleset(new ManiaRuleset().RulesetInfo));
|
||||
AddStep("set taiko as default", () => selector.SetDefaultRuleset(new TaikoRuleset().RulesetInfo));
|
||||
AddStep("set catch as default", () => selector.SetDefaultRuleset(new CatchRuleset().RulesetInfo));
|
||||
AddStep("select default ruleset", selector.SelectDefaultRuleset);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -39,8 +40,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.8f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@ -173,7 +173,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
s.Statistics.Add(HitResult.Miss, RNG.Next(2000));
|
||||
}
|
||||
|
||||
scoresContainer.Scores = scores;
|
||||
AddStep("Load all scores", () => scoresContainer.Scores = scores);
|
||||
AddStep("Load null scores", () => scoresContainer.Scores = null);
|
||||
AddStep("Load only one score", () => scoresContainer.Scores = new[] { scores.First() });
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -1,17 +1,30 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.KeyBinding;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Settings
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneKeyConfiguration : OsuTestScene
|
||||
public class TestSceneKeyBindingPanel : OsuTestScene
|
||||
{
|
||||
private readonly KeyBindingPanel panel;
|
||||
|
||||
public TestSceneKeyConfiguration()
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(KeyBindingRow),
|
||||
typeof(GlobalKeyBindingsSection),
|
||||
typeof(KeyBindingRow),
|
||||
typeof(KeyBindingsSubsection),
|
||||
typeof(RulesetBindingsSection),
|
||||
typeof(VariantBindingsSubsection),
|
||||
};
|
||||
|
||||
public TestSceneKeyBindingPanel()
|
||||
{
|
||||
Child = panel = new KeyBindingPanel();
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Screens.Tournament;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Tournament
|
||||
{
|
||||
[Description("for tournament use")]
|
||||
public class TestSceneDrawings : ScreenTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadScreen(new Drawings
|
||||
{
|
||||
TeamList = new TestTeamList(),
|
||||
});
|
||||
}
|
||||
|
||||
private class TestTeamList : ITeamList
|
||||
{
|
||||
public IEnumerable<DrawingsTeam> Teams { get; } = new[]
|
||||
{
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "GB",
|
||||
FullName = "United Kingdom",
|
||||
Acronym = "UK"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "FR",
|
||||
FullName = "France",
|
||||
Acronym = "FRA"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "CN",
|
||||
FullName = "China",
|
||||
Acronym = "CHN"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "AU",
|
||||
FullName = "Australia",
|
||||
Acronym = "AUS"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "JP",
|
||||
FullName = "Japan",
|
||||
Acronym = "JPN"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "RO",
|
||||
FullName = "Romania",
|
||||
Acronym = "ROM"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "IT",
|
||||
FullName = "Italy",
|
||||
Acronym = "PIZZA"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "VE",
|
||||
FullName = "Venezuela",
|
||||
Acronym = "VNZ"
|
||||
},
|
||||
new DrawingsTeam
|
||||
{
|
||||
FlagName = "US",
|
||||
FullName = "United States of America",
|
||||
Acronym = "USA"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
52
osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs
Normal file
52
osu.Game.Tests/Visual/UserInterface/TestSceneBackButton.cs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneBackButton : OsuTestScene
|
||||
{
|
||||
private readonly BackButton button;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(TwoLayerButton)
|
||||
};
|
||||
|
||||
public TestSceneBackButton()
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(300),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray
|
||||
},
|
||||
button = new BackButton
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Action = () => button.Hide(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddStep("show button", () => button.Show());
|
||||
AddStep("hide button", () => button.Hide());
|
||||
}
|
||||
}
|
||||
}
|
@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public void TestOsuMods()
|
||||
{
|
||||
var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0);
|
||||
AddStep("change ruleset", () => { Ruleset.Value = ruleset; });
|
||||
changeRuleset(ruleset);
|
||||
|
||||
var instance = ruleset.CreateInstance();
|
||||
|
||||
@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public void TestManiaMods()
|
||||
{
|
||||
var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3);
|
||||
AddStep("change ruleset", () => { Ruleset.Value = ruleset; });
|
||||
changeRuleset(ruleset);
|
||||
|
||||
testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom));
|
||||
}
|
||||
@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0);
|
||||
var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3);
|
||||
|
||||
AddStep("change ruleset to null", () => { Ruleset.Value = null; });
|
||||
changeRuleset(null);
|
||||
|
||||
var instance = rulesetOsu.CreateInstance();
|
||||
var easierMods = instance.GetModsFor(ModType.DifficultyReduction);
|
||||
@ -127,15 +127,15 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; });
|
||||
|
||||
AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; });
|
||||
changeRuleset(rulesetOsu);
|
||||
|
||||
AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null);
|
||||
|
||||
AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; });
|
||||
changeRuleset(rulesetMania);
|
||||
|
||||
AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail));
|
||||
|
||||
AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; });
|
||||
changeRuleset(rulesetOsu);
|
||||
|
||||
AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any());
|
||||
}
|
||||
@ -216,14 +216,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private void testRankedText(Mod mod)
|
||||
{
|
||||
AddWaitStep("wait for fade", 1);
|
||||
AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||
AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||
selectNext(mod);
|
||||
AddWaitStep("wait for fade", 1);
|
||||
AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0);
|
||||
AddUntilStep("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0);
|
||||
selectPrevious(mod);
|
||||
AddWaitStep("wait for fade", 1);
|
||||
AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||
AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||
}
|
||||
|
||||
private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1));
|
||||
@ -239,6 +236,15 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
});
|
||||
}
|
||||
|
||||
private void changeRuleset(RulesetInfo ruleset)
|
||||
{
|
||||
AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; });
|
||||
waitForLoad();
|
||||
}
|
||||
|
||||
private void waitForLoad() =>
|
||||
AddUntilStep("wait for icons to load", () => modSelect.AllLoaded);
|
||||
|
||||
private void checkNotSelected(Mod mod)
|
||||
{
|
||||
AddAssert($"check {mod.Name} is not selected", () =>
|
||||
@ -254,6 +260,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public new Bindable<IReadOnlyList<Mod>> SelectedMods => base.SelectedMods;
|
||||
|
||||
public bool AllLoaded => ModSectionsContainer.Children.All(c => c.ModIconsLoaded);
|
||||
|
||||
public ModButton GetModButton(Mod mod)
|
||||
{
|
||||
var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type);
|
||||
|
@ -18,9 +18,6 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[TestFixture]
|
||||
public class TestSceneNotificationOverlay : OsuTestScene
|
||||
{
|
||||
private readonly NotificationOverlay manager;
|
||||
private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(NotificationSection),
|
||||
@ -31,25 +28,33 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
typeof(Notification)
|
||||
};
|
||||
|
||||
public TestSceneNotificationOverlay()
|
||||
private NotificationOverlay notificationOverlay;
|
||||
|
||||
private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
|
||||
|
||||
private SpriteText displayedCount;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
progressingNotifications.Clear();
|
||||
|
||||
Content.Add(manager = new NotificationOverlay
|
||||
Content.Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight
|
||||
});
|
||||
notificationOverlay = new NotificationOverlay
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
displayedCount = new OsuSpriteText()
|
||||
};
|
||||
|
||||
SpriteText displayedCount = new OsuSpriteText();
|
||||
|
||||
Content.Add(displayedCount);
|
||||
|
||||
void setState(Visibility state) => AddStep(state.ToString(), () => manager.State.Value = state);
|
||||
void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
|
||||
|
||||
manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; };
|
||||
notificationOverlay.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; };
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestBasicFlow()
|
||||
{
|
||||
setState(Visibility.Visible);
|
||||
AddStep(@"simple #1", sendHelloNotification);
|
||||
AddStep(@"simple #2", sendAmazingNotification);
|
||||
@ -61,6 +66,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
setState(Visibility.Hidden);
|
||||
|
||||
AddRepeatStep(@"add many simple", sendManyNotifications, 3);
|
||||
|
||||
AddWaitStep("wait some", 5);
|
||||
|
||||
checkProgressingCount(0);
|
||||
@ -69,18 +75,122 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
checkProgressingCount(1);
|
||||
|
||||
AddAssert("Displayed count is 33", () => manager.UnreadCount.Value == 33);
|
||||
checkDisplayedCount(33);
|
||||
|
||||
AddWaitStep("wait some", 10);
|
||||
|
||||
checkProgressingCount(0);
|
||||
|
||||
setState(Visibility.Visible);
|
||||
|
||||
//AddStep(@"barrage", () => sendBarrage());
|
||||
}
|
||||
|
||||
private void sendBarrage(int remaining = 10)
|
||||
[Test]
|
||||
public void TestImportantWhileClosed()
|
||||
{
|
||||
AddStep(@"simple #1", sendHelloNotification);
|
||||
|
||||
AddAssert("Is visible", () => notificationOverlay.State.Value == Visibility.Visible);
|
||||
|
||||
checkDisplayedCount(1);
|
||||
|
||||
AddStep(@"progress #1", sendUploadProgress);
|
||||
AddStep(@"progress #2", sendDownloadProgress);
|
||||
|
||||
checkProgressingCount(2);
|
||||
checkDisplayedCount(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUnimportantWhileClosed()
|
||||
{
|
||||
AddStep(@"background #1", sendBackgroundNotification);
|
||||
|
||||
AddAssert("Is not visible", () => notificationOverlay.State.Value == Visibility.Hidden);
|
||||
|
||||
checkDisplayedCount(1);
|
||||
|
||||
AddStep(@"background progress #1", sendBackgroundUploadProgress);
|
||||
|
||||
AddWaitStep("wait some", 5);
|
||||
|
||||
checkProgressingCount(0);
|
||||
|
||||
checkDisplayedCount(2);
|
||||
|
||||
AddStep(@"simple #1", sendHelloNotification);
|
||||
|
||||
checkDisplayedCount(3);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSpam()
|
||||
{
|
||||
setState(Visibility.Visible);
|
||||
AddRepeatStep("send barrage", sendBarrage, 10);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
progressingNotifications.RemoveAll(n => n.State == ProgressNotificationState.Completed);
|
||||
|
||||
if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
|
||||
{
|
||||
var p = progressingNotifications.Find(n => n.State == ProgressNotificationState.Queued);
|
||||
|
||||
if (p != null)
|
||||
p.State = ProgressNotificationState.Active;
|
||||
}
|
||||
|
||||
foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active))
|
||||
{
|
||||
if (n.Progress < 1)
|
||||
n.Progress += (float)(Time.Elapsed / 400) * RNG.NextSingle();
|
||||
else
|
||||
n.State = ProgressNotificationState.Completed;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDisplayedCount(int expected) =>
|
||||
AddAssert($"Displayed count is {expected}", () => notificationOverlay.UnreadCount.Value == expected);
|
||||
|
||||
private void sendDownloadProgress()
|
||||
{
|
||||
var n = new ProgressNotification
|
||||
{
|
||||
Text = @"Downloading Haitai...",
|
||||
CompletionText = "Downloaded Haitai!",
|
||||
};
|
||||
notificationOverlay.Post(n);
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
private void sendUploadProgress()
|
||||
{
|
||||
var n = new ProgressNotification
|
||||
{
|
||||
Text = @"Uploading to BSS...",
|
||||
CompletionText = "Uploaded to BSS!",
|
||||
};
|
||||
notificationOverlay.Post(n);
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
private void sendBackgroundUploadProgress()
|
||||
{
|
||||
var n = new BackgroundProgressNotification
|
||||
{
|
||||
Text = @"Uploading to BSS...",
|
||||
CompletionText = "Uploaded to BSS!",
|
||||
};
|
||||
notificationOverlay.Post(n);
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
private void setState(Visibility state) => AddStep(state.ToString(), () => notificationOverlay.State.Value = state);
|
||||
|
||||
private void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
|
||||
|
||||
private void sendBarrage()
|
||||
{
|
||||
switch (RNG.Next(0, 4))
|
||||
{
|
||||
@ -100,69 +210,37 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
sendDownloadProgress();
|
||||
break;
|
||||
}
|
||||
|
||||
if (remaining > 0)
|
||||
Scheduler.AddDelayed(() => sendBarrage(remaining - 1), 80);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
progressingNotifications.RemoveAll(n => n.State == ProgressNotificationState.Completed);
|
||||
|
||||
if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
|
||||
{
|
||||
var p = progressingNotifications.Find(n => n.State == ProgressNotificationState.Queued);
|
||||
if (p != null)
|
||||
p.State = ProgressNotificationState.Active;
|
||||
}
|
||||
|
||||
foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active))
|
||||
{
|
||||
if (n.Progress < 1)
|
||||
n.Progress += (float)(Time.Elapsed / 400) * RNG.NextSingle();
|
||||
else
|
||||
n.State = ProgressNotificationState.Completed;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendDownloadProgress()
|
||||
{
|
||||
var n = new ProgressNotification
|
||||
{
|
||||
Text = @"Downloading Haitai...",
|
||||
CompletionText = "Downloaded Haitai!",
|
||||
};
|
||||
manager.Post(n);
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
private void sendUploadProgress()
|
||||
{
|
||||
var n = new ProgressNotification
|
||||
{
|
||||
Text = @"Uploading to BSS...",
|
||||
CompletionText = "Uploaded to BSS!",
|
||||
};
|
||||
manager.Post(n);
|
||||
progressingNotifications.Add(n);
|
||||
}
|
||||
|
||||
private void sendAmazingNotification()
|
||||
{
|
||||
manager.Post(new SimpleNotification { Text = @"You are amazing" });
|
||||
notificationOverlay.Post(new SimpleNotification { Text = @"You are amazing" });
|
||||
}
|
||||
|
||||
private void sendHelloNotification()
|
||||
{
|
||||
manager.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
|
||||
notificationOverlay.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
|
||||
}
|
||||
|
||||
private void sendBackgroundNotification()
|
||||
{
|
||||
notificationOverlay.Post(new BackgroundNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
|
||||
}
|
||||
|
||||
private void sendManyNotifications()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
manager.Post(new SimpleNotification { Text = @"Spam incoming!!" });
|
||||
notificationOverlay.Post(new SimpleNotification { Text = @"Spam incoming!!" });
|
||||
}
|
||||
|
||||
private class BackgroundNotification : SimpleNotification
|
||||
{
|
||||
public override bool IsImportant => false;
|
||||
}
|
||||
|
||||
private class BackgroundProgressNotification : ProgressNotification
|
||||
{
|
||||
public override bool IsImportant => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
55
osu.Game.Tests/Visual/UserInterface/TestSceneNumberBox.cs
Normal file
55
osu.Game.Tests/Visual/UserInterface/TestSceneNumberBox.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneNumberBox : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuNumberBox),
|
||||
};
|
||||
|
||||
private OsuNumberBox numberBox;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Padding = new MarginPadding { Horizontal = 250 },
|
||||
Child = numberBox = new OsuNumberBox
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
PlaceholderText = "Insert numbers here"
|
||||
}
|
||||
};
|
||||
|
||||
clearInput();
|
||||
AddStep("enter numbers", () => numberBox.Text = "987654321");
|
||||
expectedValue("987654321");
|
||||
clearInput();
|
||||
AddStep("enter text + single number", () => numberBox.Text = "1 hello 2 world 3");
|
||||
expectedValue("123");
|
||||
clearInput();
|
||||
}
|
||||
|
||||
private void clearInput() => AddStep("clear input", () => numberBox.Text = null);
|
||||
|
||||
private void expectedValue(string value) => AddAssert("expect number", () => numberBox.Text == value);
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
// 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.Containers;
|
||||
using osu.Game.Overlays.Toolbar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneToolbarRulesetSelector : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ToolbarRulesetSelector),
|
||||
typeof(ToolbarRulesetTabButton),
|
||||
};
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[Test]
|
||||
public void TestDisplay()
|
||||
{
|
||||
ToolbarRulesetSelector selector = null;
|
||||
|
||||
AddStep("create selector", () =>
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = Toolbar.HEIGHT,
|
||||
Child = selector = new ToolbarRulesetSelector()
|
||||
};
|
||||
});
|
||||
|
||||
AddStep("Select random", () =>
|
||||
{
|
||||
selector.Current.Value = selector.Items.ElementAt(RNG.Next(selector.Items.Count()));
|
||||
});
|
||||
AddStep("Toggle disabled state", () => selector.Current.Disabled = !selector.Current.Disabled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNonFirstRulesetInitialState()
|
||||
{
|
||||
TestSelector selector = null;
|
||||
|
||||
AddStep("create selector", () =>
|
||||
{
|
||||
Child = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = Toolbar.HEIGHT,
|
||||
Child = selector = new TestSelector()
|
||||
};
|
||||
|
||||
selector.Current.Value = rulesets.GetRuleset(2);
|
||||
});
|
||||
|
||||
AddAssert("mode line has moved", () => selector.ModeButtonLine.DrawPosition.X > 0);
|
||||
}
|
||||
|
||||
private class TestSelector : ToolbarRulesetSelector
|
||||
{
|
||||
public new Drawable ModeButtonLine => base.ModeButtonLine;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,26 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
[Description("mostly back button")]
|
||||
public class TestSceneTwoLayerButton : OsuTestScene
|
||||
{
|
||||
public TestSceneTwoLayerButton()
|
||||
{
|
||||
Add(new BackButton());
|
||||
Add(new TwoLayerButton
|
||||
{
|
||||
Position = new Vector2(100),
|
||||
Text = "button",
|
||||
Icon = FontAwesome.Solid.Check,
|
||||
BackgroundColour = Color4.SlateGray,
|
||||
HoverColour = Color4.SlateGray.Darken(0.2f)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
osu.Game.Tournament.Tests/.vscode/launch.json
vendored
Normal file
31
osu.Game.Tournament.Tests/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "VisualTests (Debug)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Tournament.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Debug)",
|
||||
"env": {},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "VisualTests (Release)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "dotnet",
|
||||
"args": [
|
||||
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Tournament.Tests.dll"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build (Release)",
|
||||
"env": {},
|
||||
"console": "internalConsole"
|
||||
}
|
||||
]
|
||||
}
|
47
osu.Game.Tournament.Tests/.vscode/tasks.json
vendored
Normal file
47
osu.Game.Tournament.Tests/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build (Debug)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests.csproj",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Build (Release)",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"build",
|
||||
"--no-restore",
|
||||
"osu.Game.Tournament.Tests.csproj",
|
||||
"/p:Configuration=Release",
|
||||
"/p:GenerateFullPaths=true",
|
||||
"/m",
|
||||
"/verbosity:m"
|
||||
],
|
||||
"group": "build",
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "Restore",
|
||||
"type": "shell",
|
||||
"command": "dotnet",
|
||||
"args": [
|
||||
"restore"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Components
|
||||
{
|
||||
public class TestSceneDrawableTournamentMatch : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(TournamentMatch),
|
||||
typeof(DrawableTournamentTeam),
|
||||
};
|
||||
|
||||
public TestSceneDrawableTournamentMatch()
|
||||
{
|
||||
Container<DrawableTournamentMatch> level1;
|
||||
Container<DrawableTournamentMatch> level2;
|
||||
|
||||
var match1 = new TournamentMatch(
|
||||
new TournamentTeam { FlagName = { Value = "AU" }, FullName = { Value = "Australia" }, },
|
||||
new TournamentTeam { FlagName = { Value = "JP" }, FullName = { Value = "Japan" }, Acronym = { Value = "JPN" } })
|
||||
{
|
||||
Team1Score = { Value = 4 },
|
||||
Team2Score = { Value = 1 },
|
||||
};
|
||||
|
||||
var match2 = new TournamentMatch(
|
||||
new TournamentTeam
|
||||
{
|
||||
FlagName = { Value = "RO" },
|
||||
FullName = { Value = "Romania" },
|
||||
}
|
||||
);
|
||||
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
level1 = new FillFlowContainer<DrawableTournamentMatch>
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new[]
|
||||
{
|
||||
new DrawableTournamentMatch(match1),
|
||||
new DrawableTournamentMatch(match2),
|
||||
new DrawableTournamentMatch(new TournamentMatch()),
|
||||
}
|
||||
},
|
||||
level2 = new FillFlowContainer<DrawableTournamentMatch>
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Vertical,
|
||||
Margin = new MarginPadding(20),
|
||||
Children = new[]
|
||||
{
|
||||
new DrawableTournamentMatch(new TournamentMatch()),
|
||||
new DrawableTournamentMatch(new TournamentMatch())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
level1.Children[0].Match.Progression.Value = level2.Children[0].Match;
|
||||
level1.Children[1].Match.Progression.Value = level2.Children[0].Match;
|
||||
|
||||
AddRepeatStep("change scores", () => match1.Team2Score.Value++, 4);
|
||||
AddStep("add new team", () => match2.Team2.Value = new TournamentTeam { FlagName = { Value = "PT" }, FullName = { Value = "Portugal" } });
|
||||
AddStep("Add progression", () => level1.Children[2].Match.Progression.Value = level2.Children[1].Match);
|
||||
|
||||
AddStep("start match", () => match2.StartMatch());
|
||||
|
||||
AddRepeatStep("change scores", () => match2.Team1Score.Value++, 10);
|
||||
|
||||
AddStep("start submatch", () => level2.Children[0].Match.StartMatch());
|
||||
|
||||
AddRepeatStep("change scores", () => level2.Children[0].Match.Team1Score.Value++, 5);
|
||||
|
||||
AddRepeatStep("change scores", () => level2.Children[0].Match.Team2Score.Value++, 4);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// 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.MathUtils;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Screens.Gameplay.Components;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Components
|
||||
{
|
||||
public class TestSceneMatchScoreDisplay : LadderTestScene
|
||||
{
|
||||
[Cached(Type = typeof(MatchIPCInfo))]
|
||||
private MatchIPCInfo matchInfo = new MatchIPCInfo();
|
||||
|
||||
public TestSceneMatchScoreDisplay()
|
||||
{
|
||||
Add(new MatchScoreDisplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Scheduler.AddDelayed(() =>
|
||||
{
|
||||
int amount = (int)((RNG.NextDouble() - 0.5) * 10000);
|
||||
if (amount < 0)
|
||||
matchInfo.Score1.Value -= amount;
|
||||
else
|
||||
matchInfo.Score2.Value += amount;
|
||||
}, 100, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
// 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.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.Tests.Visual;
|
||||
using osu.Game.Tournament.Components;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Components
|
||||
{
|
||||
public class TestSceneTournamentBeatmapPanel : OsuTestScene
|
||||
{
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 });
|
||||
req.Success += success;
|
||||
api.Queue(req);
|
||||
}
|
||||
|
||||
private void success(APIBeatmap apiBeatmap)
|
||||
{
|
||||
var beatmap = apiBeatmap.ToBeatmap(rulesets);
|
||||
Add(new TournamentBeatmapPanel(beatmap)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Components
|
||||
{
|
||||
public class TestSceneTournamentMatchChatDisplay : OsuTestScene
|
||||
{
|
||||
private readonly Channel testChannel = new Channel();
|
||||
private readonly Channel testChannel2 = new Channel();
|
||||
|
||||
private readonly User admin = new User
|
||||
{
|
||||
Username = "HappyStick",
|
||||
Id = 2,
|
||||
Colour = "f2ca34"
|
||||
};
|
||||
|
||||
private readonly User redUser = new User
|
||||
{
|
||||
Username = "BanchoBot",
|
||||
Id = 3,
|
||||
};
|
||||
|
||||
private readonly User blueUser = new User
|
||||
{
|
||||
Username = "Zallius",
|
||||
Id = 4,
|
||||
};
|
||||
|
||||
[Cached]
|
||||
private LadderInfo ladderInfo = new LadderInfo();
|
||||
|
||||
[Cached]
|
||||
private MatchIPCInfo matchInfo = new MatchIPCInfo(); // hide parent
|
||||
|
||||
private readonly TournamentMatchChatDisplay chatDisplay;
|
||||
|
||||
public TestSceneTournamentMatchChatDisplay()
|
||||
{
|
||||
Add(chatDisplay = new TournamentMatchChatDisplay
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
|
||||
ladderInfo.CurrentMatch.Value = new TournamentMatch
|
||||
{
|
||||
Team1 =
|
||||
{
|
||||
Value = new TournamentTeam { Players = new BindableList<User> { redUser } }
|
||||
},
|
||||
Team2 =
|
||||
{
|
||||
Value = new TournamentTeam { Players = new BindableList<User> { blueUser } }
|
||||
}
|
||||
};
|
||||
|
||||
chatDisplay.Channel.Value = testChannel;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I am a wang!"
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I am team red."
|
||||
}));
|
||||
|
||||
AddStep("message from team red", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = redUser,
|
||||
Content = "I plan to win!"
|
||||
}));
|
||||
|
||||
AddStep("message from team blue", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = blueUser,
|
||||
Content = "Not on my watch. Prepare to eat saaaaaaaaaand. Lots and lots of saaaaaaand."
|
||||
}));
|
||||
|
||||
AddStep("message from admin", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "Okay okay, calm down guys. Let's do this!"
|
||||
}));
|
||||
|
||||
AddStep("multiple messages", () => testChannel.AddNewMessages(new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I spam you!"
|
||||
},
|
||||
new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I spam you!!!1"
|
||||
},
|
||||
new Message(nextMessageId())
|
||||
{
|
||||
Sender = admin,
|
||||
Content = "I spam you!1!1"
|
||||
}));
|
||||
|
||||
AddStep("change channel to 2", () => chatDisplay.Channel.Value = testChannel2);
|
||||
|
||||
AddStep("change channel to 1", () => chatDisplay.Channel.Value = testChannel);
|
||||
}
|
||||
|
||||
private int messageId;
|
||||
|
||||
private long? nextMessageId() => messageId++;
|
||||
}
|
||||
}
|
15
osu.Game.Tournament.Tests/LadderTestScene.cs
Normal file
15
osu.Game.Tournament.Tests/LadderTestScene.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// 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.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Tests
|
||||
{
|
||||
public abstract class LadderTestScene : OsuTestScene
|
||||
{
|
||||
[Resolved]
|
||||
protected LadderInfo Ladder { get; private set; }
|
||||
}
|
||||
}
|
23
osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs
Normal file
23
osu.Game.Tournament.Tests/Screens/TestSceneGameplayScreen.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Screens.Gameplay;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneGameplayScreen : OsuTestScene
|
||||
{
|
||||
[Cached]
|
||||
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new GameplayScreen());
|
||||
Add(chat);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// 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.Game.Graphics.Cursor;
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneLadderEditorScreen : LadderTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new LadderEditorScreen()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
23
osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs
Normal file
23
osu.Game.Tournament.Tests/Screens/TestSceneLadderScreen.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.Game.Graphics.Cursor;
|
||||
using osu.Game.Tournament.Screens.Ladder;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneLadderScreen : LadderTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new LadderScreen()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
24
osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs
Normal file
24
osu.Game.Tournament.Tests/Screens/TestSceneMapPoolScreen.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Tournament.Screens.MapPool;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneMapPoolScreen : LadderTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(MapPoolScreen)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new MapPoolScreen { Width = 0.7f });
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneRoundEditorScreen : LadderTestScene
|
||||
{
|
||||
public TestSceneRoundEditorScreen()
|
||||
{
|
||||
Add(new RoundEditorScreen
|
||||
{
|
||||
Width = 0.85f // create room for control panel
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
18
osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs
Normal file
18
osu.Game.Tournament.Tests/Screens/TestSceneScheduleScreen.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Screens.Schedule;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneScheduleScreen : OsuTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new ScheduleScreen());
|
||||
}
|
||||
}
|
||||
}
|
18
osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs
Normal file
18
osu.Game.Tournament.Tests/Screens/TestSceneShowcaseScreen.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Screens.Showcase;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneShowcaseScreen : OsuTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(new ShowcaseScreen());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneTeamEditorScreen : LadderTestScene
|
||||
{
|
||||
public TestSceneTeamEditorScreen()
|
||||
{
|
||||
Add(new TeamEditorScreen
|
||||
{
|
||||
Width = 0.85f // create room for control panel
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.TeamIntro;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneTeamIntroScreen : LadderTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var match = new TournamentMatch();
|
||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
||||
currentMatch.Value = match;
|
||||
|
||||
Add(new TeamIntroScreen
|
||||
{
|
||||
FillMode = FillMode.Fit,
|
||||
FillAspectRatio = 16 / 9f
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
34
osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs
Normal file
34
osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.TeamWin;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneTeamWinScreen : LadderTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var match = new TournamentMatch();
|
||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
||||
currentMatch.Value = match;
|
||||
|
||||
Add(new TeamWinScreen
|
||||
{
|
||||
FillMode = FillMode.Fit,
|
||||
FillAspectRatio = 16 / 9f
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
18
osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs
Normal file
18
osu.Game.Tournament.Tests/TestSceneTournamentSceneManager.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Tournament.Tests
|
||||
{
|
||||
public class TestSceneTournamentSceneManager : OsuTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(Storage storage)
|
||||
{
|
||||
Add(new TournamentSceneManager());
|
||||
}
|
||||
}
|
||||
}
|
27
osu.Game.Tournament.Tests/TournamentTestBrowser.cs
Normal file
27
osu.Game.Tournament.Tests/TournamentTestBrowser.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
|
||||
namespace osu.Game.Tournament.Tests
|
||||
{
|
||||
public class TournamentTestBrowser : TournamentGameBase
|
||||
{
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
LoadComponentAsync(new Background("Menu/menu-background-0")
|
||||
{
|
||||
Colour = OsuColour.Gray(0.5f),
|
||||
Depth = 10
|
||||
}, AddInternal);
|
||||
|
||||
// Have to construct this here, rather than in the constructor, because
|
||||
// we depend on some dependencies to be loaded within OsuGameBase.load().
|
||||
Add(new TestBrowser());
|
||||
}
|
||||
}
|
||||
}
|
22
osu.Game.Tournament.Tests/TournamentTestRunner.cs
Normal file
22
osu.Game.Tournament.Tests/TournamentTestRunner.cs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Game.Tournament.Tests
|
||||
{
|
||||
public static class TournamentTestRunner
|
||||
{
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true))
|
||||
{
|
||||
host.Run(new TournamentTestBrowser());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
Normal file
23
osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj
Normal file
@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\osu.TestProject.props" />
|
||||
<PropertyGroup>
|
||||
<StartupObject>osu.Game.Tournament.Tests.TournamentTestRunner</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Project">
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||
<ProjectReference Include="..\osu.Game.Tournament\osu.Game.Tournament.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
69
osu.Game.Tournament/Components/ControlPanel.cs
Normal file
69
osu.Game.Tournament/Components/ControlPanel.cs
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// An element anchored to the right-hand area of a screen that provides streamer level controls.
|
||||
/// Should be off-screen.
|
||||
/// </summary>
|
||||
public class ControlPanel : Container
|
||||
{
|
||||
private readonly FillFlowContainer buttons;
|
||||
|
||||
protected override Container<Drawable> Content => buttons;
|
||||
|
||||
public ControlPanel()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
AlwaysPresent = true;
|
||||
Width = 0.15f;
|
||||
Anchor = Anchor.TopRight;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = new Color4(54, 54, 54, 255)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Control Panel",
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22)
|
||||
},
|
||||
buttons = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Width = 0.75f,
|
||||
Position = new Vector2(0, 35f),
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5f),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public class Spacer : CompositeDrawable
|
||||
{
|
||||
public Spacer(float height = 20)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height;
|
||||
AlwaysPresent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
44
osu.Game.Tournament/Components/DateTextBox.cs
Normal file
44
osu.Game.Tournament/Components/DateTextBox.cs
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Settings;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class DateTextBox : SettingsTextBox
|
||||
{
|
||||
public new Bindable<DateTimeOffset> Bindable
|
||||
{
|
||||
get => bindable;
|
||||
set
|
||||
{
|
||||
bindable = value.GetBoundCopy();
|
||||
bindable.BindValueChanged(dto =>
|
||||
base.Bindable.Value = dto.NewValue.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"), true);
|
||||
}
|
||||
}
|
||||
|
||||
// hold a reference to the provided bindable so we don't have to in every settings section.
|
||||
private Bindable<DateTimeOffset> bindable;
|
||||
|
||||
public DateTextBox()
|
||||
{
|
||||
base.Bindable = new Bindable<string>();
|
||||
((OsuTextBox)Control).OnCommit = (sender, newText) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
bindable.Value = DateTimeOffset.Parse(sender.Text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// reset textbox content to its last valid state on a parse failure.
|
||||
bindable.TriggerChange();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
55
osu.Game.Tournament/Components/DrawableTournamentTeam.cs
Normal file
55
osu.Game.Tournament/Components/DrawableTournamentTeam.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public abstract class DrawableTournamentTeam : CompositeDrawable
|
||||
{
|
||||
public readonly TournamentTeam Team;
|
||||
|
||||
protected readonly Sprite Flag;
|
||||
protected readonly OsuSpriteText AcronymText;
|
||||
|
||||
[UsedImplicitly]
|
||||
private Bindable<string> acronym;
|
||||
|
||||
[UsedImplicitly]
|
||||
private Bindable<string> flag;
|
||||
|
||||
protected DrawableTournamentTeam(TournamentTeam team)
|
||||
{
|
||||
Team = team;
|
||||
|
||||
Flag = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit
|
||||
};
|
||||
|
||||
AcronymText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
if (Team == null) return;
|
||||
|
||||
(acronym = Team.Acronym.GetBoundCopy()).BindValueChanged(acronym => AcronymText.Text = Team?.Acronym.Value?.ToUpperInvariant() ?? string.Empty, true);
|
||||
(flag = Team.FlagName.GetBoundCopy()).BindValueChanged(acronym => Flag.Texture = textures.Get($@"Flags/{Team.FlagName}"), true);
|
||||
}
|
||||
}
|
||||
}
|
251
osu.Game.Tournament/Components/SongBar.cs
Normal file
251
osu.Game.Tournament/Components/SongBar.cs
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class SongBar : CompositeDrawable
|
||||
{
|
||||
private BeatmapInfo beatmap;
|
||||
|
||||
public BeatmapInfo Beatmap
|
||||
{
|
||||
get => beatmap;
|
||||
set
|
||||
{
|
||||
if (beatmap == value)
|
||||
return;
|
||||
|
||||
beatmap = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
private LegacyMods mods;
|
||||
|
||||
public LegacyMods Mods
|
||||
{
|
||||
get => mods;
|
||||
set
|
||||
{
|
||||
mods = value;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
private Container panelContents;
|
||||
private Container innerPanel;
|
||||
private Container outerPanel;
|
||||
private TournamentBeatmapPanel panel;
|
||||
|
||||
private float panelWidth => expanded ? 0.6f : 1;
|
||||
|
||||
private const float main_width = 0.97f;
|
||||
private const float inner_panel_width = 0.7f;
|
||||
|
||||
private bool expanded;
|
||||
|
||||
public bool Expanded
|
||||
{
|
||||
get => expanded;
|
||||
set
|
||||
{
|
||||
expanded = value;
|
||||
panel?.ResizeWidthTo(panelWidth, 800, Easing.OutQuint);
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
innerPanel.ResizeWidthTo(inner_panel_width, 800, Easing.OutQuint);
|
||||
outerPanel.ResizeWidthTo(main_width, 800, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
innerPanel.ResizeWidthTo(1, 800, Easing.OutQuint);
|
||||
outerPanel.ResizeWidthTo(0.25f, 800, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
outerPanel = new Container
|
||||
{
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 5,
|
||||
},
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
RelativePositionAxes = Axes.X,
|
||||
X = -(1 - main_width) / 2,
|
||||
Y = -10,
|
||||
Width = main_width,
|
||||
Height = TournamentBeatmapPanel.HEIGHT,
|
||||
CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.93f),
|
||||
},
|
||||
new OsuLogo
|
||||
{
|
||||
Triangles = false,
|
||||
Colour = OsuColour.Gray(0.33f),
|
||||
Scale = new Vector2(0.08f),
|
||||
Margin = new MarginPadding(50),
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
},
|
||||
innerPanel = new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = inner_panel_width,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.86f),
|
||||
},
|
||||
panelContents = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Expanded = true;
|
||||
}
|
||||
|
||||
private void update()
|
||||
{
|
||||
if (beatmap == null)
|
||||
{
|
||||
panelContents.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
var bpm = beatmap.BeatmapSet.OnlineInfo.BPM;
|
||||
var length = beatmap.OnlineInfo.Length;
|
||||
string hardRockExtra = "";
|
||||
string srExtra = "";
|
||||
|
||||
//var ar = beatmap.BaseDifficulty.ApproachRate;
|
||||
if ((mods & LegacyMods.HardRock) > 0)
|
||||
{
|
||||
hardRockExtra = "*";
|
||||
srExtra = "*";
|
||||
}
|
||||
|
||||
if ((mods & LegacyMods.DoubleTime) > 0)
|
||||
{
|
||||
//ar *= 1.5f;
|
||||
bpm *= 1.5f;
|
||||
length /= 1.5f;
|
||||
srExtra = "*";
|
||||
}
|
||||
|
||||
panelContents.Children = new Drawable[]
|
||||
{
|
||||
new DiffPiece(("Length", TimeSpan.FromSeconds(length).ToString(@"mm\:ss")))
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
},
|
||||
new DiffPiece(("BPM", $"{bpm:0.#}"))
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.TopLeft
|
||||
},
|
||||
new DiffPiece(
|
||||
//("CS", $"{beatmap.BaseDifficulty.CircleSize:0.#}{hardRockExtra}"),
|
||||
//("AR", $"{ar:0.#}{srExtra}"),
|
||||
("OD", $"{beatmap.BaseDifficulty.OverallDifficulty:0.#}{hardRockExtra}"),
|
||||
("HP", $"{beatmap.BaseDifficulty.DrainRate:0.#}{hardRockExtra}")
|
||||
)
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.BottomRight
|
||||
},
|
||||
new DiffPiece(("Star Rating", $"{beatmap.StarDifficulty:0.#}{srExtra}"))
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
panel = new TournamentBeatmapPanel(beatmap)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(panelWidth, 1)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class DiffPiece : TextFlowContainer
|
||||
{
|
||||
public DiffPiece(params (string heading, string content)[] tuples)
|
||||
{
|
||||
Margin = new MarginPadding { Horizontal = 15, Vertical = 1 };
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
void cp(SpriteText s, Color4 colour)
|
||||
{
|
||||
s.Colour = colour;
|
||||
s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tuples.Length; i++)
|
||||
{
|
||||
var tuple = tuples[i];
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
AddText(" / ", s =>
|
||||
{
|
||||
cp(s, OsuColour.Gray(0.33f));
|
||||
s.Spacing = new Vector2(-2, 0);
|
||||
});
|
||||
}
|
||||
|
||||
AddText(new OsuSpriteText { Text = tuple.heading }, s => cp(s, OsuColour.Gray(0.33f)));
|
||||
AddText(" ", s => cp(s, OsuColour.Gray(0.33f)));
|
||||
AddText(new OsuSpriteText { Text = tuple.content }, s => cp(s, OsuColour.Gray(0.5f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
203
osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
Normal file
203
osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class TournamentBeatmapPanel : CompositeDrawable
|
||||
{
|
||||
public readonly BeatmapInfo Beatmap;
|
||||
private readonly string mods;
|
||||
|
||||
private const float horizontal_padding = 10;
|
||||
private const float vertical_padding = 5;
|
||||
|
||||
public const float HEIGHT = 50;
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private Box flash;
|
||||
|
||||
public TournamentBeatmapPanel(BeatmapInfo beatmap, string mods = null)
|
||||
{
|
||||
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
|
||||
|
||||
Beatmap = beatmap;
|
||||
this.mods = mods;
|
||||
Width = 400;
|
||||
Height = HEIGHT;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, TextureStore textures)
|
||||
{
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
|
||||
CornerRadius = HEIGHT / 2;
|
||||
Masking = true;
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
new UpdateableBeatmapSetCover
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.5f),
|
||||
BeatmapSet = Beatmap.BeatmapSet,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Padding = new MarginPadding(vertical_padding),
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((
|
||||
$"{Beatmap.Metadata.ArtistUnicode ?? Beatmap.Metadata.Artist} - {Beatmap.Metadata.TitleUnicode ?? Beatmap.Metadata.Title}",
|
||||
$"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")),
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Padding = new MarginPadding(vertical_padding),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "mapper",
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = Beatmap.Metadata.AuthorString,
|
||||
Padding = new MarginPadding { Right = 20 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "difficulty",
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = Beatmap.Version,
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
flash = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Gray,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0,
|
||||
},
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(mods))
|
||||
AddInternal(new Sprite
|
||||
{
|
||||
Texture = textures.Get($"mods/{mods}"),
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Margin = new MarginPadding(20),
|
||||
Scale = new Vector2(0.5f)
|
||||
});
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
if (match.OldValue != null)
|
||||
match.OldValue.PicksBans.CollectionChanged -= picksBansOnCollectionChanged;
|
||||
match.NewValue.PicksBans.CollectionChanged += picksBansOnCollectionChanged;
|
||||
updateState();
|
||||
}
|
||||
|
||||
private void picksBansOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
=> updateState();
|
||||
|
||||
private BeatmapChoice choice;
|
||||
|
||||
private void updateState()
|
||||
{
|
||||
var found = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == Beatmap.OnlineBeatmapID);
|
||||
|
||||
bool doFlash = found != choice;
|
||||
choice = found;
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
if (doFlash)
|
||||
flash?.FadeOutFromOne(500).Loop(0, 10);
|
||||
|
||||
BorderThickness = 6;
|
||||
|
||||
switch (found.Team)
|
||||
{
|
||||
case TeamColour.Red:
|
||||
BorderColour = Color4.Red;
|
||||
break;
|
||||
|
||||
case TeamColour.Blue:
|
||||
BorderColour = Color4.Blue;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (found.Type)
|
||||
{
|
||||
case ChoiceType.Pick:
|
||||
Colour = Color4.White;
|
||||
Alpha = 1;
|
||||
break;
|
||||
|
||||
case ChoiceType.Ban:
|
||||
Colour = Color4.Gray;
|
||||
Alpha = 0.5f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Colour = Color4.White;
|
||||
BorderThickness = 0;
|
||||
Alpha = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs
Normal file
93
osu.Game.Tournament/Components/TournamentMatchChatDisplay.cs
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Overlays.Chat;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class TournamentMatchChatDisplay : StandAloneChatDisplay
|
||||
{
|
||||
private readonly Bindable<string> chatChannel = new Bindable<string>();
|
||||
|
||||
private ChannelManager manager;
|
||||
|
||||
public TournamentMatchChatDisplay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Y = 100;
|
||||
Size = new Vector2(0.45f, 112);
|
||||
Margin = new MarginPadding(10);
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(MatchIPCInfo ipc)
|
||||
{
|
||||
if (ipc != null)
|
||||
{
|
||||
chatChannel.BindTo(ipc.ChatChannel);
|
||||
chatChannel.BindValueChanged(c =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(c.NewValue))
|
||||
return;
|
||||
|
||||
int id = int.Parse(c.NewValue);
|
||||
|
||||
if (id <= 0) return;
|
||||
|
||||
if (manager == null)
|
||||
{
|
||||
AddInternal(manager = new ChannelManager());
|
||||
Channel.BindTo(manager.CurrentChannel);
|
||||
}
|
||||
|
||||
foreach (var ch in manager.JoinedChannels.ToList())
|
||||
manager.LeaveChannel(ch);
|
||||
|
||||
var channel = new Channel
|
||||
{
|
||||
Id = id,
|
||||
Type = ChannelType.Public
|
||||
};
|
||||
|
||||
manager.JoinChannel(channel);
|
||||
manager.CurrentChannel.Value = channel;
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override ChatLine CreateMessage(Message message) => new MatchMessage(message);
|
||||
|
||||
protected class MatchMessage : StandAloneMessage
|
||||
{
|
||||
public MatchMessage(Message message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo info)
|
||||
{
|
||||
//if (info.CurrentMatch.Value.Team1.Value.Players.Any(u => u.Id == Message.Sender.Id))
|
||||
// ColourBox.Colour = red;
|
||||
//else if (info.CurrentMatch.Value.Team2.Value.Players.Any(u => u.Id == Message.Sender.Id))
|
||||
// ColourBox.Colour = blue;
|
||||
//else if (Message.Sender.Colour != null)
|
||||
// SenderText.Colour = ColourBox.Colour = OsuColour.FromHex(Message.Sender.Colour);
|
||||
}
|
||||
|
||||
private readonly Color4 red = new Color4(186, 0, 18, 255);
|
||||
private readonly Color4 blue = new Color4(17, 136, 170, 255);
|
||||
}
|
||||
}
|
||||
}
|
45
osu.Game.Tournament/Components/TourneyVideo.cs
Normal file
45
osu.Game.Tournament/Components/TourneyVideo.cs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.IO;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Video;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class TourneyVideo : CompositeDrawable
|
||||
{
|
||||
private readonly VideoSprite video;
|
||||
|
||||
public TourneyVideo(Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
{
|
||||
InternalChild = new Box
|
||||
{
|
||||
Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.3f), OsuColour.Gray(0.6f)),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
}
|
||||
else
|
||||
InternalChild = video = new VideoSprite(stream)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
};
|
||||
}
|
||||
|
||||
public bool Loop
|
||||
{
|
||||
set
|
||||
{
|
||||
if (video != null)
|
||||
video.Loop = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
194
osu.Game.Tournament/IPC/FileBasedIPC.cs
Normal file
194
osu.Game.Tournament/IPC/FileBasedIPC.cs
Normal file
@ -0,0 +1,194 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Win32;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Platform.Windows;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.IPC
|
||||
{
|
||||
public class FileBasedIPC : MatchIPCInfo
|
||||
{
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
protected RulesetStore Rulesets { get; private set; }
|
||||
|
||||
private int lastBeatmapId;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, GameHost host)
|
||||
{
|
||||
StableStorage stable;
|
||||
|
||||
try
|
||||
{
|
||||
stable = new StableStorage(host as DesktopGameHost);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e, "Stable installation could not be found; disabling file based IPC");
|
||||
return;
|
||||
}
|
||||
|
||||
const string file_ipc_filename = "ipc.txt";
|
||||
const string file_ipc_state_filename = "ipc-state.txt";
|
||||
const string file_ipc_scores_filename = "ipc-scores.txt";
|
||||
const string file_ipc_channel_filename = "ipc-channel.txt";
|
||||
|
||||
if (stable.Exists(file_ipc_filename))
|
||||
Scheduler.AddDelayed(delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var stream = stable.GetStream(file_ipc_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
var beatmapId = int.Parse(sr.ReadLine());
|
||||
var mods = int.Parse(sr.ReadLine());
|
||||
|
||||
if (lastBeatmapId != beatmapId)
|
||||
{
|
||||
lastBeatmapId = beatmapId;
|
||||
|
||||
var existing = ladder.CurrentMatch.Value?.Round.Value?.Beatmaps.FirstOrDefault(b => b.ID == beatmapId && b.BeatmapInfo != null);
|
||||
|
||||
if (existing != null)
|
||||
Beatmap.Value = existing.BeatmapInfo;
|
||||
else
|
||||
{
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId });
|
||||
req.Success += b => Beatmap.Value = b.ToBeatmap(Rulesets);
|
||||
API.Queue(req);
|
||||
}
|
||||
}
|
||||
|
||||
Mods.Value = (LegacyMods)mods;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// file might be in use.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var stream = stable.GetStream(file_ipc_channel_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
ChatChannel.Value = sr.ReadLine();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// file might be in use.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var stream = stable.GetStream(file_ipc_state_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
State.Value = (TourneyState)Enum.Parse(typeof(TourneyState), sr.ReadLine());
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// file might be in use.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var stream = stable.GetStream(file_ipc_scores_filename))
|
||||
using (var sr = new StreamReader(stream))
|
||||
{
|
||||
Score1.Value = int.Parse(sr.ReadLine());
|
||||
Score2.Value = int.Parse(sr.ReadLine());
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// file might be in use.
|
||||
}
|
||||
}, 250, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A method of accessing an osu-stable install in a controlled fashion.
|
||||
/// </summary>
|
||||
private class StableStorage : WindowsStorage
|
||||
{
|
||||
protected override string LocateBasePath()
|
||||
{
|
||||
bool checkExists(string p)
|
||||
{
|
||||
return File.Exists(Path.Combine(p, "ipc.txt"));
|
||||
}
|
||||
|
||||
string stableInstallPath = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
stableInstallPath = "G:\\My Drive\\Main\\osu!tourney";
|
||||
|
||||
if (checkExists(stableInstallPath))
|
||||
return stableInstallPath;
|
||||
|
||||
stableInstallPath = "G:\\My Drive\\Main\\osu!mappool";
|
||||
|
||||
if (checkExists(stableInstallPath))
|
||||
return stableInstallPath;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", "");
|
||||
|
||||
if (checkExists(stableInstallPath))
|
||||
return stableInstallPath;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
||||
if (checkExists(stableInstallPath))
|
||||
return stableInstallPath;
|
||||
|
||||
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu");
|
||||
if (checkExists(stableInstallPath))
|
||||
return stableInstallPath;
|
||||
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Logger.Log($"Stable path for tourney usage: {stableInstallPath}");
|
||||
}
|
||||
}
|
||||
|
||||
public StableStorage(DesktopGameHost host)
|
||||
: base(string.Empty, host)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
osu.Game.Tournament/IPC/MatchIPCInfo.cs
Normal file
20
osu.Game.Tournament/IPC/MatchIPCInfo.cs
Normal file
@ -0,0 +1,20 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
|
||||
namespace osu.Game.Tournament.IPC
|
||||
{
|
||||
public class MatchIPCInfo : Component
|
||||
{
|
||||
public Bindable<BeatmapInfo> Beatmap { get; } = new Bindable<BeatmapInfo>();
|
||||
public Bindable<LegacyMods> Mods { get; } = new Bindable<LegacyMods>();
|
||||
public Bindable<TourneyState> State { get; } = new Bindable<TourneyState>();
|
||||
public Bindable<string> ChatChannel { get; } = new Bindable<string>();
|
||||
public BindableInt Score1 { get; } = new BindableInt();
|
||||
public BindableInt Score2 { get; } = new BindableInt();
|
||||
}
|
||||
}
|
14
osu.Game.Tournament/IPC/TourneyState.cs
Normal file
14
osu.Game.Tournament/IPC/TourneyState.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Tournament.IPC
|
||||
{
|
||||
public enum TourneyState
|
||||
{
|
||||
Initialising,
|
||||
Idle,
|
||||
WaitingForClients,
|
||||
Playing,
|
||||
Ranking
|
||||
}
|
||||
}
|
38
osu.Game.Tournament/Models/BeatmapChoice.cs
Normal file
38
osu.Game.Tournament/Models/BeatmapChoice.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// 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 Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A beatmap choice by a team from a tournament's map pool.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class BeatmapChoice
|
||||
{
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||
public TeamColour Team;
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||
public ChoiceType Type;
|
||||
|
||||
public int BeatmapID;
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum TeamColour
|
||||
{
|
||||
Red,
|
||||
Blue
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum ChoiceType
|
||||
{
|
||||
Pick,
|
||||
Ban,
|
||||
}
|
||||
}
|
12
osu.Game.Tournament/Models/LadderEditorInfo.cs
Normal file
12
osu.Game.Tournament/Models/LadderEditorInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// 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.Bindables;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
public class LadderEditorInfo
|
||||
{
|
||||
public readonly Bindable<TournamentMatch> Selected = new Bindable<TournamentMatch>();
|
||||
}
|
||||
}
|
27
osu.Game.Tournament/Models/LadderInfo.cs
Normal file
27
osu.Game.Tournament/Models/LadderInfo.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the complete data required to operate the tournament system.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class LadderInfo
|
||||
{
|
||||
public BindableList<TournamentMatch> Matches = new BindableList<TournamentMatch>();
|
||||
public BindableList<TournamentRound> Rounds = new BindableList<TournamentRound>();
|
||||
public BindableList<TournamentTeam> Teams = new BindableList<TournamentTeam>();
|
||||
|
||||
// only used for serialisation
|
||||
public List<TournamentProgression> Progressions = new List<TournamentProgression>();
|
||||
|
||||
[JsonIgnore]
|
||||
public Bindable<TournamentMatch> CurrentMatch = new Bindable<TournamentMatch>();
|
||||
}
|
||||
}
|
15
osu.Game.Tournament/Models/RoundBeatmap.cs
Normal file
15
osu.Game.Tournament/Models/RoundBeatmap.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// 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.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
public class RoundBeatmap
|
||||
{
|
||||
public int ID;
|
||||
public string Mods;
|
||||
|
||||
public BeatmapInfo BeatmapInfo;
|
||||
}
|
||||
}
|
125
osu.Game.Tournament/Models/TournamentMatch.cs
Normal file
125
osu.Game.Tournament/Models/TournamentMatch.cs
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
using SixLabors.Primitives;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of two teams competing in a head-to-head match.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TournamentMatch
|
||||
{
|
||||
public int ID;
|
||||
|
||||
public List<string> Acronyms
|
||||
{
|
||||
get
|
||||
{
|
||||
List<string> acronyms = new List<string>();
|
||||
if (Team1Acronym != null) acronyms.Add(Team1Acronym);
|
||||
if (Team2Acronym != null) acronyms.Add(Team2Acronym);
|
||||
return acronyms;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TournamentTeam> Team1 = new Bindable<TournamentTeam>();
|
||||
|
||||
public string Team1Acronym;
|
||||
|
||||
public readonly Bindable<int?> Team1Score = new Bindable<int?>();
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TournamentTeam> Team2 = new Bindable<TournamentTeam>();
|
||||
|
||||
public string Team2Acronym;
|
||||
|
||||
public readonly Bindable<int?> Team2Score = new Bindable<int?>();
|
||||
|
||||
public readonly Bindable<bool> Completed = new Bindable<bool>();
|
||||
|
||||
public readonly Bindable<bool> Losers = new Bindable<bool>();
|
||||
|
||||
public readonly ObservableCollection<BeatmapChoice> PicksBans = new ObservableCollection<BeatmapChoice>();
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TournamentRound> Round = new Bindable<TournamentRound>();
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TournamentMatch> Progression = new Bindable<TournamentMatch>();
|
||||
|
||||
[JsonIgnore]
|
||||
public readonly Bindable<TournamentMatch> LosersProgression = new Bindable<TournamentMatch>();
|
||||
|
||||
/// <summary>
|
||||
/// Should not be set directly. Use LadderInfo.CurrentMatch.Value = this instead.
|
||||
/// </summary>
|
||||
public readonly Bindable<bool> Current = new Bindable<bool>();
|
||||
|
||||
public readonly Bindable<DateTimeOffset> Date = new Bindable<DateTimeOffset>(DateTimeOffset.Now);
|
||||
|
||||
[JsonProperty]
|
||||
public readonly BindableList<ConditionalTournamentMatch> ConditionalMatches = new BindableList<ConditionalTournamentMatch>();
|
||||
|
||||
public readonly Bindable<Point> Position = new Bindable<Point>();
|
||||
|
||||
public TournamentMatch()
|
||||
{
|
||||
Team1.BindValueChanged(t => Team1Acronym = t.NewValue?.Acronym.Value, true);
|
||||
Team2.BindValueChanged(t => Team2Acronym = t.NewValue?.Acronym.Value, true);
|
||||
}
|
||||
|
||||
public TournamentMatch(TournamentTeam team1 = null, TournamentTeam team2 = null)
|
||||
: this()
|
||||
{
|
||||
Team1.Value = team1;
|
||||
Team2.Value = team2;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public TournamentTeam Winner => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value;
|
||||
|
||||
[JsonIgnore]
|
||||
public TournamentTeam Loser => !Completed.Value ? null : Team1Score.Value > Team2Score.Value ? Team2.Value : Team1.Value;
|
||||
|
||||
public int PointsToWin => Round.Value?.BestOf.Value / 2 + 1 ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Remove scores from the match, in case of a false click or false start.
|
||||
/// </summary>
|
||||
public void CancelMatchStart()
|
||||
{
|
||||
Team1Score.Value = null;
|
||||
Team2Score.Value = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialise this match with zeroed scores. Will be a noop if either team is not present.
|
||||
/// </summary>
|
||||
public void StartMatch()
|
||||
{
|
||||
if (Team1.Value == null || Team2.Value == null)
|
||||
return;
|
||||
|
||||
Team1Score.Value = 0;
|
||||
Team2Score.Value = 0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
CancelMatchStart();
|
||||
Team1.Value = null;
|
||||
Team2.Value = null;
|
||||
Completed.Value = false;
|
||||
PicksBans.Clear();
|
||||
}
|
||||
}
|
||||
}
|
27
osu.Game.Tournament/Models/TournamentProgression.cs
Normal file
27
osu.Game.Tournament/Models/TournamentProgression.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A mapping between two <see cref="TournamentMatch"/>es.
|
||||
/// Used for serialisation exclusively.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TournamentProgression
|
||||
{
|
||||
public int SourceID;
|
||||
public int TargetID;
|
||||
|
||||
public bool Losers;
|
||||
|
||||
public TournamentProgression(int sourceID, int targetID, bool losers = false)
|
||||
{
|
||||
SourceID = sourceID;
|
||||
TargetID = targetID;
|
||||
Losers = losers;
|
||||
}
|
||||
}
|
||||
}
|
32
osu.Game.Tournament/Models/TournamentRound.cs
Normal file
32
osu.Game.Tournament/Models/TournamentRound.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A tournament round, containing many matches, generally executed in a short time period.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TournamentRound
|
||||
{
|
||||
public readonly Bindable<string> Name = new Bindable<string>();
|
||||
public readonly Bindable<string> Description = new Bindable<string>();
|
||||
|
||||
public readonly BindableInt BestOf = new BindableInt(9) { Default = 9, MinValue = 3, MaxValue = 23 };
|
||||
|
||||
[JsonProperty]
|
||||
public readonly BindableList<RoundBeatmap> Beatmaps = new BindableList<RoundBeatmap>();
|
||||
|
||||
public readonly Bindable<DateTimeOffset> StartDate = new Bindable<DateTimeOffset> { Value = DateTimeOffset.UtcNow };
|
||||
|
||||
// only used for serialisation
|
||||
public List<int> Matches = new List<int>();
|
||||
|
||||
public override string ToString() => Name.Value ?? "None";
|
||||
}
|
||||
}
|
54
osu.Game.Tournament/Models/TournamentTeam.cs
Normal file
54
osu.Game.Tournament/Models/TournamentTeam.cs
Normal file
@ -0,0 +1,54 @@
|
||||
// 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 Newtonsoft.Json;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A team representation. For official tournaments this is generally a country.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TournamentTeam
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this team.
|
||||
/// </summary>
|
||||
public Bindable<string> FullName = new Bindable<string>(string.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Name of the file containing the flag.
|
||||
/// </summary>
|
||||
public Bindable<string> FlagName = new Bindable<string>(string.Empty);
|
||||
|
||||
/// <summary>
|
||||
/// Short acronym which appears in the group boxes post-selection.
|
||||
/// </summary>
|
||||
public Bindable<string> Acronym = new Bindable<string>(string.Empty);
|
||||
|
||||
[JsonProperty]
|
||||
public BindableList<User> Players { get; set; } = new BindableList<User>();
|
||||
|
||||
public TournamentTeam()
|
||||
{
|
||||
Acronym.ValueChanged += val =>
|
||||
{
|
||||
// use a sane default flag name based on acronym.
|
||||
if (val.OldValue.StartsWith(FlagName.Value, StringComparison.InvariantCultureIgnoreCase))
|
||||
FlagName.Value = val.NewValue.Length >= 2 ? val.NewValue?.Substring(0, 2).ToUpper() : string.Empty;
|
||||
};
|
||||
|
||||
FullName.ValueChanged += val =>
|
||||
{
|
||||
// use a sane acronym based on full name.
|
||||
if (val.OldValue.StartsWith(Acronym.Value, StringComparison.InvariantCultureIgnoreCase))
|
||||
Acronym.Value = val.NewValue.Length >= 3 ? val.NewValue?.Substring(0, 3).ToUpper() : string.Empty;
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString() => FullName.Value ?? Acronym.Value;
|
||||
}
|
||||
}
|
11
osu.Game.Tournament/Properties/AssemblyInfo.cs
Normal file
11
osu.Game.Tournament/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// We publish our internal attributes to other sub-projects of the framework.
|
||||
// Note, that we omit visual tests as they are meant to test the framework
|
||||
// behavior "in the wild".
|
||||
|
||||
[assembly: InternalsVisibleTo("osu.Game.Tournament.Tests")]
|
||||
[assembly: InternalsVisibleTo("osu.Game.Tournament.Tests.Dynamic")]
|
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin
Normal file
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png
Normal file
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin
Normal file
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png
Normal file
BIN
osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
1252
osu.Game.Tournament/Resources/countries.json
Normal file
1252
osu.Game.Tournament/Resources/countries.json
Normal file
File diff suppressed because it is too large
Load Diff
45
osu.Game.Tournament/Screens/BeatmapInfoScreen.cs
Normal file
45
osu.Game.Tournament/Screens/BeatmapInfoScreen.cs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.IPC;
|
||||
|
||||
namespace osu.Game.Tournament.Screens
|
||||
{
|
||||
public abstract class BeatmapInfoScreen : TournamentScreen
|
||||
{
|
||||
protected readonly SongBar SongBar;
|
||||
|
||||
protected BeatmapInfoScreen()
|
||||
{
|
||||
AddInternal(SongBar = new SongBar
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(MatchIPCInfo ipc)
|
||||
{
|
||||
ipc.Beatmap.BindValueChanged(beatmapChanged, true);
|
||||
ipc.Mods.BindValueChanged(modsChanged, true);
|
||||
}
|
||||
|
||||
private void modsChanged(ValueChangedEvent<LegacyMods> mods)
|
||||
{
|
||||
SongBar.Mods = mods.NewValue;
|
||||
}
|
||||
|
||||
private void beatmapChanged(ValueChangedEvent<BeatmapInfo> beatmap)
|
||||
{
|
||||
SongBar.FadeInFromZero(300, Easing.OutQuint);
|
||||
SongBar.Beatmap = beatmap.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Game.Screens.Tournament.Components
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class DrawingsConfigManager : IniConfigManager<DrawingsConfig>
|
||||
{
|
@ -4,19 +4,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
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.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Tournament
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class Group : Container
|
||||
{
|
||||
@ -73,7 +71,7 @@ namespace osu.Game.Screens.Tournament
|
||||
};
|
||||
}
|
||||
|
||||
public void AddTeam(DrawingsTeam team)
|
||||
public void AddTeam(TournamentTeam team)
|
||||
{
|
||||
GroupTeam gt = new GroupTeam(team);
|
||||
|
||||
@ -88,10 +86,10 @@ namespace osu.Game.Screens.Tournament
|
||||
|
||||
public bool ContainsTeam(string fullName)
|
||||
{
|
||||
return allTeams.Any(t => t.Team.FullName == fullName);
|
||||
return allTeams.Any(t => t.Team.FullName.Value == fullName);
|
||||
}
|
||||
|
||||
public bool RemoveTeam(DrawingsTeam team)
|
||||
public bool RemoveTeam(TournamentTeam team)
|
||||
{
|
||||
allTeams.RemoveAll(gt => gt.Team == team);
|
||||
|
||||
@ -116,25 +114,29 @@ namespace osu.Game.Screens.Tournament
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (GroupTeam gt in allTeams)
|
||||
sb.AppendLine(gt.Team.FullName);
|
||||
sb.AppendLine(gt.Team.FullName.Value);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private class GroupTeam : Container
|
||||
private class GroupTeam : DrawableTournamentTeam
|
||||
{
|
||||
public readonly DrawingsTeam Team;
|
||||
|
||||
private readonly FillFlowContainer innerContainer;
|
||||
private readonly Sprite flagSprite;
|
||||
|
||||
public GroupTeam(DrawingsTeam team)
|
||||
public GroupTeam(TournamentTeam team)
|
||||
: base(team)
|
||||
{
|
||||
Team = team;
|
||||
|
||||
Width = 36;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Children = new Drawable[]
|
||||
Flag.Anchor = Anchor.TopCentre;
|
||||
Flag.Origin = Anchor.TopCentre;
|
||||
|
||||
AcronymText.Anchor = Anchor.TopCentre;
|
||||
AcronymText.Origin = Anchor.TopCentre;
|
||||
AcronymText.Text = team.Acronym.Value.ToUpperInvariant();
|
||||
AcronymText.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
innerContainer = new FillFlowContainer
|
||||
{
|
||||
@ -149,21 +151,8 @@ namespace osu.Game.Screens.Tournament
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
flagSprite = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
FillMode = FillMode.Fit
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
||||
Text = team.Acronym.ToUpperInvariant(),
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10),
|
||||
}
|
||||
Flag,
|
||||
AcronymText
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -175,12 +164,6 @@ namespace osu.Game.Screens.Tournament
|
||||
innerContainer.ScaleTo(1.5f);
|
||||
innerContainer.ScaleTo(1f, 200);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,10 +7,10 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
|
||||
namespace osu.Game.Screens.Tournament
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class GroupContainer : Container
|
||||
{
|
||||
@ -64,7 +64,7 @@ namespace osu.Game.Screens.Tournament
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTeam(DrawingsTeam team)
|
||||
public void AddTeam(TournamentTeam team)
|
||||
{
|
||||
if (groups[currentGroup].TeamsCount == maxTeams)
|
||||
return;
|
@ -2,11 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Screens.Tournament.Teams
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public interface ITeamList
|
||||
{
|
||||
IEnumerable<DrawingsTeam> Teams { get; }
|
||||
IEnumerable<TournamentTeam> Teams { get; }
|
||||
}
|
||||
}
|
@ -5,26 +5,25 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Screens.Tournament.Teams;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Tournament
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class ScrollingTeamContainer : Container
|
||||
{
|
||||
public event Action OnScrollStarted;
|
||||
public event Action<DrawingsTeam> OnSelected;
|
||||
public event Action<TournamentTeam> OnSelected;
|
||||
|
||||
private readonly List<DrawingsTeam> availableTeams = new List<DrawingsTeam>();
|
||||
private readonly List<TournamentTeam> availableTeams = new List<TournamentTeam>();
|
||||
|
||||
private readonly Container tracker;
|
||||
|
||||
@ -55,6 +54,7 @@ namespace osu.Game.Screens.Tournament
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.33f),
|
||||
|
||||
Masking = true,
|
||||
CornerRadius = 10f,
|
||||
@ -170,7 +170,7 @@ namespace osu.Game.Screens.Tournament
|
||||
}
|
||||
}
|
||||
|
||||
public void AddTeam(DrawingsTeam team)
|
||||
public void AddTeam(TournamentTeam team)
|
||||
{
|
||||
if (availableTeams.Contains(team))
|
||||
return;
|
||||
@ -181,12 +181,12 @@ namespace osu.Game.Screens.Tournament
|
||||
scrollState = ScrollState.Idle;
|
||||
}
|
||||
|
||||
public void AddTeams(IEnumerable<DrawingsTeam> teams)
|
||||
public void AddTeams(IEnumerable<TournamentTeam> teams)
|
||||
{
|
||||
if (teams == null)
|
||||
return;
|
||||
|
||||
foreach (DrawingsTeam t in teams)
|
||||
foreach (TournamentTeam t in teams)
|
||||
AddTeam(t);
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ namespace osu.Game.Screens.Tournament
|
||||
scrollState = ScrollState.Idle;
|
||||
}
|
||||
|
||||
public void RemoveTeam(DrawingsTeam team)
|
||||
public void RemoveTeam(TournamentTeam team)
|
||||
{
|
||||
availableTeams.Remove(team);
|
||||
|
||||
@ -282,7 +282,7 @@ namespace osu.Game.Screens.Tournament
|
||||
|
||||
private void addFlags()
|
||||
{
|
||||
foreach (DrawingsTeam t in availableTeams)
|
||||
foreach (TournamentTeam t in availableTeams)
|
||||
{
|
||||
Add(new ScrollingTeam(t)
|
||||
{
|
||||
@ -319,14 +319,11 @@ namespace osu.Game.Screens.Tournament
|
||||
Scrolling
|
||||
}
|
||||
|
||||
public class ScrollingTeam : Container
|
||||
public class ScrollingTeam : DrawableTournamentTeam
|
||||
{
|
||||
public const float WIDTH = 58;
|
||||
public const float HEIGHT = 41;
|
||||
|
||||
public DrawingsTeam Team;
|
||||
|
||||
private readonly Sprite flagSprite;
|
||||
private readonly Box outline;
|
||||
|
||||
private bool selected;
|
||||
@ -346,10 +343,9 @@ namespace osu.Game.Screens.Tournament
|
||||
}
|
||||
}
|
||||
|
||||
public ScrollingTeam(DrawingsTeam team)
|
||||
public ScrollingTeam(TournamentTeam team)
|
||||
: base(team)
|
||||
{
|
||||
Team = team;
|
||||
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.CentreLeft;
|
||||
|
||||
@ -359,28 +355,21 @@ namespace osu.Game.Screens.Tournament
|
||||
|
||||
Alpha = 0;
|
||||
|
||||
Children = new Drawable[]
|
||||
Flag.Anchor = Anchor.Centre;
|
||||
Flag.Origin = Anchor.Centre;
|
||||
Flag.Scale = new Vector2(0.9f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
outline = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.33f),
|
||||
Alpha = 0
|
||||
},
|
||||
flagSprite = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
Size = new Vector2(WIDTH, HEIGHT) - new Vector2(8)
|
||||
}
|
||||
Flag
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,8 +6,9 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Screens.Tournament.Teams
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class StorageBackedTeamList : ITeamList
|
||||
{
|
||||
@ -20,11 +21,11 @@ namespace osu.Game.Screens.Tournament.Teams
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
public IEnumerable<DrawingsTeam> Teams
|
||||
public IEnumerable<TournamentTeam> Teams
|
||||
{
|
||||
get
|
||||
{
|
||||
var teams = new List<DrawingsTeam>();
|
||||
var teams = new List<TournamentTeam>();
|
||||
|
||||
try
|
||||
{
|
||||
@ -47,17 +48,11 @@ namespace osu.Game.Screens.Tournament.Teams
|
||||
continue;
|
||||
}
|
||||
|
||||
string flagName = split[0].Trim();
|
||||
string teamName = split[1].Trim();
|
||||
|
||||
string acronym = split.Length >= 3 ? split[2].Trim() : teamName;
|
||||
acronym = acronym.Substring(0, Math.Min(3, acronym.Length));
|
||||
|
||||
teams.Add(new DrawingsTeam
|
||||
teams.Add(new TournamentTeam
|
||||
{
|
||||
FlagName = flagName,
|
||||
FullName = teamName,
|
||||
Acronym = acronym
|
||||
FullName = { Value = split[1].Trim(), },
|
||||
Acronym = { Value = split.Length >= 3 ? split[2].Trim() : null, },
|
||||
FlagName = { Value = split[0].Trim() }
|
||||
});
|
||||
}
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.MathUtils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Screens.Tournament.Components
|
||||
namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
{
|
||||
public class VisualiserContainer : Container
|
||||
{
|
265
osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs
Normal file
265
osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs
Normal file
@ -0,0 +1,265 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Drawings.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Drawings
|
||||
{
|
||||
public class DrawingsScreen : CompositeDrawable
|
||||
{
|
||||
private const string results_filename = "drawings_results.txt";
|
||||
|
||||
private ScrollingTeamContainer teamsContainer;
|
||||
private GroupContainer groupsContainer;
|
||||
private OsuSpriteText fullTeamNameText;
|
||||
|
||||
private readonly List<TournamentTeam> allTeams = new List<TournamentTeam>();
|
||||
|
||||
private DrawingsConfigManager drawingsConfig;
|
||||
|
||||
private Task writeOp;
|
||||
|
||||
private Storage storage;
|
||||
|
||||
public ITeamList TeamList;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, Storage storage)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
this.storage = storage;
|
||||
|
||||
if (TeamList == null)
|
||||
TeamList = new StorageBackedTeamList(storage);
|
||||
|
||||
if (!TeamList.Teams.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
drawingsConfig = new DrawingsConfigManager(storage);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
// Main container
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fill,
|
||||
Texture = textures.Get(@"Backgrounds/Drawings/background.png")
|
||||
},
|
||||
// Visualiser
|
||||
new VisualiserContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Size = new Vector2(1, 10),
|
||||
|
||||
Colour = new Color4(255, 204, 34, 255),
|
||||
|
||||
Lines = 6
|
||||
},
|
||||
// Groups
|
||||
groupsContainer = new GroupContainer(drawingsConfig.Get<int>(DrawingsConfig.Groups), drawingsConfig.Get<int>(DrawingsConfig.TeamsPerGroup))
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = 35f,
|
||||
Bottom = 35f
|
||||
}
|
||||
},
|
||||
// Scrolling teams
|
||||
teamsContainer = new ScrollingTeamContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
// Scrolling team name
|
||||
fullTeamNameText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
||||
Position = new Vector2(0, 45f),
|
||||
|
||||
Colour = OsuColour.Gray(0.33f),
|
||||
|
||||
Alpha = 0,
|
||||
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42),
|
||||
}
|
||||
}
|
||||
},
|
||||
// Control panel container
|
||||
new ControlPanel
|
||||
{
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
|
||||
Text = "Begin random",
|
||||
Action = teamsContainer.StartScrolling,
|
||||
},
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
|
||||
Text = "Stop random",
|
||||
Action = teamsContainer.StopScrolling,
|
||||
},
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
|
||||
Text = "Reload",
|
||||
Action = reloadTeams
|
||||
},
|
||||
new ControlPanel.Spacer(),
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
|
||||
Text = "Reset",
|
||||
Action = () => reset()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
teamsContainer.OnSelected += onTeamSelected;
|
||||
teamsContainer.OnScrollStarted += () => fullTeamNameText.FadeOut(200);
|
||||
|
||||
reset(true);
|
||||
}
|
||||
|
||||
private void onTeamSelected(TournamentTeam team)
|
||||
{
|
||||
groupsContainer.AddTeam(team);
|
||||
|
||||
fullTeamNameText.Text = team.FullName.Value;
|
||||
fullTeamNameText.FadeIn(200);
|
||||
|
||||
writeResults(groupsContainer.GetStringRepresentation());
|
||||
}
|
||||
|
||||
private void writeResults(string text)
|
||||
{
|
||||
void writeAction()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Write to drawings_results
|
||||
using (Stream stream = storage.GetStream(results_filename, FileAccess.Write, FileMode.Create))
|
||||
using (StreamWriter sw = new StreamWriter(stream))
|
||||
{
|
||||
sw.Write(text);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex, "Failed to write results.");
|
||||
}
|
||||
}
|
||||
|
||||
writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run((Action)writeAction);
|
||||
}
|
||||
|
||||
private void reloadTeams()
|
||||
{
|
||||
teamsContainer.ClearTeams();
|
||||
allTeams.Clear();
|
||||
|
||||
foreach (TournamentTeam t in TeamList.Teams)
|
||||
{
|
||||
if (groupsContainer.ContainsTeam(t.FullName.Value))
|
||||
continue;
|
||||
|
||||
allTeams.Add(t);
|
||||
teamsContainer.AddTeam(t);
|
||||
}
|
||||
}
|
||||
|
||||
private void reset(bool loadLastResults = false)
|
||||
{
|
||||
groupsContainer.ClearTeams();
|
||||
|
||||
reloadTeams();
|
||||
|
||||
if (!storage.Exists(results_filename))
|
||||
return;
|
||||
|
||||
if (loadLastResults)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Read from drawings_results
|
||||
using (Stream stream = storage.GetStream(results_filename, FileAccess.Read, FileMode.Open))
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
{
|
||||
string line;
|
||||
|
||||
while ((line = sr.ReadLine()?.Trim()) != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
if (line.ToUpperInvariant().StartsWith("GROUP"))
|
||||
continue;
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
TournamentTeam teamToAdd = allTeams.FirstOrDefault(t => t.FullName.Value == line);
|
||||
|
||||
if (teamToAdd == null)
|
||||
continue;
|
||||
|
||||
groupsContainer.AddTeam(teamToAdd);
|
||||
teamsContainer.RemoveTeam(teamToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex, "Failed to read last drawings results.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeResults(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
osu.Game.Tournament/Screens/Editors/IModelBacked.cs
Normal file
17
osu.Game.Tournament/Screens/Editors/IModelBacked.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a mechanism to access a related model from a representing class.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of model.</typeparam>
|
||||
public interface IModelBacked<out TModel>
|
||||
{
|
||||
/// <summary>
|
||||
/// The model.
|
||||
/// </summary>
|
||||
TModel Model { get; }
|
||||
}
|
||||
}
|
152
osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs
Normal file
152
osu.Game.Tournament/Screens/Editors/LadderEditorScreen.cs
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Ladder;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using SixLabors.Primitives;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
[Cached]
|
||||
public class LadderEditorScreen : LadderScreen, IHasContextMenu
|
||||
{
|
||||
[Cached]
|
||||
private LadderEditorInfo editorInfo = new LadderEditorInfo();
|
||||
|
||||
protected override bool DrawLoserPaths => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Content.Add(new LadderEditorSettings
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Margin = new MarginPadding(5)
|
||||
});
|
||||
}
|
||||
|
||||
public void BeginJoin(TournamentMatch match, bool losers)
|
||||
{
|
||||
ScrollContent.Add(new JoinVisualiser(MatchesContainer, match, losers, UpdateLayout));
|
||||
}
|
||||
|
||||
public MenuItem[] ContextMenuItems
|
||||
{
|
||||
get
|
||||
{
|
||||
if (editorInfo == null)
|
||||
return new MenuItem[0];
|
||||
|
||||
return new MenuItem[]
|
||||
{
|
||||
new OsuMenuItem("Create new match", MenuItemType.Highlighted, () =>
|
||||
{
|
||||
var pos = MatchesContainer.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position);
|
||||
LadderInfo.Matches.Add(new TournamentMatch { Position = { Value = new Point((int)pos.X, (int)pos.Y) } });
|
||||
}),
|
||||
new OsuMenuItem("Reset teams", MenuItemType.Destructive, () =>
|
||||
{
|
||||
foreach (var p in MatchesContainer)
|
||||
p.Match.Reset();
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(TournamentMatch match)
|
||||
{
|
||||
MatchesContainer.FirstOrDefault(p => p.Match == match)?.Remove();
|
||||
}
|
||||
|
||||
private class JoinVisualiser : CompositeDrawable
|
||||
{
|
||||
private readonly Container<DrawableTournamentMatch> matchesContainer;
|
||||
public readonly TournamentMatch Source;
|
||||
private readonly bool losers;
|
||||
private readonly Action complete;
|
||||
|
||||
private ProgressionPath path;
|
||||
|
||||
public JoinVisualiser(Container<DrawableTournamentMatch> matchesContainer, TournamentMatch source, bool losers, Action complete)
|
||||
{
|
||||
this.matchesContainer = matchesContainer;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Source = source;
|
||||
this.losers = losers;
|
||||
this.complete = complete;
|
||||
if (losers)
|
||||
Source.LosersProgression.Value = null;
|
||||
else
|
||||
Source.Progression.Value = null;
|
||||
}
|
||||
|
||||
private DrawableTournamentMatch findTarget(InputState state)
|
||||
{
|
||||
return matchesContainer.FirstOrDefault(d => d.ReceivePositionalInputAt(state.Mouse.Position));
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
var found = findTarget(e.CurrentState);
|
||||
|
||||
if (found == path?.Destination)
|
||||
return false;
|
||||
|
||||
path?.Expire();
|
||||
path = null;
|
||||
|
||||
if (found == null)
|
||||
return false;
|
||||
|
||||
AddInternal(path = new ProgressionPath(matchesContainer.First(c => c.Match == Source), found)
|
||||
{
|
||||
Colour = Color4.Yellow,
|
||||
});
|
||||
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
var found = findTarget(e.CurrentState);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
if (found.Match != Source)
|
||||
{
|
||||
if (losers)
|
||||
Source.LosersProgression.Value = found.Match;
|
||||
else
|
||||
Source.Progression.Value = found.Match;
|
||||
}
|
||||
|
||||
complete?.Invoke();
|
||||
Expire();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
282
osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs
Normal file
282
osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs
Normal file
@ -0,0 +1,282 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
public class RoundEditorScreen : TournamentEditorScreen<RoundEditorScreen.RoundRow, TournamentRound>
|
||||
{
|
||||
protected override BindableList<TournamentRound> Storage => LadderInfo.Rounds;
|
||||
|
||||
public class RoundRow : CompositeDrawable, IModelBacked<TournamentRound>
|
||||
{
|
||||
public TournamentRound Model { get; }
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
public RoundRow(TournamentRound round)
|
||||
{
|
||||
Model = round;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 10;
|
||||
|
||||
RoundBeatmapEditor beatmapEditor = new RoundBeatmapEditor(round)
|
||||
{
|
||||
Width = 0.95f
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.1f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Padding = new MarginPadding { Right = 160 },
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Name",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.Name
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Description",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.Description
|
||||
},
|
||||
new DateTextBox
|
||||
{
|
||||
LabelText = "Start Time",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.StartDate
|
||||
},
|
||||
new SettingsSlider<int>
|
||||
{
|
||||
LabelText = "Best of",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.BestOf
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Width = 0.2f,
|
||||
Margin = new MarginPadding(10),
|
||||
Text = "Add beatmap",
|
||||
Action = () => beatmapEditor.CreateNew()
|
||||
},
|
||||
beatmapEditor
|
||||
}
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 150,
|
||||
Text = "Delete Round",
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
ladderInfo.Rounds.Remove(Model);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
public class RoundBeatmapEditor : CompositeDrawable
|
||||
{
|
||||
private readonly TournamentRound round;
|
||||
private readonly FillFlowContainer flow;
|
||||
|
||||
public RoundBeatmapEditor(TournamentRound round)
|
||||
{
|
||||
this.round = round;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChild = flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
ChildrenEnumerable = round.Beatmaps.Select(p => new RoundBeatmapRow(round, p))
|
||||
};
|
||||
}
|
||||
|
||||
public void CreateNew()
|
||||
{
|
||||
var user = new RoundBeatmap();
|
||||
round.Beatmaps.Add(user);
|
||||
flow.Add(new RoundBeatmapRow(round, user));
|
||||
}
|
||||
|
||||
public class RoundBeatmapRow : CompositeDrawable
|
||||
{
|
||||
public RoundBeatmap Model { get; }
|
||||
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
private readonly Bindable<string> beatmapId = new Bindable<string>();
|
||||
|
||||
private readonly Bindable<string> mods = new Bindable<string>();
|
||||
|
||||
private readonly Container drawableContainer;
|
||||
|
||||
public RoundBeatmapRow(TournamentRound team, RoundBeatmap beatmap)
|
||||
{
|
||||
Model = beatmap;
|
||||
|
||||
Margin = new MarginPadding(10);
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.2f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Padding = new MarginPadding { Right = 160 },
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsNumberBox
|
||||
{
|
||||
LabelText = "Beatmap ID",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = beatmapId,
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Mods",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = mods,
|
||||
},
|
||||
drawableContainer = new Container
|
||||
{
|
||||
Size = new Vector2(100, 70),
|
||||
},
|
||||
}
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 150,
|
||||
Text = "Delete Beatmap",
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
team.Beatmaps.Remove(beatmap);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
beatmapId.Value = Model.ID.ToString();
|
||||
beatmapId.BindValueChanged(idString =>
|
||||
{
|
||||
int parsed;
|
||||
|
||||
int.TryParse(idString.NewValue, out parsed);
|
||||
|
||||
Model.ID = parsed;
|
||||
|
||||
if (idString.NewValue != idString.OldValue)
|
||||
Model.BeatmapInfo = null;
|
||||
|
||||
if (Model.BeatmapInfo != null)
|
||||
{
|
||||
updatePanel();
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID });
|
||||
|
||||
req.Success += res =>
|
||||
{
|
||||
Model.BeatmapInfo = res.ToBeatmap(rulesets);
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
req.Failure += _ =>
|
||||
{
|
||||
Model.BeatmapInfo = null;
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
API.Queue(req);
|
||||
}, true);
|
||||
|
||||
mods.Value = Model.Mods;
|
||||
mods.BindValueChanged(modString => Model.Mods = modString.NewValue);
|
||||
}
|
||||
|
||||
private void updatePanel()
|
||||
{
|
||||
drawableContainer.Clear();
|
||||
|
||||
if (Model.BeatmapInfo != null)
|
||||
drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Width = 300
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override RoundRow CreateDrawable(TournamentRound model) => new RoundRow(model);
|
||||
}
|
||||
}
|
314
osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
Normal file
314
osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
Normal file
@ -0,0 +1,314 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
public class TeamEditorScreen : TournamentEditorScreen<TeamEditorScreen.TeamRow, TournamentTeam>
|
||||
{
|
||||
[Resolved]
|
||||
private Framework.Game game { get; set; }
|
||||
|
||||
protected override BindableList<TournamentTeam> Storage => LadderInfo.Teams;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ControlPanel.Add(new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Add all countries",
|
||||
Action = addAllCountries
|
||||
});
|
||||
}
|
||||
|
||||
protected override TeamRow CreateDrawable(TournamentTeam model) => new TeamRow(model);
|
||||
|
||||
private void addAllCountries()
|
||||
{
|
||||
List<TournamentTeam> countries;
|
||||
using (Stream stream = game.Resources.GetStream("Resources/countries.json"))
|
||||
using (var sr = new StreamReader(stream))
|
||||
countries = JsonConvert.DeserializeObject<List<TournamentTeam>>(sr.ReadToEnd());
|
||||
|
||||
foreach (var c in countries)
|
||||
Storage.Add(c);
|
||||
}
|
||||
|
||||
public class TeamRow : CompositeDrawable, IModelBacked<TournamentTeam>
|
||||
{
|
||||
public TournamentTeam Model { get; }
|
||||
|
||||
private readonly Container drawableContainer;
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
public TeamRow(TournamentTeam team)
|
||||
{
|
||||
Model = team;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 10;
|
||||
|
||||
PlayerEditor playerEditor = new PlayerEditor(Model)
|
||||
{
|
||||
Width = 0.95f
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.1f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
drawableContainer = new Container
|
||||
{
|
||||
Size = new Vector2(100, 50),
|
||||
Margin = new MarginPadding(10),
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Name",
|
||||
Width = 0.2f,
|
||||
Bindable = Model.FullName
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Acronym",
|
||||
Width = 0.2f,
|
||||
Bindable = Model.Acronym
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Flag",
|
||||
Width = 0.2f,
|
||||
Bindable = Model.FlagName
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Width = 0.11f,
|
||||
Margin = new MarginPadding(10),
|
||||
Text = "Add player",
|
||||
Action = () => playerEditor.CreateNew()
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Width = 0.11f,
|
||||
Text = "Delete Team",
|
||||
Margin = new MarginPadding(10),
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
ladderInfo.Teams.Remove(Model);
|
||||
},
|
||||
},
|
||||
playerEditor
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Model.FlagName.BindValueChanged(updateDrawable, true);
|
||||
}
|
||||
|
||||
private void updateDrawable(ValueChangedEvent<string> flag)
|
||||
{
|
||||
drawableContainer.Child = new DrawableTeamFlag(Model);
|
||||
}
|
||||
|
||||
private class DrawableTeamFlag : DrawableTournamentTeam
|
||||
{
|
||||
public DrawableTeamFlag(TournamentTeam team)
|
||||
: base(team)
|
||||
{
|
||||
InternalChild = Flag;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Flag.Anchor = Anchor.Centre;
|
||||
Flag.Origin = Anchor.Centre;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerEditor : CompositeDrawable
|
||||
{
|
||||
private readonly TournamentTeam team;
|
||||
private readonly FillFlowContainer flow;
|
||||
|
||||
public PlayerEditor(TournamentTeam team)
|
||||
{
|
||||
this.team = team;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChild = flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
ChildrenEnumerable = team.Players.Select(p => new PlayerRow(team, p))
|
||||
};
|
||||
}
|
||||
|
||||
public void CreateNew()
|
||||
{
|
||||
var user = new User();
|
||||
team.Players.Add(user);
|
||||
flow.Add(new PlayerRow(team, user));
|
||||
}
|
||||
|
||||
public class PlayerRow : CompositeDrawable
|
||||
{
|
||||
private readonly User user;
|
||||
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
private readonly Bindable<string> userId = new Bindable<string>();
|
||||
|
||||
private readonly Container drawableContainer;
|
||||
|
||||
public PlayerRow(TournamentTeam team, User user)
|
||||
{
|
||||
this.user = user;
|
||||
|
||||
Margin = new MarginPadding(10);
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.2f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Padding = new MarginPadding { Right = 160 },
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsNumberBox
|
||||
{
|
||||
LabelText = "User ID",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = userId,
|
||||
},
|
||||
drawableContainer = new Container
|
||||
{
|
||||
Size = new Vector2(100, 70),
|
||||
},
|
||||
}
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 150,
|
||||
Text = "Delete Player",
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
team.Players.Remove(user);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
userId.Value = user.Id.ToString();
|
||||
userId.BindValueChanged(idString =>
|
||||
{
|
||||
long parsed;
|
||||
|
||||
long.TryParse(idString.NewValue, out parsed);
|
||||
|
||||
user.Id = parsed;
|
||||
|
||||
if (idString.NewValue != idString.OldValue)
|
||||
user.Username = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(user.Username))
|
||||
{
|
||||
updatePanel();
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new GetUserRequest(user.Id);
|
||||
|
||||
req.Success += res =>
|
||||
{
|
||||
// TODO: this should be done in a better way.
|
||||
user.Username = res.Username;
|
||||
user.Country = res.Country;
|
||||
user.Cover = res.Cover;
|
||||
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
req.Failure += _ =>
|
||||
{
|
||||
user.Id = 1;
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
API.Queue(req);
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updatePanel()
|
||||
{
|
||||
drawableContainer.Child = new UserPanel(user) { Width = 300 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user