mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 07:42:57 +08:00
Merge branch 'master' into fix-chat-test-scene
This commit is contained in:
commit
67246eddd4
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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" />
|
||||
|
@ -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"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
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 SettingsTextBox
|
||||
{
|
||||
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 SettingsTextBox
|
||||
{
|
||||
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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
// 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.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
public abstract class TournamentEditorScreen<TDrawable, TModel> : TournamentScreen, IProvideVideo
|
||||
where TDrawable : Drawable, IModelBacked<TModel>
|
||||
where TModel : class, new()
|
||||
{
|
||||
protected abstract BindableList<TModel> Storage { get; }
|
||||
|
||||
private FillFlowContainer<TDrawable> flow;
|
||||
|
||||
protected ControlPanel ControlPanel;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.2f),
|
||||
},
|
||||
new OsuScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.9f,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Child = flow = new FillFlowContainer<TDrawable>
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
Spacing = new Vector2(20)
|
||||
},
|
||||
},
|
||||
ControlPanel = new ControlPanel
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Add new",
|
||||
Action = () => Storage.Add(new TModel())
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Clear all",
|
||||
Action = Storage.Clear
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Storage.ItemsAdded += items => items.ForEach(i => flow.Add(CreateDrawable(i)));
|
||||
Storage.ItemsRemoved += items => items.ForEach(i => flow.RemoveAll(d => d.Model == i));
|
||||
|
||||
foreach (var model in Storage)
|
||||
flow.Add(CreateDrawable(model));
|
||||
}
|
||||
|
||||
protected abstract TDrawable CreateDrawable(TModel model);
|
||||
}
|
||||
}
|
228
osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs
Normal file
228
osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs
Normal file
@ -0,0 +1,228 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
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.Showcase;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
{
|
||||
public class MatchHeader : Container
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 95;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TournamentLogo(),
|
||||
new RoundDisplay
|
||||
{
|
||||
Y = 10,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
},
|
||||
new TeamScoreDisplay(TeamColour.Red)
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
},
|
||||
new TeamScoreDisplay(TeamColour.Blue)
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private class TeamScoreDisplay : CompositeDrawable
|
||||
{
|
||||
private readonly TeamColour teamColour;
|
||||
|
||||
private readonly Color4 red = new Color4(129, 68, 65, 255);
|
||||
private readonly Color4 blue = new Color4(41, 91, 97, 255);
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private readonly Bindable<TournamentTeam> currentTeam = new Bindable<TournamentTeam>();
|
||||
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
|
||||
|
||||
public TeamScoreDisplay(TeamColour teamColour)
|
||||
{
|
||||
this.teamColour = teamColour;
|
||||
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = 300;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder)
|
||||
{
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
currentTeamScore.UnbindBindings();
|
||||
currentTeamScore.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1Score : match.NewValue.Team2Score);
|
||||
|
||||
currentTeam.UnbindBindings();
|
||||
currentTeam.BindTo(teamColour == TeamColour.Red ? match.NewValue.Team1 : match.NewValue.Team2);
|
||||
|
||||
// team may change to same team, which means score is not in a good state.
|
||||
// thus we handle this manually.
|
||||
teamChanged(currentTeam.Value);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
switch (e.Button)
|
||||
{
|
||||
case MouseButton.Left:
|
||||
if (currentTeamScore.Value < currentMatch.Value.PointsToWin)
|
||||
currentTeamScore.Value++;
|
||||
return true;
|
||||
|
||||
case MouseButton.Right:
|
||||
if (currentTeamScore.Value > 0)
|
||||
currentTeamScore.Value--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
private void teamChanged(TournamentTeam team)
|
||||
{
|
||||
var colour = teamColour == TeamColour.Red ? red : blue;
|
||||
var flip = teamColour != TeamColour.Red;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TeamDisplay(team, colour, flip),
|
||||
new TeamScore(currentTeamScore, flip, currentMatch.Value.PointsToWin)
|
||||
{
|
||||
Colour = colour
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamScore : CompositeDrawable
|
||||
{
|
||||
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
|
||||
private readonly StarCounter counter;
|
||||
|
||||
public TeamScore(Bindable<int?> score, bool flip, int count)
|
||||
{
|
||||
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
|
||||
|
||||
Anchor = anchor;
|
||||
Origin = anchor;
|
||||
|
||||
InternalChild = counter = new StarCounter(count)
|
||||
{
|
||||
Anchor = anchor,
|
||||
X = (flip ? -1 : 1) * 90,
|
||||
Y = 5,
|
||||
Scale = flip ? new Vector2(-1, 1) : Vector2.One,
|
||||
};
|
||||
|
||||
currentTeamScore.BindValueChanged(scoreChanged);
|
||||
currentTeamScore.BindTo(score);
|
||||
}
|
||||
|
||||
private void scoreChanged(ValueChangedEvent<int?> score) => counter.CountStars = score.NewValue ?? 0;
|
||||
}
|
||||
|
||||
private class TeamDisplay : DrawableTournamentTeam
|
||||
{
|
||||
public TeamDisplay(TournamentTeam team, Color4 colour, bool flip)
|
||||
: base(team)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
var anchor = flip ? Anchor.CentreRight : Anchor.CentreLeft;
|
||||
|
||||
Anchor = Origin = anchor;
|
||||
|
||||
Flag.Anchor = Flag.Origin = anchor;
|
||||
Flag.RelativeSizeAxes = Axes.None;
|
||||
Flag.Size = new Vector2(60, 40);
|
||||
Flag.Margin = new MarginPadding(20);
|
||||
|
||||
InternalChild = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Flag,
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = team?.FullName.Value.ToUpper() ?? "???",
|
||||
X = (flip ? -1 : 1) * 90,
|
||||
Y = -10,
|
||||
Colour = colour,
|
||||
Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 20),
|
||||
Origin = anchor,
|
||||
Anchor = anchor,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class RoundDisplay : CompositeDrawable
|
||||
{
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
public RoundDisplay()
|
||||
{
|
||||
CornerRadius = 10;
|
||||
Masking = true;
|
||||
Width = 200;
|
||||
Height = 20;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder)
|
||||
{
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = new Color4(47, 71, 67, 255),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Colour = Color4.White,
|
||||
Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round",
|
||||
Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 18),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
{
|
||||
public class MatchScoreDisplay : CompositeDrawable
|
||||
{
|
||||
private readonly Color4 red = new Color4(186, 0, 18, 255);
|
||||
private readonly Color4 blue = new Color4(17, 136, 170, 255);
|
||||
|
||||
private const float bar_height = 20;
|
||||
|
||||
private readonly BindableInt score1 = new BindableInt();
|
||||
private readonly BindableInt score2 = new BindableInt();
|
||||
|
||||
private readonly MatchScoreCounter score1Text;
|
||||
private readonly MatchScoreCounter score2Text;
|
||||
|
||||
private readonly Circle score1Bar;
|
||||
private readonly Circle score2Bar;
|
||||
|
||||
public MatchScoreDisplay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
score1Bar = new Circle
|
||||
{
|
||||
Name = "top bar red",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height,
|
||||
Width = 0,
|
||||
Colour = red,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
score1Text = new MatchScoreCounter
|
||||
{
|
||||
Colour = red,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
score2Bar = new Circle
|
||||
{
|
||||
Name = "top bar blue",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height,
|
||||
Width = 0,
|
||||
Colour = blue,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopLeft
|
||||
},
|
||||
score2Text = new MatchScoreCounter
|
||||
{
|
||||
Colour = blue,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, MatchIPCInfo ipc)
|
||||
{
|
||||
score1.BindValueChanged(_ => updateScores());
|
||||
score1.BindTo(ipc.Score1);
|
||||
|
||||
score2.BindValueChanged(_ => updateScores());
|
||||
score2.BindTo(ipc.Score2);
|
||||
}
|
||||
|
||||
private void updateScores()
|
||||
{
|
||||
score1Text.Current.Value = score1.Value;
|
||||
score2Text.Current.Value = score2.Value;
|
||||
|
||||
var winningText = score1.Value > score2.Value ? score1Text : score2Text;
|
||||
var losingText = score1.Value <= score2.Value ? score1Text : score2Text;
|
||||
|
||||
winningText.Winning = true;
|
||||
losingText.Winning = false;
|
||||
|
||||
var winningBar = score1.Value > score2.Value ? score1Bar : score2Bar;
|
||||
var losingBar = score1.Value <= score2.Value ? score1Bar : score2Bar;
|
||||
|
||||
var diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value);
|
||||
|
||||
losingBar.ResizeWidthTo(0, 400, Easing.OutQuint);
|
||||
winningBar.ResizeWidthTo(Math.Min(0.4f, (float)Math.Pow(diff / 1500000f, 0.5) / 2), 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth);
|
||||
score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth);
|
||||
}
|
||||
|
||||
private class MatchScoreCounter : ScoreCounter
|
||||
{
|
||||
public MatchScoreCounter()
|
||||
{
|
||||
Margin = new MarginPadding { Top = bar_height + 5, Horizontal = 10 };
|
||||
|
||||
Winning = false;
|
||||
}
|
||||
|
||||
public bool Winning
|
||||
{
|
||||
set => DisplayedCountSpriteText.Font = value
|
||||
? TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 60)
|
||||
: TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Light, size: 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
211
osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs
Normal file
211
osu.Game.Tournament/Screens/Gameplay/GameplayScreen.cs
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Gameplay.Components;
|
||||
using osu.Game.Tournament.Screens.MapPool;
|
||||
using osu.Game.Tournament.Screens.TeamWin;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Gameplay
|
||||
{
|
||||
public class GameplayScreen : BeatmapInfoScreen
|
||||
{
|
||||
private readonly BindableBool warmup = new BindableBool();
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
public readonly Bindable<TourneyState> State = new Bindable<TourneyState>();
|
||||
private OsuButton warmupButton;
|
||||
private MatchIPCInfo ipc;
|
||||
|
||||
private readonly Color4 red = new Color4(186, 0, 18, 255);
|
||||
private readonly Color4 blue = new Color4(17, 136, 170, 255);
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private TournamentSceneManager sceneManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private TournamentMatchChatDisplay chat { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, MatchIPCInfo ipc)
|
||||
{
|
||||
this.ipc = ipc;
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new MatchHeader(),
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Y = 5,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
// chroma key area for stable gameplay
|
||||
Name = "chroma",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 512,
|
||||
Colour = new Color4(0, 255, 0, 255),
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Y = -4,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Circle
|
||||
{
|
||||
Name = "top bar red",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 8,
|
||||
Width = 0.5f,
|
||||
Colour = red,
|
||||
},
|
||||
new Circle
|
||||
{
|
||||
Name = "top bar blue",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 8,
|
||||
Width = 0.5f,
|
||||
Colour = blue,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
scoreDisplay = new MatchScoreDisplay
|
||||
{
|
||||
Y = -60,
|
||||
Scale = new Vector2(0.8f),
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
},
|
||||
new ControlPanel
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
warmupButton = new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Toggle warmup",
|
||||
Action = () => warmup.Toggle()
|
||||
},
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Toggle chat",
|
||||
Action = () => { State.Value = State.Value == TourneyState.Idle ? TourneyState.Playing : TourneyState.Idle; }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
State.BindTo(ipc.State);
|
||||
State.BindValueChanged(stateChanged, true);
|
||||
|
||||
currentMatch.BindValueChanged(m =>
|
||||
{
|
||||
warmup.Value = m.NewValue.Team1Score.Value + m.NewValue.Team2Score.Value == 0;
|
||||
scheduledOperation?.Cancel();
|
||||
});
|
||||
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
|
||||
warmup.BindValueChanged(w => warmupButton.Alpha = !w.NewValue ? 0.5f : 1, true);
|
||||
}
|
||||
|
||||
private ScheduledDelegate scheduledOperation;
|
||||
private MatchScoreDisplay scoreDisplay;
|
||||
|
||||
private TourneyState lastState;
|
||||
|
||||
private void stateChanged(ValueChangedEvent<TourneyState> state)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (state.NewValue == TourneyState.Ranking)
|
||||
{
|
||||
if (warmup.Value) return;
|
||||
|
||||
if (ipc.Score1.Value > ipc.Score2.Value)
|
||||
currentMatch.Value.Team1Score.Value++;
|
||||
else
|
||||
currentMatch.Value.Team2Score.Value++;
|
||||
}
|
||||
|
||||
scheduledOperation?.Cancel();
|
||||
|
||||
void expand()
|
||||
{
|
||||
chat?.Expand();
|
||||
|
||||
using (BeginDelayedSequence(300, true))
|
||||
{
|
||||
scoreDisplay.FadeIn(100);
|
||||
SongBar.Expanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
void contract()
|
||||
{
|
||||
SongBar.Expanded = false;
|
||||
scoreDisplay.FadeOut(100);
|
||||
using (chat?.BeginDelayedSequence(500))
|
||||
chat?.Contract();
|
||||
}
|
||||
|
||||
switch (state.NewValue)
|
||||
{
|
||||
case TourneyState.Idle:
|
||||
contract();
|
||||
|
||||
const float delay_before_progression = 4000;
|
||||
|
||||
// if we've returned to idle and the last screen was ranking
|
||||
// we should automatically proceed after a short delay
|
||||
if (lastState == TourneyState.Ranking && !warmup.Value)
|
||||
{
|
||||
if (currentMatch.Value?.Completed.Value == true)
|
||||
scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(TeamWinScreen)); }, delay_before_progression);
|
||||
else if (currentMatch.Value?.Completed.Value == false)
|
||||
scheduledOperation = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(MapPoolScreen)); }, delay_before_progression);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TourneyState.Ranking:
|
||||
scheduledOperation = Scheduler.AddDelayed(contract, 10000);
|
||||
break;
|
||||
|
||||
default:
|
||||
chat.Expand();
|
||||
expand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
lastState = state.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
osu.Game.Tournament/Screens/IProvideVideo.cs
Normal file
12
osu.Game.Tournament/Screens/IProvideVideo.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.
|
||||
|
||||
namespace osu.Game.Tournament.Screens
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for a screen which provides its own local video background.
|
||||
/// </summary>
|
||||
public interface IProvideVideo
|
||||
{
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A match that may not necessarily occur.
|
||||
/// </summary>
|
||||
public class ConditionalTournamentMatch : TournamentMatch
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
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.Editors;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class DrawableMatchTeam : DrawableTournamentTeam, IHasContextMenu
|
||||
{
|
||||
private readonly TournamentMatch match;
|
||||
private readonly bool losers;
|
||||
private OsuSpriteText scoreText;
|
||||
private Box background;
|
||||
|
||||
private readonly Bindable<int?> score = new Bindable<int?>();
|
||||
private readonly BindableBool completed = new BindableBool();
|
||||
|
||||
private Color4 colourWinner;
|
||||
private Color4 colourNormal;
|
||||
|
||||
private readonly Func<bool> isWinner;
|
||||
private LadderEditorScreen ladderEditor;
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
private void setCurrent()
|
||||
{
|
||||
//todo: tournamentgamebase?
|
||||
if (ladderInfo.CurrentMatch.Value != null)
|
||||
ladderInfo.CurrentMatch.Value.Current.Value = false;
|
||||
|
||||
ladderInfo.CurrentMatch.Value = match;
|
||||
ladderInfo.CurrentMatch.Value.Current.Value = true;
|
||||
}
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private LadderEditorInfo editorInfo { get; set; }
|
||||
|
||||
public DrawableMatchTeam(TournamentTeam team, TournamentMatch match, bool losers)
|
||||
: base(team)
|
||||
{
|
||||
this.match = match;
|
||||
this.losers = losers;
|
||||
Size = new Vector2(150, 40);
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
Flag.Scale = new Vector2(0.9f);
|
||||
Flag.Anchor = Flag.Origin = Anchor.CentreLeft;
|
||||
|
||||
AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft;
|
||||
AcronymText.Padding = new MarginPadding { Left = 50 };
|
||||
AcronymText.Font = OsuFont.GetFont(size: 24);
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
isWinner = () => match.Winner == Team;
|
||||
|
||||
completed.BindTo(match.Completed);
|
||||
if (team != null)
|
||||
score.BindTo(team == match.Team1.Value ? match.Team1Score : match.Team2Score);
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuColour colours, LadderEditorScreen ladderEditor)
|
||||
{
|
||||
this.ladderEditor = ladderEditor;
|
||||
|
||||
colourWinner = losers ? colours.YellowDarker : colours.BlueDarker;
|
||||
colourNormal = OsuColour.Gray(0.2f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Padding = new MarginPadding(5),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
AcronymText,
|
||||
Flag,
|
||||
new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = 5,
|
||||
Width = 0.3f,
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.1f),
|
||||
Alpha = 0.8f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
scoreText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.GetFont(size: 20),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
completed.BindValueChanged(_ => updateWinStyle());
|
||||
|
||||
score.BindValueChanged(val =>
|
||||
{
|
||||
scoreText.Text = val.NewValue?.ToString() ?? string.Empty;
|
||||
updateWinStyle();
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (Team == null || editorInfo != null) return false;
|
||||
|
||||
if (!match.Current.Value)
|
||||
{
|
||||
setCurrent();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e.Button == MouseButton.Left)
|
||||
{
|
||||
if (score.Value == null)
|
||||
{
|
||||
match.StartMatch();
|
||||
}
|
||||
else if (!match.Completed.Value)
|
||||
score.Value++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (match.Progression.Value?.Completed.Value == true)
|
||||
// don't allow changing scores if the match has a progression. can cause large data loss
|
||||
return false;
|
||||
|
||||
if (match.Completed.Value && match.Winner != Team)
|
||||
// don't allow changing scores from the non-winner
|
||||
return false;
|
||||
|
||||
if (score.Value > 0)
|
||||
score.Value--;
|
||||
else
|
||||
match.CancelMatchStart();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateWinStyle()
|
||||
{
|
||||
bool winner = completed.Value && isWinner?.Invoke() == true;
|
||||
|
||||
background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint);
|
||||
|
||||
scoreText.Font = AcronymText.Font = OsuFont.GetFont(weight: winner ? FontWeight.Bold : FontWeight.Regular);
|
||||
}
|
||||
|
||||
public MenuItem[] ContextMenuItems
|
||||
{
|
||||
get
|
||||
{
|
||||
if (editorInfo == null)
|
||||
return new MenuItem[0];
|
||||
|
||||
return new MenuItem[]
|
||||
{
|
||||
new OsuMenuItem("Set as current", MenuItemType.Standard, setCurrent),
|
||||
new OsuMenuItem("Join with", MenuItemType.Standard, () => ladderEditor.BeginJoin(match, false)),
|
||||
new OsuMenuItem("Join with (loser)", MenuItemType.Standard, () => ladderEditor.BeginJoin(match, true)),
|
||||
new OsuMenuItem("Remove", MenuItemType.Destructive, () => ladderEditor.Remove(match)),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
// 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.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
using SixLabors.Primitives;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class DrawableTournamentMatch : CompositeDrawable
|
||||
{
|
||||
public readonly TournamentMatch Match;
|
||||
private readonly bool editor;
|
||||
protected readonly FillFlowContainer<DrawableMatchTeam> Flow;
|
||||
private readonly Drawable selectionBox;
|
||||
private readonly Drawable currentMatchSelectionBox;
|
||||
private Bindable<TournamentMatch> globalSelection;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private LadderEditorInfo editorInfo { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
public DrawableTournamentMatch(TournamentMatch match, bool editor = false)
|
||||
{
|
||||
Match = match;
|
||||
this.editor = editor;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Margin = new MarginPadding(5);
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
selectionBox = new Container
|
||||
{
|
||||
CornerRadius = 5,
|
||||
Masking = true,
|
||||
Scale = new Vector2(1.05f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
Colour = Color4.YellowGreen,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
currentMatchSelectionBox = new Container
|
||||
{
|
||||
CornerRadius = 5,
|
||||
Masking = true,
|
||||
Scale = new Vector2(1.05f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
Colour = Color4.OrangeRed,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
Flow = new FillFlowContainer<DrawableMatchTeam>
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(2)
|
||||
}
|
||||
};
|
||||
|
||||
boundReference(match.Team1).BindValueChanged(_ => updateTeams());
|
||||
boundReference(match.Team2).BindValueChanged(_ => updateTeams());
|
||||
boundReference(match.Team1Score).BindValueChanged(_ => updateWinConditions());
|
||||
boundReference(match.Team2Score).BindValueChanged(_ => updateWinConditions());
|
||||
boundReference(match.Round).BindValueChanged(_ =>
|
||||
{
|
||||
updateWinConditions();
|
||||
Changed?.Invoke();
|
||||
});
|
||||
boundReference(match.Completed).BindValueChanged(_ => updateProgression());
|
||||
boundReference(match.Progression).BindValueChanged(_ => updateProgression());
|
||||
boundReference(match.LosersProgression).BindValueChanged(_ => updateProgression());
|
||||
boundReference(match.Losers).BindValueChanged(_ =>
|
||||
{
|
||||
updateTeams();
|
||||
Changed?.Invoke();
|
||||
});
|
||||
boundReference(match.Current).BindValueChanged(_ => updateCurrentMatch(), true);
|
||||
boundReference(match.Position).BindValueChanged(pos =>
|
||||
{
|
||||
if (!IsDragged)
|
||||
Position = new Vector2(pos.NewValue.X, pos.NewValue.Y);
|
||||
Changed?.Invoke();
|
||||
}, true);
|
||||
|
||||
updateTeams();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when somethign changed that requires a ladder redraw.
|
||||
/// </summary>
|
||||
public Action Changed;
|
||||
|
||||
private readonly List<IUnbindable> refBindables = new List<IUnbindable>();
|
||||
|
||||
private T boundReference<T>(T obj)
|
||||
where T : IBindable
|
||||
{
|
||||
obj = (T)obj.GetBoundCopy();
|
||||
refBindables.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
foreach (var b in refBindables)
|
||||
b.UnbindAll();
|
||||
}
|
||||
|
||||
private void updateCurrentMatch()
|
||||
{
|
||||
if (Match.Current.Value)
|
||||
currentMatchSelectionBox.Show();
|
||||
else
|
||||
currentMatchSelectionBox.Hide();
|
||||
}
|
||||
|
||||
private bool selected;
|
||||
|
||||
public bool Selected
|
||||
{
|
||||
get => selected;
|
||||
|
||||
set
|
||||
{
|
||||
if (value == selected) return;
|
||||
|
||||
selected = value;
|
||||
|
||||
if (selected)
|
||||
{
|
||||
selectionBox.Show();
|
||||
if (editor)
|
||||
editorInfo.Selected.Value = Match;
|
||||
else
|
||||
ladderInfo.CurrentMatch.Value = Match;
|
||||
}
|
||||
else
|
||||
selectionBox.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProgression()
|
||||
{
|
||||
if (!Match.Completed.Value)
|
||||
{
|
||||
// ensure we clear any of our teams from our progression.
|
||||
// this is not pretty logic but should suffice for now.
|
||||
if (Match.Progression.Value != null && Match.Progression.Value.Team1.Value == Match.Team1.Value)
|
||||
Match.Progression.Value.Team1.Value = null;
|
||||
|
||||
if (Match.Progression.Value != null && Match.Progression.Value.Team2.Value == Match.Team2.Value)
|
||||
Match.Progression.Value.Team2.Value = null;
|
||||
|
||||
if (Match.LosersProgression.Value != null && Match.LosersProgression.Value.Team1.Value == Match.Team1.Value)
|
||||
Match.LosersProgression.Value.Team1.Value = null;
|
||||
|
||||
if (Match.LosersProgression.Value != null && Match.LosersProgression.Value.Team2.Value == Match.Team2.Value)
|
||||
Match.LosersProgression.Value.Team2.Value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
transferProgression(Match.Progression?.Value, Match.Winner);
|
||||
transferProgression(Match.LosersProgression?.Value, Match.Loser);
|
||||
}
|
||||
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
private void transferProgression(TournamentMatch destination, TournamentTeam team)
|
||||
{
|
||||
if (destination == null) return;
|
||||
|
||||
bool progressionAbove = destination.ID < Match.ID;
|
||||
|
||||
Bindable<TournamentTeam> destinationTeam;
|
||||
|
||||
// check for the case where we have already transferred out value
|
||||
if (destination.Team1.Value == team)
|
||||
destinationTeam = destination.Team1;
|
||||
else if (destination.Team2.Value == team)
|
||||
destinationTeam = destination.Team2;
|
||||
else
|
||||
{
|
||||
destinationTeam = progressionAbove ? destination.Team2 : destination.Team1;
|
||||
if (destinationTeam.Value != null)
|
||||
destinationTeam = progressionAbove ? destination.Team1 : destination.Team2;
|
||||
}
|
||||
|
||||
destinationTeam.Value = team;
|
||||
}
|
||||
|
||||
private void updateWinConditions()
|
||||
{
|
||||
if (Match.Round.Value == null) return;
|
||||
|
||||
var instaWinAmount = Match.Round.Value.BestOf.Value / 2;
|
||||
|
||||
Match.Completed.Value = Match.Round.Value.BestOf.Value > 0
|
||||
&& (Match.Team1Score.Value + Match.Team2Score.Value >= Match.Round.Value.BestOf.Value || Match.Team1Score.Value > instaWinAmount || Match.Team2Score.Value > instaWinAmount);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateTeams();
|
||||
|
||||
if (editorInfo != null)
|
||||
{
|
||||
globalSelection = editorInfo.Selected.GetBoundCopy();
|
||||
globalSelection.BindValueChanged(s =>
|
||||
{
|
||||
if (s.NewValue != Match) Selected = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTeams()
|
||||
{
|
||||
if (LoadState != LoadState.Loaded)
|
||||
return;
|
||||
|
||||
// todo: teams may need to be bindable for transitions at a later point.
|
||||
|
||||
if (Match.Team1.Value == null || Match.Team2.Value == null)
|
||||
Match.CancelMatchStart();
|
||||
|
||||
if (Match.ConditionalMatches.Count > 0)
|
||||
{
|
||||
foreach (var conditional in Match.ConditionalMatches)
|
||||
{
|
||||
var team1Match = conditional.Acronyms.Contains(Match.Team1Acronym);
|
||||
var team2Match = conditional.Acronyms.Contains(Match.Team2Acronym);
|
||||
|
||||
if (team1Match && team2Match)
|
||||
Match.Date.Value = conditional.Date.Value;
|
||||
}
|
||||
}
|
||||
|
||||
Flow.Children = new[]
|
||||
{
|
||||
new DrawableMatchTeam(Match.Team1.Value, Match, Match.Losers.Value),
|
||||
new DrawableMatchTeam(Match.Team2.Value, Match, Match.Losers.Value)
|
||||
};
|
||||
|
||||
SchedulerAfterChildren.Add(() => Scheduler.Add(updateProgression));
|
||||
updateWinConditions();
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e) => e.Button == MouseButton.Left && editorInfo != null;
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e) => editorInfo != null;
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
if (Selected && editorInfo != null && e.Key == Key.Delete)
|
||||
{
|
||||
Remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (editorInfo == null || Match is ConditionalTournamentMatch)
|
||||
return false;
|
||||
|
||||
Selected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
{
|
||||
if (base.OnDrag(e)) return true;
|
||||
|
||||
Selected = true;
|
||||
this.MoveToOffset(e.Delta);
|
||||
|
||||
var pos = Position;
|
||||
Match.Position.Value = new Point((int)pos.X, (int)pos.Y);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
Selected = false;
|
||||
Match.Progression.Value = null;
|
||||
Match.LosersProgression.Value = null;
|
||||
|
||||
ladderInfo.Matches.Remove(Match);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class DrawableTournamentRound : CompositeDrawable
|
||||
{
|
||||
[UsedImplicitly]
|
||||
private readonly Bindable<string> name;
|
||||
|
||||
[UsedImplicitly]
|
||||
private readonly Bindable<string> description;
|
||||
|
||||
public DrawableTournamentRound(TournamentRound round, bool losers = false)
|
||||
{
|
||||
OsuSpriteText textName;
|
||||
OsuSpriteText textDescription;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
textDescription = new OsuSpriteText
|
||||
{
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
},
|
||||
textName = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
name = round.Name.GetBoundCopy();
|
||||
name.BindValueChanged(n => textName.Text = ((losers ? "Losers " : "") + round.Name).ToUpper(), true);
|
||||
|
||||
description = round.Name.GetBoundCopy();
|
||||
description.BindValueChanged(n => textDescription.Text = round.Description.Value.ToUpper(), true);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class LadderEditorSettings : PlayerSettingsGroup
|
||||
{
|
||||
private const int padding = 10;
|
||||
|
||||
protected override string Title => @"ladder";
|
||||
|
||||
private SettingsDropdown<TournamentRound> roundDropdown;
|
||||
private PlayerCheckbox losersCheckbox;
|
||||
private DateTextBox dateTimeBox;
|
||||
private SettingsTeamDropdown team1Dropdown;
|
||||
private SettingsTeamDropdown team2Dropdown;
|
||||
|
||||
[Resolved]
|
||||
private LadderEditorInfo editorInfo { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
team1Dropdown = new SettingsTeamDropdown(ladderInfo.Teams) { LabelText = "Team 1" },
|
||||
team2Dropdown = new SettingsTeamDropdown(ladderInfo.Teams) { LabelText = "Team 2" },
|
||||
roundDropdown = new SettingsRoundDropdown(ladderInfo.Rounds) { LabelText = "Round" },
|
||||
losersCheckbox = new PlayerCheckbox { LabelText = "Losers Bracket" },
|
||||
dateTimeBox = new DateTextBox { LabelText = "Match Time" },
|
||||
};
|
||||
|
||||
editorInfo.Selected.ValueChanged += selection =>
|
||||
{
|
||||
roundDropdown.Bindable = selection.NewValue?.Round;
|
||||
losersCheckbox.Current = selection.NewValue?.Losers;
|
||||
dateTimeBox.Bindable = selection.NewValue?.Date;
|
||||
|
||||
team1Dropdown.Bindable = selection.NewValue?.Team1;
|
||||
team2Dropdown.Bindable = selection.NewValue?.Team2;
|
||||
};
|
||||
|
||||
roundDropdown.Bindable.ValueChanged += round =>
|
||||
{
|
||||
if (editorInfo.Selected.Value?.Date.Value < round.NewValue?.StartDate.Value)
|
||||
{
|
||||
editorInfo.Selected.Value.Date.Value = round.NewValue.StartDate.Value;
|
||||
editorInfo.Selected.TriggerChange();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
this.FadeIn();
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
private class SettingsRoundDropdown : LadderSettingsDropdown<TournamentRound>
|
||||
{
|
||||
public SettingsRoundDropdown(BindableList<TournamentRound> rounds)
|
||||
{
|
||||
Bindable = new Bindable<TournamentRound>();
|
||||
|
||||
foreach (var r in rounds.Prepend(new TournamentRound()))
|
||||
add(r);
|
||||
|
||||
rounds.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i));
|
||||
rounds.ItemsAdded += items => items.ForEach(add);
|
||||
}
|
||||
|
||||
private readonly List<IUnbindable> refBindables = new List<IUnbindable>();
|
||||
|
||||
private T boundReference<T>(T obj)
|
||||
where T : IBindable
|
||||
{
|
||||
obj = (T)obj.GetBoundCopy();
|
||||
refBindables.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void add(TournamentRound round)
|
||||
{
|
||||
Control.AddDropdownItem(round);
|
||||
boundReference(round.Name).BindValueChanged(_ =>
|
||||
{
|
||||
Control.RemoveDropdownItem(round);
|
||||
Control.AddDropdownItem(round);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsTeamDropdown : LadderSettingsDropdown<TournamentTeam>
|
||||
{
|
||||
public SettingsTeamDropdown(BindableList<TournamentTeam> teams)
|
||||
{
|
||||
foreach (var t in teams.Prepend(new TournamentTeam()))
|
||||
add(t);
|
||||
|
||||
teams.ItemsRemoved += items => items.ForEach(i => Control.RemoveDropdownItem(i));
|
||||
teams.ItemsAdded += items => items.ForEach(add);
|
||||
}
|
||||
|
||||
private readonly List<IUnbindable> refBindables = new List<IUnbindable>();
|
||||
|
||||
private T boundReference<T>(T obj)
|
||||
where T : IBindable
|
||||
{
|
||||
obj = (T)obj.GetBoundCopy();
|
||||
refBindables.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void add(TournamentTeam team)
|
||||
{
|
||||
Control.AddDropdownItem(team);
|
||||
boundReference(team.FullName).BindValueChanged(_ =>
|
||||
{
|
||||
Control.RemoveDropdownItem(team);
|
||||
Control.AddDropdownItem(team);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class LadderSettingsDropdown<T> : SettingsDropdown<T>
|
||||
{
|
||||
protected override OsuDropdown<T> CreateDropdown() => new DropdownControl();
|
||||
|
||||
private new class DropdownControl : SettingsDropdown<T>.DropdownControl
|
||||
{
|
||||
protected override DropdownMenu CreateMenu() => new Menu();
|
||||
|
||||
private new class Menu : OsuDropdownMenu
|
||||
{
|
||||
public Menu()
|
||||
{
|
||||
MaxHeight = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class ProgressionPath : Path
|
||||
{
|
||||
public DrawableTournamentMatch Source { get; private set; }
|
||||
public DrawableTournamentMatch Destination { get; private set; }
|
||||
|
||||
public ProgressionPath(DrawableTournamentMatch source, DrawableTournamentMatch destination)
|
||||
{
|
||||
Source = source;
|
||||
Destination = destination;
|
||||
|
||||
PathRadius = 3;
|
||||
BypassAutoSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Vector2 getCenteredVector(Vector2 top, Vector2 bottom) => new Vector2(top.X, top.Y + (bottom.Y - top.Y) / 2);
|
||||
|
||||
var q1 = Source.ScreenSpaceDrawQuad;
|
||||
var q2 = Destination.ScreenSpaceDrawQuad;
|
||||
|
||||
float padding = q1.Width / 20;
|
||||
|
||||
bool progressionToRight = q2.TopLeft.X > q1.TopLeft.X;
|
||||
|
||||
if (!progressionToRight)
|
||||
{
|
||||
var temp = q2;
|
||||
q2 = q1;
|
||||
q1 = temp;
|
||||
}
|
||||
|
||||
var c1 = getCenteredVector(q1.TopRight, q1.BottomRight) + new Vector2(padding, 0);
|
||||
var c2 = getCenteredVector(q2.TopLeft, q2.BottomLeft) - new Vector2(padding, 0);
|
||||
|
||||
var p1 = c1;
|
||||
var p2 = p1 + new Vector2(padding, 0);
|
||||
|
||||
if (p2.X > c2.X)
|
||||
{
|
||||
c2 = getCenteredVector(q2.TopRight, q2.BottomRight) + new Vector2(padding, 0);
|
||||
p2.X = c2.X + padding;
|
||||
}
|
||||
|
||||
var p3 = new Vector2(p2.X, c2.Y);
|
||||
var p4 = new Vector2(c2.X, p3.Y);
|
||||
|
||||
var points = new[] { p1, p2, p3, p4 };
|
||||
|
||||
float minX = points.Min(p => p.X);
|
||||
float minY = points.Min(p => p.Y);
|
||||
|
||||
var topLeft = new Vector2(minX, minY);
|
||||
|
||||
Position = Parent.ToLocalSpace(topLeft);
|
||||
Vertices = points.Select(p => Parent.ToLocalSpace(p) - Parent.ToLocalSpace(topLeft)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
43
osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs
Normal file
43
osu.Game.Tournament/Screens/Ladder/LadderDragContainer.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// 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.Primitives;
|
||||
using osu.Framework.Input.Events;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder
|
||||
{
|
||||
public class LadderDragContainer : Container
|
||||
{
|
||||
protected override bool OnDragStart(DragStartEvent e) => true;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
||||
|
||||
private Vector2 target;
|
||||
|
||||
private float scale = 1;
|
||||
|
||||
protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false;
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
{
|
||||
this.MoveTo(target += e.Delta, 1000, Easing.OutQuint);
|
||||
return true;
|
||||
}
|
||||
|
||||
private const float min_scale = 0.6f;
|
||||
private const float max_scale = 1.4f;
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e)
|
||||
{
|
||||
var newScale = MathHelper.Clamp(scale + e.ScrollDelta.Y / 15 * scale, min_scale, max_scale);
|
||||
|
||||
this.MoveTo(target = target - e.MousePosition * (newScale - scale), 2000, Easing.OutQuint);
|
||||
this.ScaleTo(scale = newScale, 2000, Easing.OutQuint);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
174
osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
Normal file
174
osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
Normal file
@ -0,0 +1,174 @@
|
||||
// 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.Caching;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder
|
||||
{
|
||||
public class LadderScreen : TournamentScreen, IProvideVideo
|
||||
{
|
||||
protected Container<DrawableTournamentMatch> MatchesContainer;
|
||||
private Container<Path> paths;
|
||||
private Container headings;
|
||||
|
||||
protected LadderDragContainer ScrollContent;
|
||||
|
||||
protected Container Content;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, Storage storage)
|
||||
{
|
||||
normalPathColour = colours.BlueDarker.Darken(2);
|
||||
losersPathColour = colours.YellowDarker.Darken(2);
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = Content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
ScrollContent = new LadderDragContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
paths = new Container<Path> { RelativeSizeAxes = Axes.Both },
|
||||
headings = new Container { RelativeSizeAxes = Axes.Both },
|
||||
MatchesContainer = new Container<DrawableTournamentMatch> { RelativeSizeAxes = Axes.Both },
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
void addMatch(TournamentMatch match) =>
|
||||
MatchesContainer.Add(new DrawableTournamentMatch(match, this is LadderEditorScreen)
|
||||
{
|
||||
Changed = () => layout.Invalidate()
|
||||
});
|
||||
|
||||
foreach (var match in LadderInfo.Matches)
|
||||
addMatch(match);
|
||||
|
||||
LadderInfo.Rounds.ItemsAdded += _ => layout.Invalidate();
|
||||
LadderInfo.Rounds.ItemsRemoved += _ => layout.Invalidate();
|
||||
|
||||
LadderInfo.Matches.ItemsAdded += matches =>
|
||||
{
|
||||
foreach (var p in matches)
|
||||
addMatch(p);
|
||||
layout.Invalidate();
|
||||
};
|
||||
|
||||
LadderInfo.Matches.ItemsRemoved += matches =>
|
||||
{
|
||||
foreach (var p in matches)
|
||||
foreach (var d in MatchesContainer.Where(d => d.Match == p))
|
||||
d.Expire();
|
||||
|
||||
layout.Invalidate();
|
||||
};
|
||||
}
|
||||
|
||||
private Cached layout = new Cached();
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!layout.IsValid)
|
||||
UpdateLayout();
|
||||
}
|
||||
|
||||
private Color4 normalPathColour;
|
||||
private Color4 losersPathColour;
|
||||
|
||||
protected virtual bool DrawLoserPaths => false;
|
||||
|
||||
protected virtual void UpdateLayout()
|
||||
{
|
||||
paths.Clear();
|
||||
headings.Clear();
|
||||
|
||||
int id = 1;
|
||||
|
||||
foreach (var match in MatchesContainer.OrderBy(d => d.Y).ThenBy(d => d.X))
|
||||
{
|
||||
match.Match.ID = id++;
|
||||
|
||||
if (match.Match.Progression.Value != null)
|
||||
{
|
||||
var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.Progression.Value);
|
||||
|
||||
if (dest == null)
|
||||
// clean up outdated progressions.
|
||||
match.Match.Progression.Value = null;
|
||||
else
|
||||
paths.Add(new ProgressionPath(match, dest) { Colour = match.Match.Losers.Value ? losersPathColour : normalPathColour });
|
||||
}
|
||||
|
||||
if (DrawLoserPaths)
|
||||
{
|
||||
if (match.Match.LosersProgression.Value != null)
|
||||
{
|
||||
var dest = MatchesContainer.FirstOrDefault(p => p.Match == match.Match.LosersProgression.Value);
|
||||
|
||||
if (dest == null)
|
||||
// clean up outdated progressions.
|
||||
match.Match.LosersProgression.Value = null;
|
||||
else
|
||||
paths.Add(new ProgressionPath(match, dest) { Colour = losersPathColour.Opacity(0.1f) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var round in LadderInfo.Rounds)
|
||||
{
|
||||
var topMatch = MatchesContainer.Where(p => !p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault();
|
||||
|
||||
if (topMatch == null) continue;
|
||||
|
||||
headings.Add(new DrawableTournamentRound(round)
|
||||
{
|
||||
Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2),
|
||||
Margin = new MarginPadding { Bottom = 10 },
|
||||
Origin = Anchor.BottomCentre,
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var round in LadderInfo.Rounds)
|
||||
{
|
||||
var topMatch = MatchesContainer.Where(p => p.Match.Losers.Value && p.Match.Round.Value == round).OrderBy(p => p.Y).FirstOrDefault();
|
||||
|
||||
if (topMatch == null) continue;
|
||||
|
||||
headings.Add(new DrawableTournamentRound(round, true)
|
||||
{
|
||||
Position = headings.ToLocalSpace((topMatch.ScreenSpaceDrawQuad.TopLeft + topMatch.ScreenSpaceDrawQuad.TopRight) / 2),
|
||||
Margin = new MarginPadding { Bottom = 10 },
|
||||
Origin = Anchor.BottomCentre,
|
||||
});
|
||||
}
|
||||
|
||||
layout.Validate();
|
||||
}
|
||||
}
|
||||
}
|
239
osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs
Normal file
239
osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs
Normal file
@ -0,0 +1,239 @@
|
||||
// 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.Input.Events;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Gameplay;
|
||||
using osu.Game.Tournament.Screens.Gameplay.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.MapPool
|
||||
{
|
||||
public class MapPoolScreen : TournamentScreen
|
||||
{
|
||||
private readonly FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>> mapFlows;
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private TournamentSceneManager sceneManager { get; set; }
|
||||
|
||||
private TeamColour pickColour;
|
||||
private ChoiceType pickType;
|
||||
|
||||
private readonly OsuButton buttonRedBan;
|
||||
private readonly OsuButton buttonBlueBan;
|
||||
private readonly OsuButton buttonRedPick;
|
||||
private readonly OsuButton buttonBluePick;
|
||||
|
||||
public MapPoolScreen()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new MatchHeader(),
|
||||
mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>>
|
||||
{
|
||||
Y = 100,
|
||||
Spacing = new Vector2(10, 20),
|
||||
Padding = new MarginPadding(50),
|
||||
Direction = FillDirection.Vertical,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new ControlPanel
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "Current Mode"
|
||||
},
|
||||
buttonRedBan = new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Red Ban",
|
||||
Action = () => setMode(TeamColour.Red, ChoiceType.Ban)
|
||||
},
|
||||
buttonBlueBan = new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Blue Ban",
|
||||
Action = () => setMode(TeamColour.Blue, ChoiceType.Ban)
|
||||
},
|
||||
buttonRedPick = new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Red Pick",
|
||||
Action = () => setMode(TeamColour.Red, ChoiceType.Pick)
|
||||
},
|
||||
buttonBluePick = new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Blue Pick",
|
||||
Action = () => setMode(TeamColour.Blue, ChoiceType.Pick)
|
||||
},
|
||||
new ControlPanel.Spacer(),
|
||||
new OsuButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Reset",
|
||||
Action = reset
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(MatchIPCInfo ipc)
|
||||
{
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(LadderInfo.CurrentMatch);
|
||||
|
||||
ipc.Beatmap.BindValueChanged(beatmapChanged);
|
||||
}
|
||||
|
||||
private void beatmapChanged(ValueChangedEvent<BeatmapInfo> beatmap)
|
||||
{
|
||||
if (currentMatch.Value == null || currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < 2)
|
||||
return;
|
||||
|
||||
// if bans have already been placed, beatmap changes result in a selection being made autoamtically
|
||||
if (beatmap.NewValue.OnlineBeatmapID != null)
|
||||
addForBeatmap(beatmap.NewValue.OnlineBeatmapID.Value);
|
||||
}
|
||||
|
||||
private void setMode(TeamColour colour, ChoiceType choiceType)
|
||||
{
|
||||
pickColour = colour;
|
||||
pickType = choiceType;
|
||||
|
||||
Color4 setColour(bool active) => active ? Color4.White : Color4.Gray;
|
||||
|
||||
buttonRedBan.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Ban);
|
||||
buttonBlueBan.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Ban);
|
||||
buttonRedPick.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Pick);
|
||||
buttonBluePick.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Pick);
|
||||
}
|
||||
|
||||
private void setNextMode()
|
||||
{
|
||||
const TeamColour roll_winner = TeamColour.Red; //todo: draw from match
|
||||
|
||||
var nextColour = (currentMatch.Value.PicksBans.LastOrDefault()?.Team ?? roll_winner) == TeamColour.Red ? TeamColour.Blue : TeamColour.Red;
|
||||
|
||||
if (pickType == ChoiceType.Ban && currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2)
|
||||
setMode(pickColour, ChoiceType.Pick);
|
||||
else
|
||||
setMode(nextColour, currentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= 2 ? ChoiceType.Pick : ChoiceType.Ban);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
{
|
||||
var maps = mapFlows.Select(f => f.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)));
|
||||
var map = maps.FirstOrDefault(m => m != null);
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
if (e.Button == MouseButton.Left && map.Beatmap.OnlineBeatmapID != null)
|
||||
addForBeatmap(map.Beatmap.OnlineBeatmapID.Value);
|
||||
else
|
||||
{
|
||||
var existing = currentMatch.Value.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap.OnlineBeatmapID);
|
||||
|
||||
if (existing != null)
|
||||
{
|
||||
currentMatch.Value.PicksBans.Remove(existing);
|
||||
setNextMode();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnMouseDown(e);
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
currentMatch.Value.PicksBans.Clear();
|
||||
setNextMode();
|
||||
}
|
||||
|
||||
private ScheduledDelegate scheduledChange;
|
||||
|
||||
private void addForBeatmap(int beatmapId)
|
||||
{
|
||||
if (currentMatch.Value == null)
|
||||
return;
|
||||
|
||||
if (currentMatch.Value.Round.Value.Beatmaps.All(b => b.BeatmapInfo.OnlineBeatmapID != beatmapId))
|
||||
// don't attempt to add if the beatmap isn't in our pool
|
||||
return;
|
||||
|
||||
if (currentMatch.Value.PicksBans.Any(p => p.BeatmapID == beatmapId))
|
||||
// don't attempt to add if already exists.
|
||||
return;
|
||||
|
||||
currentMatch.Value.PicksBans.Add(new BeatmapChoice
|
||||
{
|
||||
Team = pickColour,
|
||||
Type = pickType,
|
||||
BeatmapID = beatmapId
|
||||
});
|
||||
|
||||
setNextMode();
|
||||
|
||||
if (pickType == ChoiceType.Pick)
|
||||
{
|
||||
scheduledChange?.Cancel();
|
||||
scheduledChange = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(GameplayScreen)); }, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
mapFlows.Clear();
|
||||
|
||||
if (match.NewValue.Round.Value != null)
|
||||
{
|
||||
FillFlowContainer<TournamentBeatmapPanel> currentFlow = null;
|
||||
string currentMod = null;
|
||||
|
||||
foreach (var b in match.NewValue.Round.Value.Beatmaps)
|
||||
{
|
||||
if (currentFlow == null || currentMod != b.Mods)
|
||||
{
|
||||
mapFlows.Add(currentFlow = new FillFlowContainer<TournamentBeatmapPanel>
|
||||
{
|
||||
Spacing = new Vector2(10, 20),
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
});
|
||||
|
||||
currentMod = b.Mods;
|
||||
}
|
||||
|
||||
currentFlow.Add(new TournamentBeatmapPanel(b.BeatmapInfo, b.Mods)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
201
osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs
Normal file
201
osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs
Normal file
@ -0,0 +1,201 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Schedule
|
||||
{
|
||||
public class ScheduleScreen : TournamentScreen, IProvideVideo
|
||||
{
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private Container mainContainer;
|
||||
private LadderInfo ladder;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, Storage storage)
|
||||
{
|
||||
this.ladder = ladder;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
mainContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
if (match.NewValue == null)
|
||||
{
|
||||
mainContainer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
var upcoming = ladder.Matches.Where(p => !p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4);
|
||||
var conditionals = ladder
|
||||
.Matches.Where(p => !p.Completed.Value && (p.Team1.Value == null || p.Team2.Value == null) && Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4)
|
||||
.SelectMany(m => m.ConditionalMatches.Where(cp => m.Acronyms.TrueForAll(a => cp.Acronyms.Contains(a))));
|
||||
|
||||
upcoming = upcoming.Concat(conditionals);
|
||||
upcoming = upcoming.OrderBy(p => p.Date.Value).Take(12);
|
||||
|
||||
mainContainer.Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.65f,
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScheduleContainer("recent matches")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.4f,
|
||||
ChildrenEnumerable = ladder.Matches
|
||||
.Where(p => p.Completed.Value && p.Team1.Value != null && p.Team2.Value != null
|
||||
&& Math.Abs(p.Date.Value.DayOfYear - DateTimeOffset.UtcNow.DayOfYear) < 4)
|
||||
.OrderByDescending(p => p.Date.Value)
|
||||
.Take(8)
|
||||
.Select(p => new ScheduleMatch(p))
|
||||
},
|
||||
new ScheduleContainer("match overview")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.6f,
|
||||
ChildrenEnumerable = upcoming.Select(p => new ScheduleMatch(p))
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
new ScheduleContainer("current match")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.25f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 },
|
||||
Spacing = new Vector2(10, 0),
|
||||
Text = match.NewValue.Round.Value?.Name.Value,
|
||||
Colour = Color4.Black,
|
||||
Font = OsuFont.GetFont(size: 20)
|
||||
},
|
||||
new ScheduleMatch(match.NewValue, false),
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"),
|
||||
Colour = Color4.Black,
|
||||
Font = OsuFont.GetFont(size: 20)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class ScheduleMatch : DrawableTournamentMatch
|
||||
{
|
||||
public ScheduleMatch(TournamentMatch match, bool showTimestamp = true)
|
||||
: base(match)
|
||||
{
|
||||
Flow.Direction = FillDirection.Horizontal;
|
||||
|
||||
bool conditional = match is ConditionalTournamentMatch;
|
||||
|
||||
if (conditional)
|
||||
Colour = OsuColour.Gray(0.5f);
|
||||
|
||||
if (showTimestamp)
|
||||
{
|
||||
AddInternal(new DrawableDate(Match.Date.Value)
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopLeft,
|
||||
Colour = Color4.Black,
|
||||
Alpha = conditional ? 0.6f : 1,
|
||||
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
|
||||
});
|
||||
AddInternal(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Colour = Color4.Black,
|
||||
Alpha = conditional ? 0.6f : 1,
|
||||
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
|
||||
Text = match.Date.Value.ToUniversalTime().ToString("HH:mm UTC") + (conditional ? " (conditional)" : "")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ScheduleContainer : Container
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
private readonly FillFlowContainer content;
|
||||
|
||||
public ScheduleContainer(string title)
|
||||
{
|
||||
Padding = new MarginPadding { Left = 30, Top = 30 };
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
X = 30,
|
||||
Text = title,
|
||||
Colour = Color4.Black,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Font = OsuFont.GetFont(size: 30)
|
||||
},
|
||||
content = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding(40)
|
||||
},
|
||||
new Circle
|
||||
{
|
||||
Colour = new Color4(233, 187, 79, 255),
|
||||
Width = 5,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
Normal file
16
osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
Normal file
@ -0,0 +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 osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Showcase
|
||||
{
|
||||
public class ShowcaseScreen : BeatmapInfoScreen
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(new TournamentLogo());
|
||||
}
|
||||
}
|
||||
}
|
36
osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs
Normal file
36
osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Showcase
|
||||
{
|
||||
public class TournamentLogo : CompositeDrawable
|
||||
{
|
||||
public TournamentLogo()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 95;
|
||||
Margin = new MarginPadding { Vertical = 5 };
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
InternalChild = new Sprite
|
||||
{
|
||||
Texture = textures.Get("game-screen-logo"),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
FillMode = FillMode.Fit,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
221
osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs
Normal file
221
osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs
Normal file
@ -0,0 +1,221 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Showcase;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.TeamIntro
|
||||
{
|
||||
public class TeamIntroScreen : TournamentScreen, IProvideVideo
|
||||
{
|
||||
private Container mainContainer;
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(Storage storage)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TourneyVideo(storage.GetStream(@"BG Team - Both OWC.m4v"))
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
new TournamentLogo(),
|
||||
mainContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(LadderInfo.CurrentMatch);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
if (match.NewValue == null)
|
||||
{
|
||||
mainContainer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
mainContainer.Children = new Drawable[]
|
||||
{
|
||||
new TeamWithPlayers(match.NewValue.Team1.Value, true)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Height = 0.6f,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreRight
|
||||
},
|
||||
new TeamWithPlayers(match.NewValue.Team2.Value)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Height = 0.6f,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.CentreLeft
|
||||
},
|
||||
new RoundDisplay(match.NewValue)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.25f,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class RoundDisplay : CompositeDrawable
|
||||
{
|
||||
public RoundDisplay(TournamentMatch match)
|
||||
{
|
||||
var col = OsuColour.Gray(0.33f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = "COMING UP NEXT",
|
||||
Spacing = new Vector2(2, 0),
|
||||
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Black)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
|
||||
Spacing = new Vector2(10, 0),
|
||||
Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light)
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"),
|
||||
Font = OsuFont.GetFont(size: 20)
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamWithPlayers : CompositeDrawable
|
||||
{
|
||||
private readonly Color4 red = new Color4(129, 68, 65, 255);
|
||||
private readonly Color4 blue = new Color4(41, 91, 97, 255);
|
||||
|
||||
public TeamWithPlayers(TournamentTeam team, bool left = false)
|
||||
{
|
||||
FillFlowContainer players;
|
||||
var colour = left ? red : blue;
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour)
|
||||
{
|
||||
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
X = (left ? -1 : 1) * 0.36f,
|
||||
},
|
||||
players = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Padding = new MarginPadding(20),
|
||||
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
X = (left ? -1 : 1) * 0.66f,
|
||||
},
|
||||
};
|
||||
|
||||
if (team != null)
|
||||
{
|
||||
foreach (var p in team.Players)
|
||||
players.Add(new OsuSpriteText
|
||||
{
|
||||
Text = p.Username,
|
||||
Font = OsuFont.GetFont(size: 24),
|
||||
Colour = colour,
|
||||
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamDisplay : DrawableTournamentTeam
|
||||
{
|
||||
public TeamDisplay(TournamentTeam team, string teamName, Color4 colour)
|
||||
: base(team)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Flag.Anchor = Flag.Origin = Anchor.TopCentre;
|
||||
Flag.RelativeSizeAxes = Axes.None;
|
||||
Flag.Size = new Vector2(300, 200);
|
||||
Flag.Scale = new Vector2(0.4f);
|
||||
Flag.Margin = new MarginPadding { Bottom = 20 };
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Flag,
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = team?.FullName.Value.ToUpper() ?? "???",
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light),
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = teamName.ToUpper(),
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Regular),
|
||||
Colour = colour,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
225
osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
Normal file
225
osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
Normal file
@ -0,0 +1,225 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Showcase;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.TeamWin
|
||||
{
|
||||
public class TeamWinScreen : TournamentScreen, IProvideVideo
|
||||
{
|
||||
private Container mainContainer;
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private readonly Bindable<bool> currentCompleted = new Bindable<bool>();
|
||||
|
||||
private TourneyVideo blueWinVideo;
|
||||
private TourneyVideo redWinVideo;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, Storage storage)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
blueWinVideo = new TourneyVideo(storage.GetStream(@"BG Team - Win Blue.m4v"))
|
||||
{
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
redWinVideo = new TourneyVideo(storage.GetStream(@"BG Team - Win Red.m4v"))
|
||||
{
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
new TournamentLogo
|
||||
{
|
||||
Y = 40,
|
||||
},
|
||||
mainContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
|
||||
currentCompleted.BindValueChanged(_ => update());
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
currentCompleted.UnbindBindings();
|
||||
currentCompleted.BindTo(match.NewValue.Completed);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
private void update()
|
||||
{
|
||||
var match = currentMatch.Value;
|
||||
|
||||
if (match.Winner == null)
|
||||
{
|
||||
mainContainer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool redWin = match.Winner == match.Team1.Value;
|
||||
redWinVideo.Alpha = redWin ? 1 : 0;
|
||||
blueWinVideo.Alpha = redWin ? 0 : 1;
|
||||
|
||||
mainContainer.Children = new Drawable[]
|
||||
{
|
||||
new TeamWithPlayers(match.Winner, redWin)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Height = 0.6f,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
new RoundDisplay(match)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.25f,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class RoundDisplay : CompositeDrawable
|
||||
{
|
||||
public RoundDisplay(TournamentMatch match)
|
||||
{
|
||||
var col = OsuColour.Gray(0.33f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = "WINNER",
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 15, FontWeight.Regular),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 50, FontWeight.Light),
|
||||
Spacing = new Vector2(10, 0),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Colour = col,
|
||||
Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"),
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Light),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamWithPlayers : CompositeDrawable
|
||||
{
|
||||
private readonly Color4 red = new Color4(129, 68, 65, 255);
|
||||
private readonly Color4 blue = new Color4(41, 91, 97, 255);
|
||||
|
||||
public TeamWithPlayers(TournamentTeam team, bool left = false)
|
||||
{
|
||||
var colour = left ? red : blue;
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Padding = new MarginPadding(20),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private class TeamDisplay : DrawableTournamentTeam
|
||||
{
|
||||
public TeamDisplay(TournamentTeam team, string teamName, Color4 colour)
|
||||
: base(team)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Flag.Anchor = Flag.Origin = Anchor.TopCentre;
|
||||
Flag.RelativeSizeAxes = Axes.None;
|
||||
Flag.Size = new Vector2(300, 200);
|
||||
Flag.Scale = new Vector2(0.4f);
|
||||
Flag.Margin = new MarginPadding { Bottom = 20 };
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Flag,
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = team?.FullName.Value.ToUpper() ?? "???",
|
||||
Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light),
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = teamName.ToUpper(),
|
||||
Font = OsuFont.GetFont(size: 20),
|
||||
Colour = colour,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
osu.Game.Tournament/Screens/TournamentScreen.cs
Normal file
31
osu.Game.Tournament/Screens/TournamentScreen.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// 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.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Screens
|
||||
{
|
||||
public abstract class TournamentScreen : CompositeDrawable
|
||||
{
|
||||
[Resolved]
|
||||
protected LadderInfo LadderInfo { get; private set; }
|
||||
|
||||
protected TournamentScreen()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
public override void Hide()
|
||||
{
|
||||
this.FadeOut(200);
|
||||
}
|
||||
|
||||
public override void Show()
|
||||
{
|
||||
this.FadeIn(200);
|
||||
}
|
||||
}
|
||||
}
|
75
osu.Game.Tournament/TournamentFont.cs
Normal file
75
osu.Game.Tournament/TournamentFont.cs
Normal file
@ -0,0 +1,75 @@
|
||||
// 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.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament
|
||||
{
|
||||
public static class TournamentFont
|
||||
{
|
||||
/// <summary>
|
||||
/// The default font size.
|
||||
/// </summary>
|
||||
public const float DEFAULT_FONT_SIZE = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a <see cref="FontUsage"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeface">The font typeface.</param>
|
||||
/// <param name="size">The size of the text in local space. For a value of 16, a single line will have a height of 16px.</param>
|
||||
/// <param name="weight">The font weight.</param>
|
||||
/// <param name="italics">Whether the font is italic.</param>
|
||||
/// <param name="fixedWidth">Whether all characters should be spaced the same distance apart.</param>
|
||||
/// <returns>The <see cref="FontUsage"/>.</returns>
|
||||
public static FontUsage GetFont(TournamentTypeface typeface = TournamentTypeface.Aquatico, float size = DEFAULT_FONT_SIZE, FontWeight weight = FontWeight.Medium, bool italics = false, bool fixedWidth = false)
|
||||
=> new FontUsage(GetFamilyString(typeface), size, GetWeightString(typeface, weight), italics, fixedWidth);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the string representation of a <see cref="TournamentTypeface"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeface">The <see cref="TournamentTypeface"/>.</param>
|
||||
/// <returns>The string representation.</returns>
|
||||
public static string GetFamilyString(TournamentTypeface typeface)
|
||||
{
|
||||
switch (typeface)
|
||||
{
|
||||
case TournamentTypeface.Aquatico:
|
||||
return "Aquatico";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the string representation of a <see cref="FontWeight"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeface">The <see cref="TournamentTypeface"/>.</param>
|
||||
/// <param name="weight">The <see cref="FontWeight"/>.</param>
|
||||
/// <returns>The string representation of <paramref name="weight"/> in the specified <paramref name="typeface"/>.</returns>
|
||||
public static string GetWeightString(TournamentTypeface typeface, FontWeight weight)
|
||||
=> GetWeightString(GetFamilyString(typeface), weight);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the string representation of a <see cref="FontWeight"/>.
|
||||
/// </summary>
|
||||
/// <param name="family">The family string.</param>
|
||||
/// <param name="weight">The <see cref="FontWeight"/>.</param>
|
||||
/// <returns>The string representation of <paramref name="weight"/> in the specified <paramref name="family"/>.</returns>
|
||||
public static string GetWeightString(string family, FontWeight weight)
|
||||
{
|
||||
string weightString = weight.ToString();
|
||||
|
||||
// Only exo has an explicit "regular" weight, other fonts do not
|
||||
if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico) && family != GetFamilyString(TournamentTypeface.Aquatico))
|
||||
weightString = string.Empty;
|
||||
|
||||
return weightString;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TournamentTypeface
|
||||
{
|
||||
Aquatico
|
||||
}
|
||||
}
|
25
osu.Game.Tournament/TournamentGame.cs
Normal file
25
osu.Game.Tournament/TournamentGame.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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.Graphics.Cursor;
|
||||
|
||||
namespace osu.Game.Tournament
|
||||
{
|
||||
public class TournamentGame : TournamentGameBase
|
||||
{
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new OsuContextMenuContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new TournamentSceneManager()
|
||||
});
|
||||
|
||||
// we don't want to show the menu cursor as it would appear on stream output.
|
||||
MenuCursorContainer.Cursor.Alpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
259
osu.Game.Tournament/TournamentGameBase.cs
Normal file
259
osu.Game.Tournament/TournamentGameBase.cs
Normal file
@ -0,0 +1,259 @@
|
||||
// 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.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tournament
|
||||
{
|
||||
public abstract class TournamentGameBase : OsuGameBase
|
||||
{
|
||||
private const string bracket_filename = "bracket.json";
|
||||
|
||||
private LadderInfo ladder;
|
||||
|
||||
private Storage storage;
|
||||
|
||||
private DependencyContainer dependencies;
|
||||
|
||||
private Bindable<Size> windowSize;
|
||||
private FileBasedIPC ipc;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
return dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(Storage storage, FrameworkConfigManager frameworkConfig)
|
||||
{
|
||||
Resources.AddStore(new DllResourceStore(@"osu.Game.Tournament.dll"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Regular"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Resources/Fonts/Aquatico-Light"));
|
||||
|
||||
Textures.AddStore(new TextureLoaderStore(new ResourceStore<byte[]>(new StorageBackedResourceStore(storage))));
|
||||
|
||||
this.storage = storage;
|
||||
|
||||
windowSize = frameworkConfig.GetBindable<Size>(FrameworkSetting.WindowedSize);
|
||||
|
||||
readBracket();
|
||||
|
||||
ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value);
|
||||
|
||||
dependencies.CacheAs<MatchIPCInfo>(ipc = new FileBasedIPC());
|
||||
Add(ipc);
|
||||
|
||||
Add(new OsuButton
|
||||
{
|
||||
Text = "Save Changes",
|
||||
Width = 140,
|
||||
Height = 50,
|
||||
Depth = float.MinValue,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Padding = new MarginPadding(10),
|
||||
Action = SaveChanges,
|
||||
});
|
||||
}
|
||||
|
||||
private void readBracket()
|
||||
{
|
||||
if (storage.Exists(bracket_filename))
|
||||
{
|
||||
using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open))
|
||||
using (var sr = new StreamReader(stream))
|
||||
ladder = JsonConvert.DeserializeObject<LadderInfo>(sr.ReadToEnd());
|
||||
}
|
||||
else
|
||||
{
|
||||
ladder = new LadderInfo();
|
||||
}
|
||||
|
||||
dependencies.Cache(ladder);
|
||||
|
||||
bool addedInfo = false;
|
||||
|
||||
// assign teams
|
||||
foreach (var match in ladder.Matches)
|
||||
{
|
||||
match.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team1Acronym);
|
||||
match.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team2Acronym);
|
||||
|
||||
foreach (var conditional in match.ConditionalMatches)
|
||||
{
|
||||
conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team1Acronym);
|
||||
conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team2Acronym);
|
||||
conditional.Round.Value = match.Round.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// assign progressions
|
||||
foreach (var pair in ladder.Progressions)
|
||||
{
|
||||
var src = ladder.Matches.FirstOrDefault(p => p.ID == pair.SourceID);
|
||||
var dest = ladder.Matches.FirstOrDefault(p => p.ID == pair.TargetID);
|
||||
|
||||
if (src == null)
|
||||
continue;
|
||||
|
||||
if (dest != null)
|
||||
{
|
||||
if (pair.Losers)
|
||||
src.LosersProgression.Value = dest;
|
||||
else
|
||||
src.Progression.Value = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// link matches to rounds
|
||||
foreach (var round in ladder.Rounds)
|
||||
foreach (var id in round.Matches)
|
||||
{
|
||||
var found = ladder.Matches.FirstOrDefault(p => p.ID == id);
|
||||
|
||||
if (found != null)
|
||||
{
|
||||
found.Round.Value = round;
|
||||
if (round.StartDate.Value > found.Date.Value)
|
||||
found.Date.Value = round.StartDate.Value;
|
||||
}
|
||||
}
|
||||
|
||||
addedInfo |= addPlayers();
|
||||
addedInfo |= addBeatmaps();
|
||||
|
||||
if (addedInfo)
|
||||
SaveChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add missing player info based on user IDs.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool addPlayers()
|
||||
{
|
||||
bool addedInfo = false;
|
||||
|
||||
foreach (var t in ladder.Teams)
|
||||
foreach (var p in t.Players)
|
||||
if (string.IsNullOrEmpty(p.Username))
|
||||
{
|
||||
var req = new GetUserRequest(p.Id);
|
||||
req.Perform(API);
|
||||
p.Username = req.Result.Username;
|
||||
|
||||
addedInfo = true;
|
||||
}
|
||||
|
||||
return addedInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add missing beatmap info based on beatmap IDs
|
||||
/// </summary>
|
||||
private bool addBeatmaps()
|
||||
{
|
||||
bool addedInfo = false;
|
||||
|
||||
foreach (var r in ladder.Rounds)
|
||||
foreach (var b in r.Beatmaps)
|
||||
if (b.BeatmapInfo == null)
|
||||
{
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID });
|
||||
req.Perform(API);
|
||||
b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore);
|
||||
|
||||
addedInfo = true;
|
||||
}
|
||||
|
||||
return addedInfo;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display
|
||||
MenuCursorContainer.Cursor.Alpha = 0;
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
var minWidth = (int)(windowSize.Value.Height / 9f * 16 + 400);
|
||||
|
||||
if (windowSize.Value.Width < minWidth)
|
||||
{
|
||||
// todo: can be removed after ppy/osu-framework#1975
|
||||
windowSize.Value = Host.Window.ClientSize = new Size(minWidth, windowSize.Value.Height);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SaveChanges()
|
||||
{
|
||||
foreach (var r in ladder.Rounds)
|
||||
r.Matches = ladder.Matches.Where(p => p.Round.Value == r).Select(p => p.ID).ToList();
|
||||
|
||||
ladder.Progressions = ladder.Matches.Where(p => p.Progression.Value != null).Select(p => new TournamentProgression(p.ID, p.Progression.Value.ID)).Concat(
|
||||
ladder.Matches.Where(p => p.LosersProgression.Value != null).Select(p => new TournamentProgression(p.ID, p.LosersProgression.Value.ID, true)))
|
||||
.ToList();
|
||||
|
||||
using (var stream = storage.GetStream(bracket_filename, FileAccess.Write, FileMode.Create))
|
||||
using (var sw = new StreamWriter(stream))
|
||||
{
|
||||
sw.Write(JsonConvert.SerializeObject(ladder,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
DefaultValueHandling = DefaultValueHandling.Ignore,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
protected override UserInputManager CreateUserInputManager() => new TournamentInputManager();
|
||||
|
||||
private class TournamentInputManager : UserInputManager
|
||||
{
|
||||
protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case MouseButton.Right:
|
||||
return new RightMouseManager(button);
|
||||
}
|
||||
|
||||
return base.CreateButtonManagerFor(button);
|
||||
}
|
||||
|
||||
private class RightMouseManager : MouseButtonEventManager
|
||||
{
|
||||
public RightMouseManager(MouseButton button)
|
||||
: base(button)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool EnableDrag => true; // allow right-mouse dragging for absolute scroll in scroll containers.
|
||||
public override bool EnableClick => true;
|
||||
public override bool ChangeFocusOnClick => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
165
osu.Game.Tournament/TournamentSceneManager.cs
Normal file
165
osu.Game.Tournament/TournamentSceneManager.cs
Normal file
@ -0,0 +1,165 @@
|
||||
// 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.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens;
|
||||
using osu.Game.Tournament.Screens.Drawings;
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
using osu.Game.Tournament.Screens.Gameplay;
|
||||
using osu.Game.Tournament.Screens.Ladder;
|
||||
using osu.Game.Tournament.Screens.MapPool;
|
||||
using osu.Game.Tournament.Screens.Schedule;
|
||||
using osu.Game.Tournament.Screens.Showcase;
|
||||
using osu.Game.Tournament.Screens.TeamIntro;
|
||||
using osu.Game.Tournament.Screens.TeamWin;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament
|
||||
{
|
||||
[Cached]
|
||||
public class TournamentSceneManager : CompositeDrawable
|
||||
{
|
||||
private Container screens;
|
||||
private TourneyVideo video;
|
||||
|
||||
[Cached]
|
||||
private TournamentMatchChatDisplay chat = new TournamentMatchChatDisplay();
|
||||
|
||||
private Container chatContainer;
|
||||
|
||||
public TournamentSceneManager()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, Storage storage)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
X = 200,
|
||||
FillMode = FillMode.Fit,
|
||||
FillAspectRatio = 16 / 9f,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
Size = new Vector2(0.8f, 1),
|
||||
//Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
video = new TourneyVideo(storage.GetStream("BG Logoless - OWC.m4v"))
|
||||
{
|
||||
Loop = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
screens = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ScheduleScreen(),
|
||||
new LadderScreen(),
|
||||
new LadderEditorScreen(),
|
||||
new TeamEditorScreen(),
|
||||
new RoundEditorScreen(),
|
||||
new ShowcaseScreen(),
|
||||
new MapPoolScreen(),
|
||||
new TeamIntroScreen(),
|
||||
new DrawingsScreen(),
|
||||
new GameplayScreen(),
|
||||
new TeamWinScreen()
|
||||
}
|
||||
},
|
||||
chatContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = chat
|
||||
},
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 200,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = Color4.Black,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Team Editor", Action = () => SetScreen(typeof(TeamEditorScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Rounds Editor", Action = () => SetScreen(typeof(RoundEditorScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket Editor", Action = () => SetScreen(typeof(LadderEditorScreen)) },
|
||||
new Container { RelativeSizeAxes = Axes.X, Height = 50 },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Drawings", Action = () => SetScreen(typeof(DrawingsScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Showcase", Action = () => SetScreen(typeof(ShowcaseScreen)) },
|
||||
new Container { RelativeSizeAxes = Axes.X, Height = 50 },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Schedule", Action = () => SetScreen(typeof(ScheduleScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Bracket", Action = () => SetScreen(typeof(LadderScreen)) },
|
||||
new Container { RelativeSizeAxes = Axes.X, Height = 50 },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "TeamIntro", Action = () => SetScreen(typeof(TeamIntroScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "MapPool", Action = () => SetScreen(typeof(MapPoolScreen)) },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Gameplay", Action = () => SetScreen(typeof(GameplayScreen)) },
|
||||
new Container { RelativeSizeAxes = Axes.X, Height = 50 },
|
||||
new OsuButton { RelativeSizeAxes = Axes.X, Text = "Win", Action = () => SetScreen(typeof(TeamWinScreen)) },
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
SetScreen(typeof(ScheduleScreen));
|
||||
}
|
||||
|
||||
public void SetScreen(Type screenType)
|
||||
{
|
||||
var screen = screens.FirstOrDefault(s => s.GetType() == screenType);
|
||||
if (screen == null) return;
|
||||
|
||||
foreach (var s in screens.Children)
|
||||
{
|
||||
if (s == screen)
|
||||
{
|
||||
s.Show();
|
||||
if (s is IProvideVideo)
|
||||
video.FadeOut(200);
|
||||
else
|
||||
video.Show();
|
||||
}
|
||||
else
|
||||
s.Hide();
|
||||
}
|
||||
|
||||
switch (screen)
|
||||
{
|
||||
case GameplayScreen _:
|
||||
case MapPoolScreen _:
|
||||
chatContainer.FadeIn(100);
|
||||
break;
|
||||
|
||||
default:
|
||||
chatContainer.FadeOut(100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
osu.Game.Tournament/osu.Game.Tournament.csproj
Normal file
16
osu.Game.Tournament/osu.Game.Tournament.csproj
Normal file
@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\osu.Game.props" />
|
||||
<PropertyGroup Label="Project">
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Description>tools for tournaments.</Description>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Project References">
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -13,9 +13,10 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
@ -47,7 +48,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
public bool FilteringActive { get; set; }
|
||||
|
||||
private OsuSpriteText text;
|
||||
private OsuTextFlowContainer pressAKey;
|
||||
private Drawable pressAKey;
|
||||
|
||||
private FillFlowContainer<KeyButton> buttons;
|
||||
|
||||
@ -80,7 +81,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
Hollow = true,
|
||||
};
|
||||
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
@ -99,15 +100,19 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
pressAKey = new OsuTextFlowContainer
|
||||
pressAKey = new FillFlowContainer
|
||||
{
|
||||
Text = "Press a key to change binding, Shift+Delete to delete, Escape to cancel.",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding(padding),
|
||||
Padding = new MarginPadding { Top = height },
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding(padding) { Top = height + padding * 2 },
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Alpha = 0,
|
||||
Colour = colours.YellowDark
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CancelButton { Action = finalise },
|
||||
new ClearButton { Action = clear },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -205,21 +210,6 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
if (!HasFocus)
|
||||
return false;
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Delete:
|
||||
{
|
||||
if (e.ShiftPressed)
|
||||
{
|
||||
bindTarget.UpdateKeyCombination(InputKey.None);
|
||||
finalise();
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(e.CurrentState));
|
||||
if (!isModifier(e.Key)) finalise();
|
||||
|
||||
@ -254,6 +244,12 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
return true;
|
||||
}
|
||||
|
||||
private void clear()
|
||||
{
|
||||
bindTarget.UpdateKeyCombination(InputKey.None);
|
||||
finalise();
|
||||
}
|
||||
|
||||
private void finalise()
|
||||
{
|
||||
if (bindTarget != null)
|
||||
@ -300,6 +296,41 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
if (bindTarget != null) bindTarget.IsBinding = true;
|
||||
}
|
||||
|
||||
private class CancelButton : TriangleButton
|
||||
{
|
||||
public CancelButton()
|
||||
{
|
||||
Text = "Cancel";
|
||||
Size = new Vector2(80, 20);
|
||||
}
|
||||
}
|
||||
|
||||
private class ClearButton : TriangleButton
|
||||
{
|
||||
public ClearButton()
|
||||
{
|
||||
Text = "Clear";
|
||||
Size = new Vector2(80, 20);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(MouseUpEvent e)
|
||||
{
|
||||
base.OnMouseUp(e);
|
||||
|
||||
// without this, the mouse up triggers a finalise (and deselection) of the current binding target.
|
||||
return true;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
BackgroundColour = colours.Pink;
|
||||
|
||||
Triangles.ColourDark = colours.PinkDark;
|
||||
Triangles.ColourLight = colours.PinkLight;
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyButton : Container
|
||||
{
|
||||
public readonly Framework.Input.Bindings.KeyBinding KeyBinding;
|
||||
|
@ -60,7 +60,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Text = "Reset";
|
||||
Text = "Reset all bindings in section";
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Margin = new MarginPadding { Top = 5 };
|
||||
Height = 20;
|
||||
|
@ -116,6 +116,7 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new[]
|
||||
{
|
||||
scoreRankInfos[ScoreRank.XH] = new ScoreRankInfo(ScoreRank.XH),
|
||||
@ -200,7 +201,7 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new UpdateableRank(rank)
|
||||
new DrawableRank(rank)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 30,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user