mirror of
https://github.com/osukey/osukey.git
synced 2025-05-29 09:27:18 +09:00
Merge branch 'master' into osu-hd-setting
This commit is contained in:
commit
ee92986494
@ -1,6 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="VisualTests (netcoreapp2.0)" type="DotNetProject" factoryName=".NET Project">
|
<configuration default="false" name="VisualTests (netcoreapp2.1)" type="DotNetProject" factoryName=".NET Project">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/netcoreapp2.1/osu.Game.Tests.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.0" />
|
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
@ -1,6 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="osu! (netcoreapp2.0)" type="DotNetProject" factoryName=".NET Project">
|
<configuration default="false" name="osu! (netcoreapp2.1)" type="DotNetProject" factoryName=".NET Project">
|
||||||
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.0/osu!.dll" />
|
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/netcoreapp2.1/osu!.dll" />
|
||||||
<option name="PROGRAM_PARAMETERS" value="" />
|
<option name="PROGRAM_PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
|
||||||
<option name="PASS_PARENT_ENVS" value="1" />
|
<option name="PASS_PARENT_ENVS" value="1" />
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.0" />
|
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v2.1" />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
26
.vscode/launch.json
vendored
26
.vscode/launch.json
vendored
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"type": "mono",
|
"type": "mono",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net471/osu.Game.Tests.exe",
|
"program": "${workspaceRoot}/osu.Game.Tests/bin/Release/net471/osu.Game.Tests.exe",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, msbuild)",
|
"preLaunchTask": "Build (Release, msbuild)",
|
||||||
"runtimeExecutable": null,
|
"runtimeExecutable": null,
|
||||||
@ -58,54 +58,54 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Debug, netcoreapp2.0)",
|
"name": "VisualTests (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll"
|
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.1/osu.Game.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build tests (Debug, dotnet)",
|
||||||
"env": {},
|
"env": {},
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Release, netcoreapp2.0)",
|
"name": "VisualTests (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp2.0/osu.Game.Tests.dll"
|
"${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp2.1/osu.Game.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build tests (Release, dotnet)",
|
||||||
"env": {},
|
"env": {},
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "osu! (Debug, netcoreapp2.0)",
|
"name": "osu! (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.0/osu!.dll",
|
"${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp2.1/osu!.dll",
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build osu! (Debug, dotnet)",
|
||||||
"env": {},
|
"env": {},
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "osu! (Release, netcoreapp2.0)",
|
"name": "osu! (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.0/osu!.dll",
|
"${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp2.1/osu!.dll",
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build osu! (Release, dotnet)",
|
||||||
"env": {},
|
"env": {},
|
||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
}
|
}
|
||||||
|
43
.vscode/tasks.json
vendored
43
.vscode/tasks.json
vendored
@ -31,14 +31,14 @@
|
|||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Build (Debug, dotnet)",
|
"label": "Build osu! (Debug, dotnet)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Desktop",
|
"osu.Desktop",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
"/verbosity:m"
|
"/verbosity:m"
|
||||||
@ -47,14 +47,47 @@
|
|||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Build (Release, dotnet)",
|
"label": "Build osu! (Release, dotnet)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Desktop",
|
"osu.Desktop",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
|
"/p:Configuration=Release",
|
||||||
|
"/p:GenerateFullPaths=true",
|
||||||
|
"/m",
|
||||||
|
"/verbosity:m"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build tests (Debug, dotnet)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--no-restore",
|
||||||
|
"osu.Game.Tests",
|
||||||
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
|
"/p:GenerateFullPaths=true",
|
||||||
|
"/m",
|
||||||
|
"/verbosity:m"
|
||||||
|
],
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Build tests (Release, dotnet)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--no-restore",
|
||||||
|
"osu.Game.Tests",
|
||||||
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:Configuration=Release",
|
"/p:Configuration=Release",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
@ -73,7 +106,7 @@
|
|||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Restore (netcoreapp2.0)",
|
"label": "Restore (netcoreapp2.1)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
version: '{branch}-{build}'
|
version: '{branch}-{build}'
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017 preview
|
||||||
configuration: Debug
|
configuration: Debug
|
||||||
cache:
|
cache:
|
||||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4
|
Subproject commit b963ce82505bc953db0a0763679e1ec80a060811
|
@ -12,6 +12,7 @@ using osu.Framework.Platform;
|
|||||||
using osu.Game;
|
using osu.Game;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
using osu.Framework.Platform.Windows;
|
||||||
|
|
||||||
namespace osu.Desktop
|
namespace osu.Desktop
|
||||||
{
|
{
|
||||||
@ -40,7 +41,7 @@ namespace osu.Desktop
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A method of accessing an osu-stable install in a controlled fashion.
|
/// A method of accessing an osu-stable install in a controlled fashion.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private class StableStorage : DesktopStorage
|
private class StableStorage : WindowsStorage
|
||||||
{
|
{
|
||||||
protected override string LocateBasePath()
|
protected override string LocateBasePath()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="..\osu.Game.props" />
|
<Import Project="..\osu.Game.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<TargetFrameworks>net471;netcoreapp2.0</TargetFrameworks>
|
<TargetFrameworks>net471;netcoreapp2.1</TargetFrameworks>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@ -30,10 +30,10 @@
|
|||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.3" />
|
||||||
<PackageReference Include="squirrel.windows" Version="1.8.0" Condition="'$(TargetFramework)' == 'net471'" />
|
<PackageReference Include="squirrel.windows" Version="1.8.0" Condition="'$(TargetFramework)' == 'net471'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<EmbeddedResource Include="lazer.ico" />
|
<EmbeddedResource Include="lazer.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"type": "mono",
|
"type": "mono",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe",
|
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Catch.Tests.exe",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, msbuild)",
|
"preLaunchTask": "Build (Release, msbuild)",
|
||||||
"runtimeExecutable": null,
|
"runtimeExecutable": null,
|
||||||
@ -30,12 +30,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Debug, netcoreapp2.0)",
|
"name": "VisualTests (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Catch.Tests.dll"
|
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build (Debug, dotnet)",
|
||||||
@ -43,12 +43,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Release, netcoreapp2.0)",
|
"name": "VisualTests (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Catch.Tests.dll"
|
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Catch.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build (Release, dotnet)",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Catch.Tests.csproj",
|
"osu.Game.Rulesets.Catch.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
"/verbosity:m"
|
"/verbosity:m"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Catch.Tests.csproj",
|
"osu.Game.Rulesets.Catch.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:Configuration=Release",
|
"/p:Configuration=Release",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Restore (netcoreapp2.0)",
|
"label": "Restore (netcoreapp2.1)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size })
|
Child = catcherArea = new TestCatcherArea(new BeatmapDifficulty { CircleSize = size })
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.BottomLeft
|
Origin = Anchor.TopLeft
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
typeof(DrawableCatchHitObject),
|
typeof(DrawableCatchHitObject),
|
||||||
typeof(DrawableFruit),
|
typeof(DrawableFruit),
|
||||||
typeof(DrawableDroplet),
|
typeof(DrawableDroplet),
|
||||||
|
typeof(BananaShower),
|
||||||
typeof(Pulp),
|
typeof(Pulp),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,12 +54,19 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private DrawableFruit createDrawable(int index)
|
private DrawableFruit createDrawable(int index)
|
||||||
{
|
{
|
||||||
var fruit = new Fruit
|
Fruit fruit = index == 5
|
||||||
{
|
? new BananaShower.Banana
|
||||||
StartTime = 1000000000000,
|
{
|
||||||
IndexInBeatmap = index,
|
StartTime = 1000000000000,
|
||||||
Scale = 1.5f,
|
IndexInBeatmap = index,
|
||||||
};
|
Scale = 1.5f,
|
||||||
|
}
|
||||||
|
: new Fruit
|
||||||
|
{
|
||||||
|
StartTime = 1000000000000,
|
||||||
|
IndexInBeatmap = index,
|
||||||
|
Scale = 1.5f,
|
||||||
|
};
|
||||||
|
|
||||||
return new DrawableFruit(fruit)
|
return new DrawableFruit(fruit)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
|
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />
|
||||||
|
@ -28,7 +28,20 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
var endTime = obj as IHasEndTime;
|
var endTime = obj as IHasEndTime;
|
||||||
|
|
||||||
if (positionData == null)
|
if (positionData == null)
|
||||||
|
{
|
||||||
|
if (endTime != null)
|
||||||
|
{
|
||||||
|
yield return new BananaShower
|
||||||
|
{
|
||||||
|
StartTime = obj.StartTime,
|
||||||
|
Samples = obj.Samples,
|
||||||
|
Duration = endTime.Duration,
|
||||||
|
NewCombo = comboData?.NewCombo ?? false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
yield break;
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
if (curveData != null)
|
if (curveData != null)
|
||||||
{
|
{
|
||||||
@ -48,19 +61,6 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endTime != null)
|
|
||||||
{
|
|
||||||
yield return new BananaShower
|
|
||||||
{
|
|
||||||
StartTime = obj.StartTime,
|
|
||||||
Samples = obj.Samples,
|
|
||||||
Duration = endTime.Duration,
|
|
||||||
NewCombo = comboData?.NewCombo ?? false
|
|
||||||
};
|
|
||||||
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return new Fruit
|
yield return new Fruit
|
||||||
{
|
{
|
||||||
StartTime = obj.StartTime,
|
StartTime = obj.StartTime,
|
||||||
|
@ -18,12 +18,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
private Circle border;
|
private Circle border;
|
||||||
|
|
||||||
|
private const float drawable_radius = (float)CatchHitObject.OBJECT_RADIUS * radius_adjust;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Because we're adding a border around the fruit, we need to scale down some.
|
||||||
|
/// </summary>
|
||||||
|
private const float radius_adjust = 1.1f;
|
||||||
|
|
||||||
public DrawableFruit(Fruit h)
|
public DrawableFruit(Fruit h)
|
||||||
: base(h)
|
: base(h)
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS);
|
Size = new Vector2(drawable_radius);
|
||||||
Masking = false;
|
Masking = false;
|
||||||
|
|
||||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||||
@ -44,14 +51,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
Hollow = !HitObject.HyperDash,
|
Hollow = !HitObject.HyperDash,
|
||||||
Type = EdgeEffectType.Glow,
|
Type = EdgeEffectType.Glow,
|
||||||
Radius = 4,
|
Radius = 4 * radius_adjust,
|
||||||
Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f)
|
Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f)
|
||||||
},
|
},
|
||||||
Size = new Vector2(Height * 1.5f),
|
Size = new Vector2(Height),
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
BorderThickness = 4f,
|
BorderThickness = 3f * radius_adjust,
|
||||||
Children = new Framework.Graphics.Drawable[]
|
Children = new Framework.Graphics.Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
@ -82,8 +89,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
|
|
||||||
private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation)
|
private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation)
|
||||||
{
|
{
|
||||||
const float large_pulp_3 = 13f;
|
const float large_pulp_3 = 8f * radius_adjust;
|
||||||
const float distance_from_centre_3 = 0.23f;
|
const float distance_from_centre_3 = 0.15f;
|
||||||
|
|
||||||
const float large_pulp_4 = large_pulp_3 * 0.925f;
|
const float large_pulp_4 = large_pulp_3 * 0.925f;
|
||||||
const float distance_from_centre_4 = distance_from_centre_3 / 0.925f;
|
const float distance_from_centre_4 = distance_from_centre_3 / 0.925f;
|
||||||
@ -106,11 +113,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(small_pulp),
|
Size = new Vector2(small_pulp),
|
||||||
Y = 0.05f,
|
Y = -0.34f,
|
||||||
},
|
},
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
@ -146,11 +151,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.BottomCentre,
|
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(small_pulp),
|
Size = new Vector2(small_pulp),
|
||||||
Y = 0.1f,
|
Y = -0.3f,
|
||||||
},
|
},
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
@ -186,11 +189,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(small_pulp),
|
Size = new Vector2(small_pulp),
|
||||||
Y = -0.1f,
|
Y = -0.33f,
|
||||||
},
|
},
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
@ -220,10 +221,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(small_pulp),
|
Size = new Vector2(small_pulp),
|
||||||
|
Y = -0.25f,
|
||||||
},
|
},
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
@ -253,16 +253,15 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
{
|
{
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(small_pulp),
|
Size = new Vector2(small_pulp),
|
||||||
Y = -0.15f
|
Y = -0.3f
|
||||||
},
|
},
|
||||||
new Pulp
|
new Pulp
|
||||||
{
|
{
|
||||||
AccentColour = AccentColour,
|
AccentColour = AccentColour,
|
||||||
Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3),
|
Size = new Vector2(large_pulp_4 * 0.8f, large_pulp_4 * 2.5f),
|
||||||
|
Y = 0.05f,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -29,14 +29,24 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
accentColour = value;
|
accentColour = value;
|
||||||
|
if (IsLoaded) updateAccentColour();
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 8,
|
|
||||||
Colour = accentColour.Darken(0.2f).Opacity(0.75f)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateAccentColour()
|
||||||
|
{
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = Size.X / 2,
|
||||||
|
Colour = accentColour.Darken(0.2f).Opacity(0.75f)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
updateAccentColour();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
|
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
|
||||||
|
|
||||||
|
protected override Vector2 PlayfieldArea => new Vector2(0.86f); // matches stable's vertical offset for catcher plate
|
||||||
|
|
||||||
protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
|
protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
|
||||||
{
|
{
|
||||||
switch (h)
|
switch (h)
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class CatcherArea : Container
|
public class CatcherArea : Container
|
||||||
{
|
{
|
||||||
public const float CATCHER_SIZE = 172;
|
public const float CATCHER_SIZE = 84;
|
||||||
|
|
||||||
protected readonly Catcher MovableCatcher;
|
protected readonly Catcher MovableCatcher;
|
||||||
|
|
||||||
@ -99,8 +99,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||||
{
|
{
|
||||||
private Texture texture;
|
|
||||||
|
|
||||||
private Container<DrawableHitObject> caughtFruit;
|
private Container<DrawableHitObject> caughtFruit;
|
||||||
|
|
||||||
public Container ExplodingFruitTarget;
|
public Container ExplodingFruitTarget;
|
||||||
@ -121,10 +119,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load()
|
||||||
{
|
{
|
||||||
texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
caughtFruit = new Container<DrawableHitObject>
|
caughtFruit = new Container<DrawableHitObject>
|
||||||
@ -196,13 +192,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
|
Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Sprite createCatcherSprite() => new Sprite
|
private Sprite createCatcherSprite() => new CatcherSprite();
|
||||||
{
|
|
||||||
Size = new Vector2(CATCHER_SIZE),
|
|
||||||
FillMode = FillMode.Fill,
|
|
||||||
Texture = texture,
|
|
||||||
OriginPosition = new Vector2(-3, 10) // temporary until the sprite is aligned correctly.
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a caught fruit to the catcher's stack.
|
/// Add a caught fruit to the catcher's stack.
|
||||||
@ -411,6 +401,23 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
f.Expire();
|
f.Expire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CatcherSprite : Sprite
|
||||||
|
{
|
||||||
|
public CatcherSprite()
|
||||||
|
{
|
||||||
|
Size = new Vector2(CATCHER_SIZE);
|
||||||
|
|
||||||
|
// Sets the origin roughly to the centre of the catcher's plate to allow for correct scaling.
|
||||||
|
OriginPosition = new Vector2(-0.02f, 0.06f) * CATCHER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(TextureStore textures)
|
||||||
|
{
|
||||||
|
Texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"type": "mono",
|
"type": "mono",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe",
|
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Mania.Tests.exe",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, msbuild)",
|
"preLaunchTask": "Build (Release, msbuild)",
|
||||||
"runtimeExecutable": null,
|
"runtimeExecutable": null,
|
||||||
@ -30,12 +30,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Debug, netcoreapp2.0)",
|
"name": "VisualTests (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Mania.Tests.dll"
|
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build (Debug, dotnet)",
|
||||||
@ -43,12 +43,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Release, netcoreapp2.0)",
|
"name": "VisualTests (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Mania.Tests.dll"
|
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Mania.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build (Release, dotnet)",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Mania.Tests.csproj",
|
"osu.Game.Rulesets.Mania.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
"/verbosity:m"
|
"/verbosity:m"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Mania.Tests.csproj",
|
"osu.Game.Rulesets.Mania.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:Configuration=Release",
|
"/p:Configuration=Release",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Restore (netcoreapp2.0)",
|
"label": "Restore (netcoreapp2.1)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
|
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />
|
||||||
|
@ -105,7 +105,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
|
|
||||||
private double computeAccuracyValue(double strainValue)
|
private double computeAccuracyValue(double strainValue)
|
||||||
{
|
{
|
||||||
double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate;
|
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future
|
||||||
|
double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate;
|
||||||
if (hitWindowGreat <= 0)
|
if (hitWindowGreat <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Name => "Dual Stages";
|
public override string Name => "Dual Stages";
|
||||||
public override string ShortenedName => "DS";
|
public override string ShortenedName => "DS";
|
||||||
public override string Description => @"Double the stages, double the fun!";
|
public override string Description => @"Double the stages, double the fun!";
|
||||||
public override double ScoreMultiplier => 0;
|
public override double ScoreMultiplier => 1;
|
||||||
|
|
||||||
private bool isForCurrentRuleset;
|
private bool isForCurrentRuleset;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string ShortenedName => "RD";
|
public override string ShortenedName => "RD";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_dice;
|
public override FontAwesome Icon => FontAwesome.fa_osu_dice;
|
||||||
public override string Description => @"Shuffle around the keys!";
|
public override string Description => @"Shuffle around the keys!";
|
||||||
public override double ScoreMultiplier => 0;
|
public override double ScoreMultiplier => 1;
|
||||||
|
|
||||||
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
|
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
||||||
{
|
{
|
||||||
|
public override bool DisplayJudgement => false;
|
||||||
|
|
||||||
private readonly DrawableNote head;
|
private readonly DrawableNote head;
|
||||||
private readonly DrawableNote tail;
|
private readonly DrawableNote tail;
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
{
|
{
|
||||||
if (!judgement.IsHit)
|
if (!judgement.IsHit || !judgedObject.DisplayJudgement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
explosionContainer.Add(new HitExplosion(judgedObject));
|
explosionContainer.Add(new HitExplosion(judgedObject));
|
||||||
|
@ -171,6 +171,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
{
|
{
|
||||||
|
if (!judgedObject.DisplayJudgement)
|
||||||
|
return;
|
||||||
|
|
||||||
judgements.Clear();
|
judgements.Clear();
|
||||||
judgements.Add(new DrawableManiaJudgement(judgement, judgedObject)
|
judgements.Add(new DrawableManiaJudgement(judgement, judgedObject)
|
||||||
{
|
{
|
||||||
|
10
osu.Game.Rulesets.Osu.Tests/.vscode/launch.json
vendored
10
osu.Game.Rulesets.Osu.Tests/.vscode/launch.json
vendored
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"type": "mono",
|
"type": "mono",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe",
|
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Osu.Tests.exe",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, msbuild)",
|
"preLaunchTask": "Build (Release, msbuild)",
|
||||||
"runtimeExecutable": null,
|
"runtimeExecutable": null,
|
||||||
@ -30,12 +30,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Debug, netcoreapp2.0)",
|
"name": "VisualTests (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Osu.Tests.dll"
|
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build (Debug, dotnet)",
|
||||||
@ -43,12 +43,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Release, netcoreapp2.0)",
|
"name": "VisualTests (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Osu.Tests.dll"
|
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Osu.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build (Release, dotnet)",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Osu.Tests.csproj",
|
"osu.Game.Rulesets.Osu.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
"/verbosity:m"
|
"/verbosity:m"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Osu.Tests.csproj",
|
"osu.Game.Rulesets.Osu.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:Configuration=Release",
|
"/p:Configuration=Release",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Restore (netcoreapp2.0)",
|
"label": "Restore (netcoreapp2.1)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
|
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -61,20 +61,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
if (mods.Any(m => !m.Ranked))
|
if (mods.Any(m => !m.Ranked))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Todo: In the future we should apply changes to PreEmpt/AR at an OsuHitObject/BaseDifficulty level, but this is done
|
// Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future
|
||||||
// locally for now as doing so would modify animations and other things unexpectedly
|
double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate;
|
||||||
// DO NOT MODIFY THIS
|
double preEmpt = (int)BeatmapDifficulty.DifficultyRange(Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / TimeRate;
|
||||||
double ar = Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate;
|
|
||||||
if (mods.Any(m => m is OsuModHardRock))
|
|
||||||
ar = Math.Min(10, ar * 1.4);
|
|
||||||
if (mods.Any(m => m is OsuModEasy))
|
|
||||||
ar = Math.Max(0, ar / 2);
|
|
||||||
|
|
||||||
double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate;
|
|
||||||
double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate;
|
|
||||||
|
|
||||||
realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5;
|
realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5;
|
||||||
realOverallDifficulty = (80 - 0.5 - hitWindowGreat) / 6;
|
realOverallDifficulty = (80 - hitWindowGreat) / 6;
|
||||||
|
|
||||||
// Custom multipliers for NoFail and SpunOut.
|
// Custom multipliers for NoFail and SpunOut.
|
||||||
double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things
|
double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things
|
||||||
|
@ -13,8 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
public override string ShortenedName => "AP";
|
public override string ShortenedName => "AP";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
|
||||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||||
public override double ScoreMultiplier => 0;
|
public override double ScoreMultiplier => 1;
|
||||||
public override bool Ranked => false;
|
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
|
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"type": "mono",
|
"type": "mono",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe",
|
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Taiko.Tests.exe",
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, msbuild)",
|
"preLaunchTask": "Build (Release, msbuild)",
|
||||||
"runtimeExecutable": null,
|
"runtimeExecutable": null,
|
||||||
@ -30,12 +30,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Debug, netcoreapp2.0)",
|
"name": "VisualTests (Debug, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Taiko.Tests.dll"
|
"${workspaceRoot}/bin/Debug/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Debug, dotnet)",
|
"preLaunchTask": "Build (Debug, dotnet)",
|
||||||
@ -43,12 +43,12 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "VisualTests (Release, netcoreapp2.0)",
|
"name": "VisualTests (Release, netcoreapp2.1)",
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "dotnet",
|
"program": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceRoot}/bin/Debug/netcoreapp2.0/osu.Game.Rulesets.Taiko.Tests.dll"
|
"${workspaceRoot}/bin/Release/netcoreapp2.1/osu.Game.Rulesets.Taiko.Tests.dll"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
"preLaunchTask": "Build (Release, dotnet)",
|
"preLaunchTask": "Build (Release, dotnet)",
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Taiko.Tests.csproj",
|
"osu.Game.Rulesets.Taiko.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
"/verbosity:m"
|
"/verbosity:m"
|
||||||
@ -56,7 +56,7 @@
|
|||||||
"build",
|
"build",
|
||||||
"--no-restore",
|
"--no-restore",
|
||||||
"osu.Game.Rulesets.Taiko.Tests.csproj",
|
"osu.Game.Rulesets.Taiko.Tests.csproj",
|
||||||
"/p:TargetFramework=netcoreapp2.0",
|
"/p:TargetFramework=netcoreapp2.1",
|
||||||
"/p:Configuration=Release",
|
"/p:Configuration=Release",
|
||||||
"/p:GenerateFullPaths=true",
|
"/p:GenerateFullPaths=true",
|
||||||
"/m",
|
"/m",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Restore (netcoreapp2.0)",
|
"label": "Restore (netcoreapp2.1)",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
|
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
|
||||||
|
@ -94,7 +94,8 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
|
|
||||||
private double computeAccuracyValue()
|
private double computeAccuracyValue()
|
||||||
{
|
{
|
||||||
double hitWindowGreat = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate;
|
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future
|
||||||
|
double hitWindowGreat = (int)(Beatmap.HitObjects.First().HitWindows.Great / 2) / TimeRate;
|
||||||
if (hitWindowGreat <= 0)
|
if (hitWindowGreat <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ using osu.Framework.Platform;
|
|||||||
using osu.Game.IPC;
|
using osu.Game.IPC;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using SharpCompress.Archives.Zip;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Beatmaps.IO
|
namespace osu.Game.Tests.Beatmaps.IO
|
||||||
{
|
{
|
||||||
@ -77,8 +78,69 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 1);
|
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1);
|
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
host.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRollbackOnFailure()
|
||||||
|
{
|
||||||
|
//unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here.
|
||||||
|
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestRollbackOnFailure"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var osu = loadOsu(host);
|
||||||
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
|
int fireCount = 0;
|
||||||
|
|
||||||
|
// ReSharper disable once AccessToModifiedClosure
|
||||||
|
manager.ItemAdded += _ => fireCount++;
|
||||||
|
manager.ItemRemoved += _ => fireCount++;
|
||||||
|
|
||||||
|
var imported = loadOszIntoOsu(osu);
|
||||||
|
|
||||||
|
Assert.AreEqual(0, fireCount -= 1);
|
||||||
|
|
||||||
|
imported.Hash += "-changed";
|
||||||
|
manager.Update(imported);
|
||||||
|
|
||||||
|
Assert.AreEqual(0, fireCount -= 2);
|
||||||
|
|
||||||
|
var breakTemp = createTemporaryBeatmap();
|
||||||
|
|
||||||
|
MemoryStream brokenOsu = new MemoryStream(new byte[] { 1, 3, 3, 7 });
|
||||||
|
MemoryStream brokenOsz = new MemoryStream(File.ReadAllBytes(breakTemp));
|
||||||
|
|
||||||
|
File.Delete(breakTemp);
|
||||||
|
|
||||||
|
using (var outStream = File.Open(breakTemp, FileMode.CreateNew))
|
||||||
|
using (var zip = ZipArchive.Open(brokenOsz))
|
||||||
|
{
|
||||||
|
zip.AddEntry("broken.osu", brokenOsu, false);
|
||||||
|
zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||||
|
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||||
|
Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count);
|
||||||
|
|
||||||
|
// this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu.
|
||||||
|
manager.Import(breakTemp);
|
||||||
|
|
||||||
|
// no events should be fired in the case of a rollback.
|
||||||
|
Assert.AreEqual(0, fireCount);
|
||||||
|
|
||||||
|
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||||
|
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||||
|
Assert.AreEqual(12, manager.QueryBeatmaps(_ => true).ToList().Count);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -100,18 +162,17 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var imported = loadOszIntoOsu(osu);
|
var imported = loadOszIntoOsu(osu);
|
||||||
|
|
||||||
//var change = manager.QueryBeatmapSets(_ => true).First();
|
|
||||||
imported.Hash += "-changed";
|
imported.Hash += "-changed";
|
||||||
manager.Update(imported);
|
manager.Update(imported);
|
||||||
|
|
||||||
var importedSecondTime = loadOszIntoOsu(osu);
|
var importedSecondTime = loadOszIntoOsu(osu);
|
||||||
|
|
||||||
// check the newly "imported" beatmap is actually just the restored previous import. since it matches hash.
|
|
||||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||||
Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID);
|
Assert.IsTrue(imported.Beatmaps.First().ID < importedSecondTime.Beatmaps.First().ID);
|
||||||
|
|
||||||
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 1);
|
// only one beatmap will exist as the online set ID matched, causing purging of the first import.
|
||||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1);
|
Assert.AreEqual(1, manager.GetAllUsableBeatmapSets().Count);
|
||||||
|
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -162,8 +223,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var osu = loadOsu(host);
|
var osu = loadOsu(host);
|
||||||
|
|
||||||
var temp = prepareTempCopy(osz_path);
|
var temp = createTemporaryBeatmap();
|
||||||
Assert.IsTrue(File.Exists(temp));
|
|
||||||
|
|
||||||
var importer = new ArchiveImportIPCChannel(client);
|
var importer = new ArchiveImportIPCChannel(client);
|
||||||
if (!importer.ImportAsync(temp).Wait(10000))
|
if (!importer.ImportAsync(temp).Wait(10000))
|
||||||
@ -188,8 +248,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var osu = loadOsu(host);
|
var osu = loadOsu(host);
|
||||||
var temp = prepareTempCopy(osz_path);
|
var temp = createTemporaryBeatmap();
|
||||||
Assert.IsTrue(File.Exists(temp), "Temporary file copy never substantiated");
|
|
||||||
using (File.OpenRead(temp))
|
using (File.OpenRead(temp))
|
||||||
osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
osu.Dependencies.Get<BeatmapManager>().Import(temp);
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
@ -203,11 +262,16 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BeatmapSetInfo loadOszIntoOsu(OsuGameBase osu)
|
private string createTemporaryBeatmap()
|
||||||
{
|
{
|
||||||
var temp = prepareTempCopy(osz_path);
|
var temp = new FileInfo(osz_path).CopyTo(Path.GetTempFileName(), true).FullName;
|
||||||
|
|
||||||
Assert.IsTrue(File.Exists(temp));
|
Assert.IsTrue(File.Exists(temp));
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BeatmapSetInfo loadOszIntoOsu(OsuGameBase osu, string path = null)
|
||||||
|
{
|
||||||
|
var temp = path ?? createTemporaryBeatmap();
|
||||||
|
|
||||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
@ -219,7 +283,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||||
|
|
||||||
return imported.FirstOrDefault();
|
return imported.LastOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu)
|
private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu)
|
||||||
@ -228,16 +292,10 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
manager.Delete(imported);
|
manager.Delete(imported);
|
||||||
|
|
||||||
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 0);
|
Assert.IsTrue(manager.GetAllUsableBeatmapSets().Count == 0);
|
||||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).ToList().Count == 1);
|
Assert.AreEqual(1, manager.QueryBeatmapSets(_ => true).ToList().Count);
|
||||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending);
|
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string prepareTempCopy(string path)
|
|
||||||
{
|
|
||||||
var temp = Path.GetTempFileName();
|
|
||||||
return new FileInfo(path).CopyTo(temp, true).FullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private OsuGameBase loadOsu(GameHost host)
|
private OsuGameBase loadOsu(GameHost host)
|
||||||
{
|
{
|
||||||
var osu = new OsuGameBase();
|
var osu = new OsuGameBase();
|
||||||
|
@ -5,6 +5,7 @@ using System.ComponentModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
@ -15,7 +16,20 @@ namespace osu.Game.Tests.Visual
|
|||||||
protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
|
protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
|
||||||
{
|
{
|
||||||
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
||||||
return base.CreatePlayer(beatmap, ruleset);
|
return new ScoreAccessiblePlayer
|
||||||
|
{
|
||||||
|
InitialBeatmap = beatmap,
|
||||||
|
AllowPause = false,
|
||||||
|
AllowLeadIn = false,
|
||||||
|
AllowResults = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ContinueCondition(Player player) => base.ContinueCondition(player) && ((ScoreAccessiblePlayer)player).ScoreProcessor.TotalScore > 0;
|
||||||
|
|
||||||
|
private class ScoreAccessiblePlayer : Player
|
||||||
|
{
|
||||||
|
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
carousel.SelectionChanged = s => currentSelection = s;
|
carousel.SelectionChanged = s => currentSelection = s;
|
||||||
|
|
||||||
AddStep("Load Beatmaps", () => { carousel.BeatmapSets = beatmapSets; });
|
loadBeatmaps(beatmapSets);
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
carousel.BeatmapSetsChanged = () => changed = true;
|
|
||||||
AddUntilStep(() => changed, "Wait for load");
|
|
||||||
|
|
||||||
testTraversal();
|
testTraversal();
|
||||||
testFiltering();
|
testFiltering();
|
||||||
@ -84,6 +80,17 @@ namespace osu.Game.Tests.Visual
|
|||||||
testCarouselRootIsRandom();
|
testCarouselRootIsRandom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadBeatmaps(List<BeatmapSetInfo> beatmapSets)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
AddStep($"Load {beatmapSets.Count} Beatmaps", () =>
|
||||||
|
{
|
||||||
|
carousel.BeatmapSetsChanged = () => changed = true;
|
||||||
|
carousel.BeatmapSets = beatmapSets;
|
||||||
|
});
|
||||||
|
AddUntilStep(() => changed, "Wait for load");
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureRandomFetchSuccess() =>
|
private void ensureRandomFetchSuccess() =>
|
||||||
AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet);
|
AddAssert("ensure prev random fetch worked", () => selectedSets.Peek() == carousel.SelectedBeatmapSet);
|
||||||
|
|
||||||
@ -423,7 +430,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
for (int i = 1; i <= 50; i++)
|
for (int i = 1; i <= 50; i++)
|
||||||
beatmapSets.Add(createTestBeatmapSet(i));
|
beatmapSets.Add(createTestBeatmapSet(i));
|
||||||
|
|
||||||
AddStep("Load 50 Beatmaps", () => { carousel.BeatmapSets = beatmapSets; });
|
loadBeatmaps(beatmapSets);
|
||||||
advanceSelection(direction: 1, diff: false);
|
advanceSelection(direction: 1, diff: false);
|
||||||
checkNonmatchingFilter();
|
checkNonmatchingFilter();
|
||||||
checkNonmatchingFilter();
|
checkNonmatchingFilter();
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep("show", () =>
|
AddStep("show", () =>
|
||||||
{
|
{
|
||||||
infoWedge.State = Visibility.Visible;
|
infoWedge.State = Visibility.Visible;
|
||||||
infoWedge.UpdateBeatmap(beatmap);
|
infoWedge.Beatmap = beatmap;
|
||||||
});
|
});
|
||||||
|
|
||||||
// select part is redundant, but wait for load isn't
|
// select part is redundant, but wait for load isn't
|
||||||
@ -133,7 +133,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep($"select {b.Metadata.Title} beatmap", () =>
|
AddStep($"select {b.Metadata.Title} beatmap", () =>
|
||||||
{
|
{
|
||||||
infoBefore = infoWedge.Info;
|
infoBefore = infoWedge.Info;
|
||||||
infoWedge.UpdateBeatmap(beatmap.Value = new TestWorkingBeatmap(b));
|
infoWedge.Beatmap = beatmap.Value = new TestWorkingBeatmap(b);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load");
|
AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load");
|
||||||
@ -144,7 +144,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep("select null beatmap", () =>
|
AddStep("select null beatmap", () =>
|
||||||
{
|
{
|
||||||
beatmap.Value = beatmap.Default;
|
beatmap.Value = beatmap.Default;
|
||||||
infoWedge.UpdateBeatmap(beatmap);
|
infoWedge.Beatmap = beatmap;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@ namespace osu.Game.Tests.Visual
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestCaseCursors : ManualInputManagerTestCase
|
public class TestCaseCursors : ManualInputManagerTestCase
|
||||||
{
|
{
|
||||||
private readonly CursorOverrideContainer cursorOverrideContainer;
|
private readonly MenuCursorContainer menuCursorContainer;
|
||||||
private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6];
|
private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6];
|
||||||
|
|
||||||
public TestCaseCursors()
|
public TestCaseCursors()
|
||||||
{
|
{
|
||||||
Child = cursorOverrideContainer = new CursorOverrideContainer
|
Child = menuCursorContainer = new MenuCursorContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor));
|
AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor));
|
||||||
AddStep("Move out", moveOut);
|
AddStep("Move out", moveOut);
|
||||||
AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor));
|
AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor));
|
||||||
AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor));
|
AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -112,11 +112,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep("Move to purple area", () => InputManager.MoveMouseTo(cursorBoxes[3]));
|
AddStep("Move to purple area", () => InputManager.MoveMouseTo(cursorBoxes[3]));
|
||||||
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
|
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
|
||||||
AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor));
|
AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor));
|
||||||
AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor));
|
AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor));
|
||||||
AddAssert("Check global cursor at mouse", () => checkAtMouse(cursorOverrideContainer.Cursor));
|
AddAssert("Check global cursor at mouse", () => checkAtMouse(menuCursorContainer.Cursor));
|
||||||
AddStep("Move out", moveOut);
|
AddStep("Move out", moveOut);
|
||||||
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
|
AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor));
|
||||||
AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor));
|
AddAssert("Check global cursor visible", () => checkVisible(menuCursorContainer.Cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
23
osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs
Normal file
23
osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
public class TestCaseExternalLinkButton : OsuTestCase
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ExternalLinkButton) };
|
||||||
|
|
||||||
|
public TestCaseExternalLinkButton()
|
||||||
|
{
|
||||||
|
Child = new ExternalLinkButton("https://osu.ppy.sh/home")
|
||||||
|
{
|
||||||
|
Size = new Vector2(50)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
osu.Game.Tests/Visual/TestCaseLoaderAnimation.cs
Normal file
115
osu.Game.Tests/Visual/TestCaseLoaderAnimation.cs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Screens;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestCaseLoaderAnimation : OsuTestCase
|
||||||
|
{
|
||||||
|
private TestLoader loader;
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
// required to preload the logo in a headless run (so it doesn't delay the loading itself).
|
||||||
|
Add(new OsuLogo());
|
||||||
|
|
||||||
|
bool logoVisible = false;
|
||||||
|
AddStep("almost instant display", () => Child = loader = new TestLoader(250));
|
||||||
|
AddUntilStep(() =>
|
||||||
|
{
|
||||||
|
logoVisible = loader.Logo?.Alpha > 0;
|
||||||
|
return loader.Logo != null && loader.ScreenLoaded;
|
||||||
|
}, "loaded");
|
||||||
|
AddAssert("logo not visible", () => !logoVisible);
|
||||||
|
|
||||||
|
AddStep("short load", () => Child = loader = new TestLoader(800));
|
||||||
|
AddUntilStep(() =>
|
||||||
|
{
|
||||||
|
logoVisible = loader.Logo?.Alpha > 0;
|
||||||
|
return loader.Logo != null && loader.ScreenLoaded;
|
||||||
|
}, "loaded");
|
||||||
|
AddAssert("logo visible", () => logoVisible);
|
||||||
|
AddUntilStep(() => loader.Logo?.Alpha == 0, "logo gone");
|
||||||
|
|
||||||
|
AddStep("longer load", () => Child = loader = new TestLoader(1400));
|
||||||
|
AddUntilStep(() =>
|
||||||
|
{
|
||||||
|
logoVisible = loader.Logo?.Alpha > 0;
|
||||||
|
return loader.Logo != null && loader.ScreenLoaded;
|
||||||
|
}, "loaded");
|
||||||
|
AddAssert("logo visible", () => logoVisible);
|
||||||
|
AddUntilStep(() => loader.Logo?.Alpha == 0, "logo gone");
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestLoader : Loader
|
||||||
|
{
|
||||||
|
private readonly double delay;
|
||||||
|
|
||||||
|
public OsuLogo Logo;
|
||||||
|
private TestScreen screen;
|
||||||
|
|
||||||
|
public bool ScreenLoaded => screen.IsCurrentScreen;
|
||||||
|
|
||||||
|
public TestLoader(double delay)
|
||||||
|
{
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||||
|
{
|
||||||
|
Logo = logo;
|
||||||
|
base.LogoArriving(logo, resuming);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override OsuScreen CreateLoadableScreen() => screen = new TestScreen();
|
||||||
|
protected override ShaderPrecompiler CreateShaderPrecompiler() => new TestShaderPrecompiler(delay);
|
||||||
|
|
||||||
|
private class TestShaderPrecompiler : ShaderPrecompiler
|
||||||
|
{
|
||||||
|
private readonly double delay;
|
||||||
|
private double startTime;
|
||||||
|
|
||||||
|
public TestShaderPrecompiler(double delay)
|
||||||
|
{
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
startTime = Time.Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool AllLoaded => Time.Current > startTime + delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestScreen : OsuScreen
|
||||||
|
{
|
||||||
|
public TestScreen()
|
||||||
|
{
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.DarkSlateGray,
|
||||||
|
Alpha = 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||||
|
{
|
||||||
|
base.LogoArriving(logo, resuming);
|
||||||
|
Child.FadeInFromZero(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
211
osu.Game.Tests/Visual/TestCaseLounge.cs
Normal file
211
osu.Game.Tests/Visual/TestCaseLounge.cs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Online.Multiplayer;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Screens.Multi.Components;
|
||||||
|
using osu.Game.Screens.Multi.Screens.Lounge;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using OpenTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestCaseLounge : ManualInputManagerTestCase
|
||||||
|
{
|
||||||
|
private TestLounge lounge;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(RulesetStore rulesets)
|
||||||
|
{
|
||||||
|
lounge = new TestLounge();
|
||||||
|
|
||||||
|
Room[] rooms =
|
||||||
|
{
|
||||||
|
new Room
|
||||||
|
{
|
||||||
|
Name = { Value = @"Just Another Room" },
|
||||||
|
Host = { Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } } },
|
||||||
|
Status = { Value = new RoomStatusPlaying() },
|
||||||
|
Availability = { Value = RoomAvailability.Public },
|
||||||
|
Type = { Value = new GameTypeTagTeam() },
|
||||||
|
Beatmap =
|
||||||
|
{
|
||||||
|
Value = new BeatmapInfo
|
||||||
|
{
|
||||||
|
StarDifficulty = 5.65,
|
||||||
|
Ruleset = rulesets.GetRuleset(0),
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Title = @"Sidetracked Day (Short Ver.)",
|
||||||
|
Artist = @"VINXIS",
|
||||||
|
AuthorString = @"Hobbes2",
|
||||||
|
},
|
||||||
|
BeatmapSet = new BeatmapSetInfo
|
||||||
|
{
|
||||||
|
OnlineInfo = new BeatmapSetOnlineInfo
|
||||||
|
{
|
||||||
|
Covers = new BeatmapSetOnlineCovers
|
||||||
|
{
|
||||||
|
Cover = @"https://assets.ppy.sh/beatmaps/767600/covers/cover.jpg?1526243446",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MaxParticipants = { Value = 10 },
|
||||||
|
Participants =
|
||||||
|
{
|
||||||
|
Value = new[]
|
||||||
|
{
|
||||||
|
new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } },
|
||||||
|
new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } },
|
||||||
|
new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } },
|
||||||
|
new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } },
|
||||||
|
new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } },
|
||||||
|
new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Room
|
||||||
|
{
|
||||||
|
Name = { Value = @"Not Just Any Room" },
|
||||||
|
Host = { Value = new User { Username = @"Monstrata", Id = 2706438, Country = new Country { FlagName = @"CA" } } },
|
||||||
|
Status = { Value = new RoomStatusOpen() },
|
||||||
|
Availability = { Value = RoomAvailability.FriendsOnly },
|
||||||
|
Type = { Value = new GameTypeTeamVersus() },
|
||||||
|
Beatmap =
|
||||||
|
{
|
||||||
|
Value = new BeatmapInfo
|
||||||
|
{
|
||||||
|
StarDifficulty = 2.73,
|
||||||
|
Ruleset = rulesets.GetRuleset(0),
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Title = @"lit(var)",
|
||||||
|
Artist = @"kensuke ushio",
|
||||||
|
AuthorString = @"Monstrata",
|
||||||
|
},
|
||||||
|
BeatmapSet = new BeatmapSetInfo
|
||||||
|
{
|
||||||
|
OnlineInfo = new BeatmapSetOnlineInfo
|
||||||
|
{
|
||||||
|
Covers = new BeatmapSetOnlineCovers
|
||||||
|
{
|
||||||
|
Cover = @"https://assets.ppy.sh/beatmaps/623972/covers/cover.jpg?1521167183",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Participants =
|
||||||
|
{
|
||||||
|
Value = new[]
|
||||||
|
{
|
||||||
|
new User { Username = @"Jeby", Id = 3136279, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 3497 } } },
|
||||||
|
new User { Username = @"DualAkira", Id = 5220933, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 643 } } },
|
||||||
|
new User { Username = @"Datenshi Yohane", Id = 7171857, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10555 } } },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Room
|
||||||
|
{
|
||||||
|
Name = { Value = @"room THE FINAL" },
|
||||||
|
Host = { Value = new User { Username = @"Delis", Id = 1603923, Country = new Country { FlagName = @"JP" } } },
|
||||||
|
Status = { Value = new RoomStatusPlaying() },
|
||||||
|
Availability = { Value = RoomAvailability.Public },
|
||||||
|
Type = { Value = new GameTypeTagTeam() },
|
||||||
|
Beatmap =
|
||||||
|
{
|
||||||
|
Value = new BeatmapInfo
|
||||||
|
{
|
||||||
|
StarDifficulty = 4.48,
|
||||||
|
Ruleset = rulesets.GetRuleset(3),
|
||||||
|
Metadata = new BeatmapMetadata
|
||||||
|
{
|
||||||
|
Title = @"ONIGIRI FREEWAY",
|
||||||
|
Artist = @"OISHII",
|
||||||
|
AuthorString = @"Mentholzzz",
|
||||||
|
},
|
||||||
|
BeatmapSet = new BeatmapSetInfo
|
||||||
|
{
|
||||||
|
OnlineInfo = new BeatmapSetOnlineInfo
|
||||||
|
{
|
||||||
|
Covers = new BeatmapSetOnlineCovers
|
||||||
|
{
|
||||||
|
Cover = @"https://assets.ppy.sh/beatmaps/663098/covers/cover.jpg?1521898837",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MaxParticipants = { Value = 30 },
|
||||||
|
Participants =
|
||||||
|
{
|
||||||
|
Value = new[]
|
||||||
|
{
|
||||||
|
new User { Username = @"KizuA", Id = 6510442, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 5372 } } },
|
||||||
|
new User { Username = @"Colored", Id = 827563, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 810 } } },
|
||||||
|
new User { Username = @"Beryl", Id = 3817591, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 10096 } } },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep(@"show", () => Add(lounge));
|
||||||
|
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||||
|
selectAssert(0);
|
||||||
|
AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {});
|
||||||
|
AddAssert(@"no room selected", () => lounge.SelectedRoom == null);
|
||||||
|
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||||
|
selectAssert(1);
|
||||||
|
AddStep(@"open room 1", () => clickRoom(1));
|
||||||
|
AddStep(@"make lounge current", lounge.MakeCurrent);
|
||||||
|
filterAssert(@"THE FINAL", LoungeTab.Public, 1);
|
||||||
|
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||||
|
filterAssert(string.Empty, LoungeTab.Private, 1);
|
||||||
|
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||||
|
filterAssert(@"no matches", LoungeTab.Public, 0);
|
||||||
|
AddStep(@"clear rooms", () => lounge.Rooms = new Room[] {});
|
||||||
|
AddStep(@"set rooms", () => lounge.Rooms = rooms);
|
||||||
|
AddAssert(@"no matches after clear", () => !lounge.ChildRooms.Any());
|
||||||
|
filterAssert(string.Empty, LoungeTab.Public, 2);
|
||||||
|
AddStep(@"exit", lounge.Exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickRoom(int n)
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(lounge.ChildRooms.ElementAt(n));
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectAssert(int n)
|
||||||
|
{
|
||||||
|
AddStep($@"select room {n}", () => clickRoom(n));
|
||||||
|
AddAssert($@"room {n} selected", () => lounge.SelectedRoom == lounge.ChildRooms.ElementAt(n).Room);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterAssert(string filter, LoungeTab tab, int endCount)
|
||||||
|
{
|
||||||
|
AddStep($@"filter '{filter}', {tab}", () => lounge.SetFilter(filter, tab));
|
||||||
|
AddAssert(@"filtered correctly", () => lounge.ChildRooms.Count() == endCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestLounge : Lounge
|
||||||
|
{
|
||||||
|
public IEnumerable<DrawableRoom> ChildRooms => RoomsContainer.Children.Where(r => r.MatchingFilter);
|
||||||
|
public Room SelectedRoom => Inspector.Room;
|
||||||
|
|
||||||
|
public void SetFilter(string filter, LoungeTab tab)
|
||||||
|
{
|
||||||
|
Filter.Search.Current.Value = filter;
|
||||||
|
Filter.Tabs.Current.Value = tab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,8 +39,6 @@ namespace osu.Game.Tests.Visual
|
|||||||
typeof(SpecialSection),
|
typeof(SpecialSection),
|
||||||
};
|
};
|
||||||
|
|
||||||
private const string unranked_suffix = " (Unranked)";
|
|
||||||
|
|
||||||
private RulesetStore rulesets;
|
private RulesetStore rulesets;
|
||||||
private ModDisplay modDisplay;
|
private ModDisplay modDisplay;
|
||||||
private TestModSelectOverlay modSelect;
|
private TestModSelectOverlay modSelect;
|
||||||
@ -121,7 +119,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private void testManiaMods(ManiaRuleset ruleset)
|
private void testManiaMods(ManiaRuleset ruleset)
|
||||||
{
|
{
|
||||||
testMultiplierTextUnranked(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom));
|
testRankedText(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testSingleMod(Mod mod)
|
private void testSingleMod(Mod mod)
|
||||||
@ -198,13 +196,16 @@ namespace osu.Game.Tests.Visual
|
|||||||
checkLabelColor(Color4.White);
|
checkLabelColor(Color4.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testMultiplierTextUnranked(Mod mod)
|
private void testRankedText(Mod mod)
|
||||||
{
|
{
|
||||||
AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
AddWaitStep(1, "wait for fade");
|
||||||
|
AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||||
selectNext(mod);
|
selectNext(mod);
|
||||||
AddAssert("check for unranked", () => modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
AddWaitStep(1, "wait for fade");
|
||||||
|
AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0);
|
||||||
selectPrevious(mod);
|
selectPrevious(mod);
|
||||||
AddAssert("check for ranked", () => !modSelect.MultiplierLabel.Text.EndsWith(unranked_suffix));
|
AddWaitStep(1, "wait for fade");
|
||||||
|
AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1));
|
private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1));
|
||||||
@ -240,6 +241,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
}
|
}
|
||||||
|
|
||||||
public new OsuSpriteText MultiplierLabel => base.MultiplierLabel;
|
public new OsuSpriteText MultiplierLabel => base.MultiplierLabel;
|
||||||
|
public new OsuSpriteText UnrankedLabel => base.UnrankedLabel;
|
||||||
public new TriangleButton DeselectAllButton => base.DeselectAllButton;
|
public new TriangleButton DeselectAllButton => base.DeselectAllButton;
|
||||||
|
|
||||||
public new Color4 LowMultiplierColour => base.LowMultiplierColour;
|
public new Color4 LowMultiplierColour => base.LowMultiplierColour;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Screens.Multi;
|
using osu.Game.Screens.Multi;
|
||||||
using osu.Game.Screens.Multi.Screens;
|
using osu.Game.Screens.Multi.Screens.Lounge;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
{
|
{
|
||||||
@ -13,14 +13,14 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public TestCaseMultiHeader()
|
public TestCaseMultiHeader()
|
||||||
{
|
{
|
||||||
Lobby lobby;
|
Lounge lounge;
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
lobby = new Lobby
|
lounge = new Lounge
|
||||||
{
|
{
|
||||||
Padding = new MarginPadding { Top = Header.HEIGHT },
|
Padding = new MarginPadding { Top = Header.HEIGHT },
|
||||||
},
|
},
|
||||||
new Header(lobby),
|
new Header(lounge),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
osu.Game.Tests/Visual/TestCaseQuitButton.cs
Normal file
53
osu.Game.Tests/Visual/TestCaseQuitButton.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
[Description("'Hold to Quit' UI element")]
|
||||||
|
public class TestCaseQuitButton : ManualInputManagerTestCase
|
||||||
|
{
|
||||||
|
private bool exitAction;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
QuitButton quitButton;
|
||||||
|
|
||||||
|
Add(quitButton = new QuitButton
|
||||||
|
{
|
||||||
|
Origin = Anchor.BottomRight,
|
||||||
|
Anchor = Anchor.BottomRight,
|
||||||
|
Action = () => exitAction = true
|
||||||
|
});
|
||||||
|
|
||||||
|
var text = quitButton.Children.OfType<SpriteText>().First();
|
||||||
|
|
||||||
|
AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(quitButton));
|
||||||
|
AddUntilStep(() => text.IsPresent && !exitAction, "Text visible");
|
||||||
|
AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One));
|
||||||
|
AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible");
|
||||||
|
|
||||||
|
AddStep("Trigger exit action", () =>
|
||||||
|
{
|
||||||
|
exitAction = false;
|
||||||
|
InputManager.MoveMouseTo(quitButton);
|
||||||
|
InputManager.PressButton(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Early release", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||||
|
AddAssert("action not triggered", () => !exitAction);
|
||||||
|
|
||||||
|
AddStep("Trigger exit action", () => InputManager.PressButton(MouseButton.Left));
|
||||||
|
AddUntilStep(() => exitAction, $"{nameof(quitButton.Action)} was triggered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -84,12 +84,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private abstract class TestScreen : OsuScreen
|
private abstract class TestScreen : OsuScreen
|
||||||
{
|
{
|
||||||
protected abstract string Title { get; }
|
|
||||||
protected abstract string NextTitle { get; }
|
protected abstract string NextTitle { get; }
|
||||||
protected abstract TestScreen CreateNextScreen();
|
protected abstract TestScreen CreateNextScreen();
|
||||||
|
|
||||||
public override string ToString() => Title;
|
|
||||||
|
|
||||||
public TestScreen PushNext()
|
public TestScreen PushNext()
|
||||||
{
|
{
|
||||||
TestScreen screen = CreateNextScreen();
|
TestScreen screen = CreateNextScreen();
|
||||||
@ -130,14 +127,14 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private class TestScreenOne : TestScreen
|
private class TestScreenOne : TestScreen
|
||||||
{
|
{
|
||||||
protected override string Title => @"Screen One";
|
public override string Title => @"Screen One";
|
||||||
protected override string NextTitle => @"Two";
|
protected override string NextTitle => @"Two";
|
||||||
protected override TestScreen CreateNextScreen() => new TestScreenTwo();
|
protected override TestScreen CreateNextScreen() => new TestScreenTwo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestScreenTwo : TestScreen
|
private class TestScreenTwo : TestScreen
|
||||||
{
|
{
|
||||||
protected override string Title => @"Screen Two";
|
public override string Title => @"Screen Two";
|
||||||
protected override string NextTitle => @"One";
|
protected override string NextTitle => @"One";
|
||||||
protected override TestScreen CreateNextScreen() => new TestScreenOne();
|
protected override TestScreen CreateNextScreen() => new TestScreenOne();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\osu.TestProject.props" />
|
<Import Project="..\osu.TestProject.props" />
|
||||||
<PropertyGroup Label="Project">
|
<PropertyGroup Label="Project">
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
|
<TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Project References">
|
<ItemGroup Label="Project References">
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />
|
||||||
|
@ -81,7 +81,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
protected override void Populate(BeatmapSetInfo model, ArchiveReader archive)
|
protected override void Populate(BeatmapSetInfo model, ArchiveReader archive)
|
||||||
{
|
{
|
||||||
model.Beatmaps = createBeatmapDifficulties(archive);
|
model.Beatmaps = createBeatmapDifficulties(model, archive);
|
||||||
|
|
||||||
// remove metadata from difficulties where it matches the set
|
// remove metadata from difficulties where it matches the set
|
||||||
foreach (BeatmapInfo b in model.Beatmaps)
|
foreach (BeatmapInfo b in model.Beatmaps)
|
||||||
@ -107,6 +107,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
Delete(existingOnlineId);
|
Delete(existingOnlineId);
|
||||||
beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID);
|
beatmaps.PurgeDeletable(s => s.ID == existingOnlineId.ID);
|
||||||
|
Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({model.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
if (error is OperationCanceledException) return;
|
if (error is OperationCanceledException) return;
|
||||||
|
|
||||||
downloadNotification.State = ProgressNotificationState.Completed;
|
downloadNotification.State = ProgressNotificationState.Cancelled;
|
||||||
Logger.Error(error, "Beatmap download failed!");
|
Logger.Error(error, "Beatmap download failed!");
|
||||||
currentDownloads.Remove(request);
|
currentDownloads.Remove(request);
|
||||||
};
|
};
|
||||||
@ -241,7 +242,13 @@ namespace osu.Game.Beatmaps
|
|||||||
/// Returns a list of all usable <see cref="BeatmapSetInfo"/>s.
|
/// Returns a list of all usable <see cref="BeatmapSetInfo"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of available <see cref="BeatmapSetInfo"/>.</returns>
|
/// <returns>A list of available <see cref="BeatmapSetInfo"/>.</returns>
|
||||||
public List<BeatmapSetInfo> GetAllUsableBeatmapSets() => beatmaps.ConsumableItems.Where(s => !s.DeletePending && !s.Protected).ToList();
|
public List<BeatmapSetInfo> GetAllUsableBeatmapSets() => GetAllUsableBeatmapSetsEnumerable().ToList();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all usable <see cref="BeatmapSetInfo"/>s.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of available <see cref="BeatmapSetInfo"/>.</returns>
|
||||||
|
public IQueryable<BeatmapSetInfo> GetAllUsableBeatmapSetsEnumerable() => beatmaps.ConsumableItems.Where(s => !s.DeletePending && !s.Protected);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a lookup query on available <see cref="BeatmapSetInfo"/>s.
|
/// Perform a lookup query on available <see cref="BeatmapSetInfo"/>s.
|
||||||
@ -303,7 +310,7 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
// let's make sure there are actually .osu files to import.
|
// let's make sure there are actually .osu files to import.
|
||||||
string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu"));
|
string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu"));
|
||||||
if (string.IsNullOrEmpty(mapName)) throw new InvalidOperationException("No beatmap files found in the map folder.");
|
if (string.IsNullOrEmpty(mapName)) throw new InvalidOperationException("No beatmap files found in this beatmap archive.");
|
||||||
|
|
||||||
BeatmapMetadata metadata;
|
BeatmapMetadata metadata;
|
||||||
using (var stream = new StreamReader(reader.GetStream(mapName)))
|
using (var stream = new StreamReader(reader.GetStream(mapName)))
|
||||||
@ -321,7 +328,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create all required <see cref="BeatmapInfo"/>s for the provided archive.
|
/// Create all required <see cref="BeatmapInfo"/>s for the provided archive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<BeatmapInfo> createBeatmapDifficulties(ArchiveReader reader)
|
private List<BeatmapInfo> createBeatmapDifficulties(BeatmapSetInfo model, ArchiveReader reader)
|
||||||
{
|
{
|
||||||
var beatmapInfos = new List<BeatmapInfo>();
|
var beatmapInfos = new List<BeatmapInfo>();
|
||||||
|
|
||||||
@ -341,6 +348,14 @@ namespace osu.Game.Beatmaps
|
|||||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
||||||
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
|
||||||
|
|
||||||
|
// ensure we have the same online set ID as the set itself.
|
||||||
|
beatmap.BeatmapInfo.OnlineBeatmapSetID = model.OnlineBeatmapSetID;
|
||||||
|
beatmap.BeatmapInfo.Metadata.OnlineBeatmapSetID = model.OnlineBeatmapSetID;
|
||||||
|
|
||||||
|
// check that no existing beatmap exists that is imported with the same online beatmap ID. if so, give it precedence.
|
||||||
|
if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue && QueryBeatmap(b => b.OnlineBeatmapID.Value == beatmap.BeatmapInfo.OnlineBeatmapID.Value) != null)
|
||||||
|
beatmap.BeatmapInfo.OnlineBeatmapID = null;
|
||||||
|
|
||||||
RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
||||||
|
|
||||||
beatmap.BeatmapInfo.Ruleset = ruleset;
|
beatmap.BeatmapInfo.Ruleset = ruleset;
|
||||||
|
@ -36,6 +36,11 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasVideo { get; set; }
|
public bool HasVideo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this beatmap set has a storyboard.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasStoryboard { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The different sizes of cover art for this beatmap set.
|
/// The different sizes of cover art for this beatmap set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
79
osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs
Normal file
79
osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Beatmaps.Drawables
|
||||||
|
{
|
||||||
|
public class UpdateableBeatmapSetCover : Container
|
||||||
|
{
|
||||||
|
private Drawable displayedCover;
|
||||||
|
|
||||||
|
private BeatmapSetInfo beatmapSet;
|
||||||
|
public BeatmapSetInfo BeatmapSet
|
||||||
|
{
|
||||||
|
get { return beatmapSet; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == beatmapSet) return;
|
||||||
|
beatmapSet = value;
|
||||||
|
|
||||||
|
if (IsLoaded)
|
||||||
|
updateCover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BeatmapSetCoverType coverType = BeatmapSetCoverType.Cover;
|
||||||
|
public BeatmapSetCoverType CoverType
|
||||||
|
{
|
||||||
|
get { return coverType; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == coverType) return;
|
||||||
|
coverType = value;
|
||||||
|
|
||||||
|
if (IsLoaded)
|
||||||
|
updateCover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateableBeatmapSetCover()
|
||||||
|
{
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
updateCover();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCover()
|
||||||
|
{
|
||||||
|
displayedCover?.FadeOut(400);
|
||||||
|
displayedCover?.Expire();
|
||||||
|
displayedCover = null;
|
||||||
|
|
||||||
|
if (beatmapSet != null)
|
||||||
|
{
|
||||||
|
Add(displayedCover = new DelayedLoadWrapper(
|
||||||
|
new BeatmapSetCover(beatmapSet, coverType)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fill,
|
||||||
|
OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -56,13 +56,49 @@ namespace osu.Game.Database
|
|||||||
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||||
private ArchiveImportIPCChannel ipc;
|
private ArchiveImportIPCChannel ipc;
|
||||||
|
|
||||||
|
private readonly List<Action> cachedEvents = new List<Action>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows delaying of outwards events until an operation is confirmed (at a database level).
|
||||||
|
/// </summary>
|
||||||
|
private bool delayingEvents;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Begin delaying outwards events.
|
||||||
|
/// </summary>
|
||||||
|
private void delayEvents() => delayingEvents = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flush delayed events and disable delaying.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="perform">Whether the flushed events should be performed.</param>
|
||||||
|
private void flushEvents(bool perform)
|
||||||
|
{
|
||||||
|
if (perform)
|
||||||
|
{
|
||||||
|
foreach (var a in cachedEvents)
|
||||||
|
a.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedEvents.Clear();
|
||||||
|
delayingEvents = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleEvent(Action a)
|
||||||
|
{
|
||||||
|
if (delayingEvents)
|
||||||
|
cachedEvents.Add(a);
|
||||||
|
else
|
||||||
|
a.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStore<TModel> modelStore, IIpcHost importHost = null)
|
protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStore<TModel> modelStore, IIpcHost importHost = null)
|
||||||
{
|
{
|
||||||
ContextFactory = contextFactory;
|
ContextFactory = contextFactory;
|
||||||
|
|
||||||
ModelStore = modelStore;
|
ModelStore = modelStore;
|
||||||
ModelStore.ItemAdded += s => ItemAdded?.Invoke(s);
|
ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s));
|
||||||
ModelStore.ItemRemoved += s => ItemRemoved?.Invoke(s);
|
ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s));
|
||||||
|
|
||||||
Files = new FileStore(contextFactory, storage);
|
Files = new FileStore(contextFactory, storage);
|
||||||
|
|
||||||
@ -138,24 +174,56 @@ namespace osu.Game.Database
|
|||||||
/// <param name="archive">The archive to be imported.</param>
|
/// <param name="archive">The archive to be imported.</param>
|
||||||
public TModel Import(ArchiveReader archive)
|
public TModel Import(ArchiveReader archive)
|
||||||
{
|
{
|
||||||
using (ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes.
|
TModel item = null;
|
||||||
|
delayEvents();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// create a new model (don't yet add to database)
|
using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes.
|
||||||
var item = CreateModel(archive);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}");
|
||||||
|
|
||||||
var existing = CheckForExisting(item);
|
// create a new model (don't yet add to database)
|
||||||
|
item = CreateModel(archive);
|
||||||
|
|
||||||
if (existing != null) return existing;
|
var existing = CheckForExisting(item);
|
||||||
|
|
||||||
item.Files = createFileInfos(archive, Files);
|
if (existing != null)
|
||||||
|
{
|
||||||
|
Logger.Log($"Found existing {typeof(TModel)} for {archive.Name} (ID {existing.ID}). Skipping import.", LoggingTarget.Database);
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
Populate(item, archive);
|
item.Files = createFileInfos(archive, Files);
|
||||||
|
|
||||||
// import to store
|
Populate(item, archive);
|
||||||
ModelStore.Add(item);
|
|
||||||
|
|
||||||
return item;
|
// import to store
|
||||||
|
ModelStore.Add(item);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
write.Errors.Add(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Log($"Import of {archive.Name} successfully completed!", LoggingTarget.Database);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, $"Import of {archive.Name} failed and has been rolled back.", LoggingTarget.Database);
|
||||||
|
item = null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// we only want to flush events after we've confirmed the write context didn't have any errors.
|
||||||
|
flushEvents(item != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -178,12 +246,8 @@ namespace osu.Game.Database
|
|||||||
/// <param name="item">The item to delete.</param>
|
/// <param name="item">The item to delete.</param>
|
||||||
public void Delete(TModel item)
|
public void Delete(TModel item)
|
||||||
{
|
{
|
||||||
using (var usage = ContextFactory.GetForWrite())
|
using (ContextFactory.GetForWrite())
|
||||||
{
|
{
|
||||||
var context = usage.Context;
|
|
||||||
|
|
||||||
context.ChangeTracker.AutoDetectChangesEnabled = false;
|
|
||||||
|
|
||||||
// re-fetch the model on the import context.
|
// re-fetch the model on the import context.
|
||||||
var foundModel = queryModel().Include(s => s.Files).ThenInclude(f => f.FileInfo).First(s => s.ID == item.ID);
|
var foundModel = queryModel().Include(s => s.Files).ThenInclude(f => f.FileInfo).First(s => s.ID == item.ID);
|
||||||
|
|
||||||
@ -191,8 +255,6 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
if (ModelStore.Delete(foundModel))
|
if (ModelStore.Delete(foundModel))
|
||||||
Files.Dereference(foundModel.Files.Select(f => f.FileInfo).ToArray());
|
Files.Dereference(foundModel.Files.Select(f => f.FileInfo).ToArray());
|
||||||
|
|
||||||
context.ChangeTracker.AutoDetectChangesEnabled = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
@ -17,8 +19,12 @@ namespace osu.Game.Database
|
|||||||
private readonly object writeLock = new object();
|
private readonly object writeLock = new object();
|
||||||
|
|
||||||
private bool currentWriteDidWrite;
|
private bool currentWriteDidWrite;
|
||||||
|
private bool currentWriteDidError;
|
||||||
|
|
||||||
private int currentWriteUsages;
|
private int currentWriteUsages;
|
||||||
|
|
||||||
|
private IDbContextTransaction currentWriteTransaction;
|
||||||
|
|
||||||
public DatabaseContextFactory(GameHost host)
|
public DatabaseContextFactory(GameHost host)
|
||||||
{
|
{
|
||||||
this.host = host;
|
this.host = host;
|
||||||
@ -35,14 +41,25 @@ namespace osu.Game.Database
|
|||||||
/// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context).
|
/// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context).
|
||||||
/// This method may block if a write is already active on a different thread.
|
/// This method may block if a write is already active on a different thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="withTransaction">Whether to start a transaction for this write.</param>
|
||||||
/// <returns>A usage containing a usable context.</returns>
|
/// <returns>A usage containing a usable context.</returns>
|
||||||
public DatabaseWriteUsage GetForWrite()
|
public DatabaseWriteUsage GetForWrite(bool withTransaction = true)
|
||||||
{
|
{
|
||||||
Monitor.Enter(writeLock);
|
Monitor.Enter(writeLock);
|
||||||
|
|
||||||
|
if (currentWriteTransaction == null && withTransaction)
|
||||||
|
{
|
||||||
|
// this mitigates the fact that changes on tracked entities will not be rolled back with the transaction by ensuring write operations are always executed in isolated contexts.
|
||||||
|
// if this results in sub-optimal efficiency, we may need to look into removing Database-level transactions in favour of running SaveChanges where we currently commit the transaction.
|
||||||
|
if (threadContexts.IsValueCreated)
|
||||||
|
recycleThreadContexts();
|
||||||
|
|
||||||
|
currentWriteTransaction = threadContexts.Value.Database.BeginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
Interlocked.Increment(ref currentWriteUsages);
|
Interlocked.Increment(ref currentWriteUsages);
|
||||||
|
|
||||||
return new DatabaseWriteUsage(threadContexts.Value, usageCompleted);
|
return new DatabaseWriteUsage(threadContexts.Value, usageCompleted) { IsTransactionLeader = currentWriteTransaction != null && currentWriteUsages == 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
private void usageCompleted(DatabaseWriteUsage usage)
|
private void usageCompleted(DatabaseWriteUsage usage)
|
||||||
@ -52,18 +69,27 @@ namespace osu.Game.Database
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
currentWriteDidWrite |= usage.PerformedWrite;
|
currentWriteDidWrite |= usage.PerformedWrite;
|
||||||
|
currentWriteDidError |= usage.Errors.Any();
|
||||||
|
|
||||||
if (usages > 0) return;
|
if (usages == 0)
|
||||||
|
|
||||||
if (currentWriteDidWrite)
|
|
||||||
{
|
{
|
||||||
// explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged).
|
if (currentWriteDidError)
|
||||||
usage.Context.Dispose();
|
currentWriteTransaction?.Rollback();
|
||||||
|
else
|
||||||
|
currentWriteTransaction?.Commit();
|
||||||
|
|
||||||
|
if (currentWriteDidWrite || currentWriteDidError)
|
||||||
|
{
|
||||||
|
// explicitly dispose to ensure any outstanding flushes happen as soon as possible (and underlying resources are purged).
|
||||||
|
usage.Context.Dispose();
|
||||||
|
|
||||||
|
// once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches.
|
||||||
|
recycleThreadContexts();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWriteTransaction = null;
|
||||||
currentWriteDidWrite = false;
|
currentWriteDidWrite = false;
|
||||||
|
currentWriteDidError = false;
|
||||||
// once all writes are complete, we want to refresh thread-specific contexts to make sure they don't have stale local caches.
|
|
||||||
recycleThreadContexts();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -2,34 +2,50 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
public class DatabaseWriteUsage : IDisposable
|
public class DatabaseWriteUsage : IDisposable
|
||||||
{
|
{
|
||||||
public readonly OsuDbContext Context;
|
public readonly OsuDbContext Context;
|
||||||
private readonly IDbContextTransaction transaction;
|
|
||||||
private readonly Action<DatabaseWriteUsage> usageCompleted;
|
private readonly Action<DatabaseWriteUsage> usageCompleted;
|
||||||
|
|
||||||
public DatabaseWriteUsage(OsuDbContext context, Action<DatabaseWriteUsage> onCompleted)
|
public DatabaseWriteUsage(OsuDbContext context, Action<DatabaseWriteUsage> onCompleted)
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
transaction = Context.BeginTransaction();
|
|
||||||
usageCompleted = onCompleted;
|
usageCompleted = onCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PerformedWrite { get; private set; }
|
public bool PerformedWrite { get; private set; }
|
||||||
|
|
||||||
private bool isDisposed;
|
private bool isDisposed;
|
||||||
|
public List<Exception> Errors = new List<Exception>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this write usage will commit a transaction on completion.
|
||||||
|
/// If false, there is a parent usage responsible for transaction commit.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTransactionLeader = false;
|
||||||
|
|
||||||
protected void Dispose(bool disposing)
|
protected void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (isDisposed) return;
|
if (isDisposed) return;
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
|
|
||||||
PerformedWrite |= Context.SaveChanges(transaction) > 0;
|
try
|
||||||
usageCompleted?.Invoke(this);
|
{
|
||||||
|
PerformedWrite |= Context.SaveChanges() > 0;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Errors.Add(e);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
usageCompleted?.Invoke(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -14,7 +14,8 @@ namespace osu.Game.Database
|
|||||||
/// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context).
|
/// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context).
|
||||||
/// This method may block if a write is already active on a different thread.
|
/// This method may block if a write is already active on a different thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="withTransaction">Whether to start a transaction for this write.</param>
|
||||||
/// <returns>A usage containing a usable context.</returns>
|
/// <returns>A usage containing a usable context.</returns>
|
||||||
DatabaseWriteUsage GetForWrite();
|
DatabaseWriteUsage GetForWrite(bool withTransaction = true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,11 +50,10 @@ namespace osu.Game.Database
|
|||||||
/// <param name="item">The item to update.</param>
|
/// <param name="item">The item to update.</param>
|
||||||
public void Update(T item)
|
public void Update(T item)
|
||||||
{
|
{
|
||||||
ItemRemoved?.Invoke(item);
|
|
||||||
|
|
||||||
using (var usage = ContextFactory.GetForWrite())
|
using (var usage = ContextFactory.GetForWrite())
|
||||||
usage.Context.Update(item);
|
usage.Context.Update(item);
|
||||||
|
|
||||||
|
ItemRemoved?.Invoke(item);
|
||||||
ItemAdded?.Invoke(item);
|
ItemAdded?.Invoke(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
@ -83,8 +82,8 @@ namespace osu.Game.Database
|
|||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.OnlineBeatmapID).IsUnique();
|
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.OnlineBeatmapID).IsUnique();
|
||||||
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.MD5Hash).IsUnique();
|
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.MD5Hash);
|
||||||
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.Hash).IsUnique();
|
modelBuilder.Entity<BeatmapInfo>().HasIndex(b => b.Hash);
|
||||||
|
|
||||||
modelBuilder.Entity<BeatmapSetInfo>().HasIndex(b => b.OnlineBeatmapSetID).IsUnique();
|
modelBuilder.Entity<BeatmapSetInfo>().HasIndex(b => b.OnlineBeatmapSetID).IsUnique();
|
||||||
modelBuilder.Entity<BeatmapSetInfo>().HasIndex(b => b.DeletePending);
|
modelBuilder.Entity<BeatmapSetInfo>().HasIndex(b => b.DeletePending);
|
||||||
@ -104,19 +103,6 @@ namespace osu.Game.Database
|
|||||||
modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty);
|
modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDbContextTransaction BeginTransaction()
|
|
||||||
{
|
|
||||||
// return Database.BeginTransaction();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int SaveChanges(IDbContextTransaction transaction = null)
|
|
||||||
{
|
|
||||||
var ret = base.SaveChanges();
|
|
||||||
if (ret > 0) transaction?.Commit();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OsuDbLoggerFactory : ILoggerFactory
|
private class OsuDbLoggerFactory : ILoggerFactory
|
||||||
{
|
{
|
||||||
#region Disposal
|
#region Disposal
|
||||||
|
@ -14,6 +14,6 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
public OsuDbContext Get() => context;
|
public OsuDbContext Get() => context;
|
||||||
|
|
||||||
public DatabaseWriteUsage GetForWrite() => new DatabaseWriteUsage(context, null);
|
public DatabaseWriteUsage GetForWrite(bool withTransaction = true) => new DatabaseWriteUsage(context, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
52
osu.Game/Graphics/Containers/HoldToConfirmContainer.cs
Normal file
52
osu.Game/Graphics/Containers/HoldToConfirmContainer.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
public abstract class HoldToConfirmContainer : Container
|
||||||
|
{
|
||||||
|
public Action Action;
|
||||||
|
|
||||||
|
private const int activate_delay = 400;
|
||||||
|
private const int fadeout_delay = 200;
|
||||||
|
|
||||||
|
private bool fired;
|
||||||
|
private bool confirming;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the overlay should be allowed to return from a fired state.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual bool AllowMultipleFires => false;
|
||||||
|
|
||||||
|
public Bindable<double> Progress = new BindableDouble();
|
||||||
|
|
||||||
|
protected void BeginConfirm()
|
||||||
|
{
|
||||||
|
if (confirming || !AllowMultipleFires && fired) return;
|
||||||
|
|
||||||
|
confirming = true;
|
||||||
|
|
||||||
|
this.TransformBindableTo(Progress, 1, activate_delay * (1 - Progress.Value), Easing.Out).OnComplete(_ => Confirm());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Confirm()
|
||||||
|
{
|
||||||
|
Action?.Invoke();
|
||||||
|
fired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AbortConfirm()
|
||||||
|
{
|
||||||
|
if (!AllowMultipleFires && fired) return;
|
||||||
|
|
||||||
|
confirming = false;
|
||||||
|
|
||||||
|
this.TransformBindableTo(Progress, 0, fadeout_delay, Easing.Out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using osu.Framework.Audio.Sample;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers
|
namespace osu.Game.Graphics.Containers
|
||||||
{
|
{
|
||||||
@ -15,9 +16,14 @@ namespace osu.Game.Graphics.Containers
|
|||||||
private SampleChannel samplePopIn;
|
private SampleChannel samplePopIn;
|
||||||
private SampleChannel samplePopOut;
|
private SampleChannel samplePopOut;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
private readonly BindableBool allowOpeningOverlays = new BindableBool(true);
|
||||||
private void load(AudioManager audio)
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(OsuGame osuGame, AudioManager audio)
|
||||||
{
|
{
|
||||||
|
if (osuGame != null)
|
||||||
|
allowOpeningOverlays.BindTo(osuGame.AllowOpeningOverlays);
|
||||||
|
|
||||||
samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in");
|
samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in");
|
||||||
samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out");
|
samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out");
|
||||||
|
|
||||||
@ -46,15 +52,20 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
private void onStateChanged(Visibility visibility)
|
private void onStateChanged(Visibility visibility)
|
||||||
{
|
{
|
||||||
switch (visibility)
|
if (allowOpeningOverlays)
|
||||||
{
|
{
|
||||||
case Visibility.Visible:
|
switch (visibility)
|
||||||
samplePopIn?.Play();
|
{
|
||||||
break;
|
case Visibility.Visible:
|
||||||
case Visibility.Hidden:
|
samplePopIn?.Play();
|
||||||
samplePopOut?.Play();
|
break;
|
||||||
break;
|
case Visibility.Hidden:
|
||||||
|
samplePopOut?.Play();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
State = Visibility.Hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container which provides a <see cref="MenuCursor"/> which can be overridden by hovered <see cref="Drawable"/>s.
|
/// A container which provides a <see cref="MenuCursor"/> which can be overridden by hovered <see cref="Drawable"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CursorOverrideContainer : Container, IProvideCursor
|
public class MenuCursorContainer : Container, IProvideCursor
|
||||||
{
|
{
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private readonly Container content;
|
private readonly Container content;
|
||||||
@ -25,7 +25,7 @@ namespace osu.Game.Graphics.Cursor
|
|||||||
public CursorContainer Cursor { get; }
|
public CursorContainer Cursor { get; }
|
||||||
public bool ProvidingUserCursor => true;
|
public bool ProvidingUserCursor => true;
|
||||||
|
|
||||||
public CursorOverrideContainer()
|
public MenuCursorContainer()
|
||||||
{
|
{
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new Drawable[]
|
||||||
{
|
{
|
63
osu.Game/Graphics/UserInterface/ExternalLinkButton.cs
Normal file
63
osu.Game/Graphics/UserInterface/ExternalLinkButton.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
public class ExternalLinkButton : CompositeDrawable, IHasTooltip
|
||||||
|
{
|
||||||
|
public string Link { get; set; }
|
||||||
|
|
||||||
|
private Color4 hoverColour;
|
||||||
|
|
||||||
|
public ExternalLinkButton(string link = null)
|
||||||
|
{
|
||||||
|
Link = link;
|
||||||
|
Size = new Vector2(12);
|
||||||
|
InternalChild = new SpriteIcon
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.fa_external_link,
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
hoverColour = colours.Yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(InputState state)
|
||||||
|
{
|
||||||
|
InternalChild.FadeColour(hoverColour, 500, Easing.OutQuint);
|
||||||
|
return base.OnHover(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(InputState state)
|
||||||
|
{
|
||||||
|
InternalChild.FadeColour(Color4.White, 500, Easing.OutQuint);
|
||||||
|
base.OnHoverLost(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnClick(InputState state)
|
||||||
|
{
|
||||||
|
if(Link != null)
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = Link,
|
||||||
|
UseShellExecute = true //see https://github.com/dotnet/corefx/issues/10361
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TooltipText => "View in browser";
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -157,7 +158,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Text = (value as Enum)?.GetDescription() ?? value.ToString(),
|
Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetDescription() ?? value.ToString(),
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
Font = @"Exo2.0-Bold", // Font should only turn bold when active?
|
Font = @"Exo2.0-Bold", // Font should only turn bold when active?
|
||||||
},
|
},
|
||||||
|
377
osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs
generated
Normal file
377
osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs
generated
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace osu.Game.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(OsuDbContext))]
|
||||||
|
[Migration("20180529055154_RemoveUniqueHashConstraints")]
|
||||||
|
partial class RemoveUniqueHashConstraints
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.0.3-rtm-10026");
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<float>("ApproachRate");
|
||||||
|
|
||||||
|
b.Property<float>("CircleSize");
|
||||||
|
|
||||||
|
b.Property<float>("DrainRate");
|
||||||
|
|
||||||
|
b.Property<float>("OverallDifficulty");
|
||||||
|
|
||||||
|
b.Property<double>("SliderMultiplier");
|
||||||
|
|
||||||
|
b.Property<double>("SliderTickRate");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.ToTable("BeatmapDifficulty");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AudioLeadIn");
|
||||||
|
|
||||||
|
b.Property<int>("BaseDifficultyID");
|
||||||
|
|
||||||
|
b.Property<int>("BeatDivisor");
|
||||||
|
|
||||||
|
b.Property<int>("BeatmapSetInfoID");
|
||||||
|
|
||||||
|
b.Property<bool>("Countdown");
|
||||||
|
|
||||||
|
b.Property<double>("DistanceSpacing");
|
||||||
|
|
||||||
|
b.Property<int>("GridSize");
|
||||||
|
|
||||||
|
b.Property<string>("Hash");
|
||||||
|
|
||||||
|
b.Property<bool>("Hidden");
|
||||||
|
|
||||||
|
b.Property<bool>("LetterboxInBreaks");
|
||||||
|
|
||||||
|
b.Property<string>("MD5Hash");
|
||||||
|
|
||||||
|
b.Property<int?>("MetadataID");
|
||||||
|
|
||||||
|
b.Property<int?>("OnlineBeatmapID");
|
||||||
|
|
||||||
|
b.Property<string>("Path");
|
||||||
|
|
||||||
|
b.Property<int>("RulesetID");
|
||||||
|
|
||||||
|
b.Property<bool>("SpecialStyle");
|
||||||
|
|
||||||
|
b.Property<float>("StackLeniency");
|
||||||
|
|
||||||
|
b.Property<double>("StarDifficulty");
|
||||||
|
|
||||||
|
b.Property<string>("StoredBookmarks");
|
||||||
|
|
||||||
|
b.Property<double>("TimelineZoom");
|
||||||
|
|
||||||
|
b.Property<string>("Version");
|
||||||
|
|
||||||
|
b.Property<bool>("WidescreenStoryboard");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("BaseDifficultyID");
|
||||||
|
|
||||||
|
b.HasIndex("BeatmapSetInfoID");
|
||||||
|
|
||||||
|
b.HasIndex("Hash");
|
||||||
|
|
||||||
|
b.HasIndex("MD5Hash");
|
||||||
|
|
||||||
|
b.HasIndex("MetadataID");
|
||||||
|
|
||||||
|
b.HasIndex("OnlineBeatmapID")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("RulesetID");
|
||||||
|
|
||||||
|
b.ToTable("BeatmapInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Artist");
|
||||||
|
|
||||||
|
b.Property<string>("ArtistUnicode");
|
||||||
|
|
||||||
|
b.Property<string>("AudioFile");
|
||||||
|
|
||||||
|
b.Property<string>("AuthorString")
|
||||||
|
.HasColumnName("Author");
|
||||||
|
|
||||||
|
b.Property<string>("BackgroundFile");
|
||||||
|
|
||||||
|
b.Property<int>("PreviewTime");
|
||||||
|
|
||||||
|
b.Property<string>("Source");
|
||||||
|
|
||||||
|
b.Property<string>("Tags");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TitleUnicode");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.ToTable("BeatmapMetadata");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("BeatmapSetInfoID");
|
||||||
|
|
||||||
|
b.Property<int>("FileInfoID");
|
||||||
|
|
||||||
|
b.Property<string>("Filename")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("BeatmapSetInfoID");
|
||||||
|
|
||||||
|
b.HasIndex("FileInfoID");
|
||||||
|
|
||||||
|
b.ToTable("BeatmapSetFileInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("DeletePending");
|
||||||
|
|
||||||
|
b.Property<string>("Hash");
|
||||||
|
|
||||||
|
b.Property<int?>("MetadataID");
|
||||||
|
|
||||||
|
b.Property<int?>("OnlineBeatmapSetID");
|
||||||
|
|
||||||
|
b.Property<bool>("Protected");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("DeletePending");
|
||||||
|
|
||||||
|
b.HasIndex("Hash")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("MetadataID");
|
||||||
|
|
||||||
|
b.HasIndex("OnlineBeatmapSetID")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("BeatmapSetInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("IntKey")
|
||||||
|
.HasColumnName("Key");
|
||||||
|
|
||||||
|
b.Property<int?>("RulesetID");
|
||||||
|
|
||||||
|
b.Property<string>("StringValue")
|
||||||
|
.HasColumnName("Value");
|
||||||
|
|
||||||
|
b.Property<int?>("Variant");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("RulesetID", "Variant");
|
||||||
|
|
||||||
|
b.ToTable("Settings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("IntAction")
|
||||||
|
.HasColumnName("Action");
|
||||||
|
|
||||||
|
b.Property<string>("KeysString")
|
||||||
|
.HasColumnName("Keys");
|
||||||
|
|
||||||
|
b.Property<int?>("RulesetID");
|
||||||
|
|
||||||
|
b.Property<int?>("Variant");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("IntAction");
|
||||||
|
|
||||||
|
b.HasIndex("RulesetID", "Variant");
|
||||||
|
|
||||||
|
b.ToTable("KeyBinding");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Hash");
|
||||||
|
|
||||||
|
b.Property<int>("ReferenceCount");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("Hash")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ReferenceCount");
|
||||||
|
|
||||||
|
b.ToTable("FileInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int?>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<string>("InstantiationInfo");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("ShortName");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("Available");
|
||||||
|
|
||||||
|
b.HasIndex("ShortName")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("RulesetInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("FileInfoID");
|
||||||
|
|
||||||
|
b.Property<string>("Filename")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("SkinInfoID");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.HasIndex("FileInfoID");
|
||||||
|
|
||||||
|
b.HasIndex("SkinInfoID");
|
||||||
|
|
||||||
|
b.ToTable("SkinFileInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ID")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Creator");
|
||||||
|
|
||||||
|
b.Property<bool>("DeletePending");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.HasKey("ID");
|
||||||
|
|
||||||
|
b.ToTable("SkinInfo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BaseDifficultyID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||||
|
.WithMany("Beatmaps")
|
||||||
|
.HasForeignKey("BeatmapSetInfoID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||||
|
.WithMany("Beatmaps")
|
||||||
|
.HasForeignKey("MetadataID");
|
||||||
|
|
||||||
|
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RulesetID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||||
|
.WithMany("Files")
|
||||||
|
.HasForeignKey("BeatmapSetInfoID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FileInfoID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||||
|
.WithMany("BeatmapSets")
|
||||||
|
.HasForeignKey("MetadataID");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FileInfoID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||||
|
.WithMany("Files")
|
||||||
|
.HasForeignKey("SkinInfoID")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Migrations
|
||||||
|
{
|
||||||
|
public partial class RemoveUniqueHashConstraints : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BeatmapInfo_Hash",
|
||||||
|
table: "BeatmapInfo");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BeatmapInfo_MD5Hash",
|
||||||
|
table: "BeatmapInfo");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BeatmapInfo_Hash",
|
||||||
|
table: "BeatmapInfo",
|
||||||
|
column: "Hash");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BeatmapInfo_MD5Hash",
|
||||||
|
table: "BeatmapInfo",
|
||||||
|
column: "MD5Hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BeatmapInfo_Hash",
|
||||||
|
table: "BeatmapInfo");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BeatmapInfo_MD5Hash",
|
||||||
|
table: "BeatmapInfo");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BeatmapInfo_Hash",
|
||||||
|
table: "BeatmapInfo",
|
||||||
|
column: "Hash",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BeatmapInfo_MD5Hash",
|
||||||
|
table: "BeatmapInfo",
|
||||||
|
column: "MD5Hash",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,11 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace osu.Game.Migrations
|
namespace osu.Game.Migrations
|
||||||
{
|
{
|
||||||
@ -12,7 +16,7 @@ namespace osu.Game.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "2.0.0-rtm-26452");
|
.HasAnnotation("ProductVersion", "2.0.3-rtm-10026");
|
||||||
|
|
||||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||||
{
|
{
|
||||||
@ -27,9 +31,9 @@ namespace osu.Game.Migrations
|
|||||||
|
|
||||||
b.Property<float>("OverallDifficulty");
|
b.Property<float>("OverallDifficulty");
|
||||||
|
|
||||||
b.Property<float>("SliderMultiplier");
|
b.Property<double>("SliderMultiplier");
|
||||||
|
|
||||||
b.Property<float>("SliderTickRate");
|
b.Property<double>("SliderTickRate");
|
||||||
|
|
||||||
b.HasKey("ID");
|
b.HasKey("ID");
|
||||||
|
|
||||||
@ -91,11 +95,9 @@ namespace osu.Game.Migrations
|
|||||||
|
|
||||||
b.HasIndex("BeatmapSetInfoID");
|
b.HasIndex("BeatmapSetInfoID");
|
||||||
|
|
||||||
b.HasIndex("Hash")
|
b.HasIndex("Hash");
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.HasIndex("MD5Hash")
|
b.HasIndex("MD5Hash");
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.HasIndex("MetadataID");
|
b.HasIndex("MetadataID");
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ namespace osu.Game.Online.API
|
|||||||
throw new TimeoutException(@"API request timeout hit");
|
throw new TimeoutException(@"API request timeout hit");
|
||||||
|
|
||||||
WebRequest = CreateWebRequest();
|
WebRequest = CreateWebRequest();
|
||||||
|
WebRequest.Failed += Fail;
|
||||||
WebRequest.AllowRetryOnTimeout = false;
|
WebRequest.AllowRetryOnTimeout = false;
|
||||||
WebRequest.AddHeader("Authorization", $"Bearer {api.AccessToken}");
|
WebRequest.AddHeader("Authorization", $"Bearer {api.AccessToken}");
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ namespace osu.Game.Online.API.Requests
|
|||||||
[JsonProperty(@"video")]
|
[JsonProperty(@"video")]
|
||||||
private bool hasVideo { get; set; }
|
private bool hasVideo { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(@"storyboard")]
|
||||||
|
private bool hasStoryboard { get; set; }
|
||||||
|
|
||||||
[JsonProperty(@"status")]
|
[JsonProperty(@"status")]
|
||||||
private BeatmapSetOnlineStatus status { get; set; }
|
private BeatmapSetOnlineStatus status { get; set; }
|
||||||
|
|
||||||
@ -65,6 +68,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
BPM = bpm,
|
BPM = bpm,
|
||||||
Status = status,
|
Status = status,
|
||||||
HasVideo = hasVideo,
|
HasVideo = hasVideo,
|
||||||
|
HasStoryboard = hasStoryboard,
|
||||||
Submitted = submitted,
|
Submitted = submitted,
|
||||||
Ranked = ranked,
|
Ranked = ranked,
|
||||||
LastUpdated = lastUpdated,
|
LastUpdated = lastUpdated,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -12,9 +13,10 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
public Bindable<string> Name = new Bindable<string>();
|
public Bindable<string> Name = new Bindable<string>();
|
||||||
public Bindable<User> Host = new Bindable<User>();
|
public Bindable<User> Host = new Bindable<User>();
|
||||||
public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
|
||||||
|
public Bindable<RoomAvailability> Availability = new Bindable<RoomAvailability>();
|
||||||
public Bindable<GameType> Type = new Bindable<GameType>();
|
public Bindable<GameType> Type = new Bindable<GameType>();
|
||||||
public Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
public Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||||
public Bindable<int?> MaxParticipants = new Bindable<int?>();
|
public Bindable<int?> MaxParticipants = new Bindable<int?>();
|
||||||
public Bindable<User[]> Participants = new Bindable<User[]>();
|
public Bindable<IEnumerable<User>> Participants = new Bindable<IEnumerable<User>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
osu.Game/Online/Multiplayer/RoomAvailability.cs
Normal file
18
osu.Game/Online/Multiplayer/RoomAvailability.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.Multiplayer
|
||||||
|
{
|
||||||
|
public enum RoomAvailability
|
||||||
|
{
|
||||||
|
Public,
|
||||||
|
|
||||||
|
[Description(@"Friends Only")]
|
||||||
|
FriendsOnly,
|
||||||
|
|
||||||
|
[Description(@"Invite Only")]
|
||||||
|
InviteOnly,
|
||||||
|
}
|
||||||
|
}
|
@ -77,7 +77,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight;
|
public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight;
|
||||||
|
|
||||||
public readonly BindableBool ShowOverlays = new BindableBool();
|
public readonly BindableBool HideOverlaysOnEnter = new BindableBool();
|
||||||
|
public readonly BindableBool AllowOpeningOverlays = new BindableBool(true);
|
||||||
|
|
||||||
private OsuScreen screenStack;
|
private OsuScreen screenStack;
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
// this needs to be cached before base.LoadComplete as it is used by CursorOverrideContainer.
|
// this needs to be cached before base.LoadComplete as it is used by MenuCursorContainer.
|
||||||
dependencies.Cache(screenshotManager = new ScreenshotManager());
|
dependencies.Cache(screenshotManager = new ScreenshotManager());
|
||||||
|
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
@ -219,7 +220,7 @@ namespace osu.Game
|
|||||||
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
|
// The next time this is updated is in UpdateAfterChildren, which occurs too late and results
|
||||||
// in the cursor being shown for a few frames during the intro.
|
// in the cursor being shown for a few frames during the intro.
|
||||||
// This prevents the cursor from showing until we have a screen with CursorVisible = true
|
// This prevents the cursor from showing until we have a screen with CursorVisible = true
|
||||||
CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
||||||
|
|
||||||
// hook up notifications to components.
|
// hook up notifications to components.
|
||||||
SkinManager.PostNotification = n => notifications?.Post(n);
|
SkinManager.PostNotification = n => notifications?.Post(n);
|
||||||
@ -367,12 +368,12 @@ namespace osu.Game
|
|||||||
settings.StateChanged += _ => updateScreenOffset();
|
settings.StateChanged += _ => updateScreenOffset();
|
||||||
notifications.StateChanged += _ => updateScreenOffset();
|
notifications.StateChanged += _ => updateScreenOffset();
|
||||||
|
|
||||||
notifications.Enabled.BindTo(ShowOverlays);
|
notifications.Enabled.BindTo(AllowOpeningOverlays);
|
||||||
|
|
||||||
ShowOverlays.ValueChanged += show =>
|
HideOverlaysOnEnter.ValueChanged += hide =>
|
||||||
{
|
{
|
||||||
//central game screen change logic.
|
//central game screen change logic.
|
||||||
if (!show)
|
if (hide)
|
||||||
{
|
{
|
||||||
hideAllOverlays();
|
hideAllOverlays();
|
||||||
musicController.State = Visibility.Hidden;
|
musicController.State = Visibility.Hidden;
|
||||||
@ -547,7 +548,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
mainContent.Padding = new MarginPadding { Top = ToolbarOffset };
|
mainContent.Padding = new MarginPadding { Top = ToolbarOffset };
|
||||||
|
|
||||||
CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void screenAdded(Screen newScreen)
|
private void screenAdded(Screen newScreen)
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
protected SettingsStore SettingsStore;
|
protected SettingsStore SettingsStore;
|
||||||
|
|
||||||
protected CursorOverrideContainer CursorOverrideContainer;
|
protected MenuCursorContainer MenuCursorContainer;
|
||||||
|
|
||||||
protected override string MainResourceFile => @"osu.Game.Resources.dll";
|
protected override string MainResourceFile => @"osu.Game.Resources.dll";
|
||||||
|
|
||||||
@ -191,14 +191,14 @@ namespace osu.Game
|
|||||||
|
|
||||||
GlobalActionContainer globalBinding;
|
GlobalActionContainer globalBinding;
|
||||||
|
|
||||||
CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both };
|
MenuCursorContainer = new MenuCursorContainer { RelativeSizeAxes = Axes.Both };
|
||||||
CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this)
|
MenuCursorContainer.Child = globalBinding = new GlobalActionContainer(this)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both }
|
Child = content = new OsuTooltipContainer(MenuCursorContainer.Cursor) { RelativeSizeAxes = Axes.Both }
|
||||||
};
|
};
|
||||||
|
|
||||||
base.Content.Add(new DrawSizePreservingFillContainer { Child = CursorOverrideContainer });
|
base.Content.Add(new DrawSizePreservingFillContainer { Child = MenuCursorContainer });
|
||||||
|
|
||||||
KeyBindingStore.Register(globalBinding);
|
KeyBindingStore.Register(globalBinding);
|
||||||
dependencies.Cache(globalBinding);
|
dependencies.Cache(globalBinding);
|
||||||
@ -208,7 +208,7 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var db = contextFactory.GetForWrite())
|
using (var db = contextFactory.GetForWrite(false))
|
||||||
db.Context.Migrate();
|
db.Context.Migrate();
|
||||||
}
|
}
|
||||||
catch (MigrationFailedException e)
|
catch (MigrationFailedException e)
|
||||||
@ -220,7 +220,7 @@ namespace osu.Game
|
|||||||
contextFactory.ResetDatabase();
|
contextFactory.ResetDatabase();
|
||||||
Logger.Log("Database purged successfully.", LoggingTarget.Database, LogLevel.Important);
|
Logger.Log("Database purged successfully.", LoggingTarget.Database, LogLevel.Important);
|
||||||
|
|
||||||
using (var db = contextFactory.GetForWrite())
|
using (var db = contextFactory.GetForWrite(false))
|
||||||
db.Context.Migrate();
|
db.Context.Migrate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
fields.Children = new Drawable[]
|
fields.Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Field("made by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"),
|
new Field("mapped by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"),
|
||||||
new Field("submitted on", online.Submitted.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold")
|
new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold")
|
||||||
{
|
{
|
||||||
Margin = new MarginPadding { Top = 5 },
|
Margin = new MarginPadding { Top = 5 },
|
||||||
},
|
},
|
||||||
@ -58,11 +58,11 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
if (online.Ranked.HasValue)
|
if (online.Ranked.HasValue)
|
||||||
{
|
{
|
||||||
fields.Add(new Field("ranked on ", online.Ranked.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold"));
|
fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold"));
|
||||||
}
|
}
|
||||||
else if (online.LastUpdated.HasValue)
|
else if (online.LastUpdated.HasValue)
|
||||||
{
|
{
|
||||||
fields.Add(new Field("last updated on ", online.LastUpdated.Value.ToString(@"MMM d, yyyy"), @"Exo2.0-Bold"));
|
fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays.BeatmapSet.Buttons;
|
using osu.Game.Overlays.BeatmapSet.Buttons;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
@ -25,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
private const float buttons_spacing = 5;
|
private const float buttons_spacing = 5;
|
||||||
|
|
||||||
private readonly Box tabsBg;
|
private readonly Box tabsBg;
|
||||||
private readonly Container coverContainer;
|
private readonly UpdateableBeatmapSetCover cover;
|
||||||
private readonly OsuSpriteText title, artist;
|
private readonly OsuSpriteText title, artist;
|
||||||
private readonly Container noVideoButtons;
|
private readonly Container noVideoButtons;
|
||||||
private readonly FillFlowContainer videoButtons;
|
private readonly FillFlowContainer videoButtons;
|
||||||
@ -35,7 +36,6 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
public Details Details;
|
public Details Details;
|
||||||
|
|
||||||
private BeatmapManager beatmaps;
|
private BeatmapManager beatmaps;
|
||||||
private DelayedLoadWrapper cover;
|
|
||||||
|
|
||||||
public readonly BeatmapPicker Picker;
|
public readonly BeatmapPicker Picker;
|
||||||
|
|
||||||
@ -61,8 +61,8 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
title.Text = BeatmapSet?.Metadata.Title ?? string.Empty;
|
title.Text = BeatmapSet?.Metadata.Title ?? string.Empty;
|
||||||
artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty;
|
artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty;
|
||||||
onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None;
|
onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None;
|
||||||
|
cover.BeatmapSet = BeatmapSet;
|
||||||
|
|
||||||
cover?.FadeOut(400, Easing.Out);
|
|
||||||
if (BeatmapSet != null)
|
if (BeatmapSet != null)
|
||||||
{
|
{
|
||||||
downloadButtonsContainer.FadeIn(transition_duration);
|
downloadButtonsContainer.FadeIn(transition_duration);
|
||||||
@ -70,19 +70,6 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration);
|
noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration);
|
||||||
videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration);
|
videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration);
|
||||||
|
|
||||||
coverContainer.Add(cover = new DelayedLoadWrapper(
|
|
||||||
new BeatmapSetCover(BeatmapSet)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
FillMode = FillMode.Fill,
|
|
||||||
OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out),
|
|
||||||
}, 300)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -93,6 +80,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
public Header()
|
public Header()
|
||||||
{
|
{
|
||||||
|
ExternalLinkButton externalLink;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = 400;
|
Height = 400;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
@ -128,12 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
cover = new UpdateableBeatmapSetCover
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
},
|
|
||||||
coverContainer = new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
@ -160,10 +143,24 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
Height = 113,
|
Height = 113,
|
||||||
Child = Picker = new BeatmapPicker(),
|
Child = Picker = new BeatmapPicker(),
|
||||||
},
|
},
|
||||||
title = new OsuSpriteText
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Font = @"Exo2.0-BoldItalic",
|
Direction = FillDirection.Horizontal,
|
||||||
TextSize = 37,
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
title = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Font = @"Exo2.0-BoldItalic",
|
||||||
|
TextSize = 37,
|
||||||
|
},
|
||||||
|
externalLink = new ExternalLinkButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Margin = new MarginPadding { Left = 3, Bottom = 4 }, //To better lineup with the font
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
artist = new OsuSpriteText
|
artist = new OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -247,6 +244,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
};
|
};
|
||||||
|
|
||||||
Picker.Beatmap.ValueChanged += b => Details.Beatmap = b;
|
Picker.Beatmap.ValueChanged += b => Details.Beatmap = b;
|
||||||
|
Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}";
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
private const float metadata_width = 225;
|
private const float metadata_width = 225;
|
||||||
private const float spacing = 20;
|
private const float spacing = 20;
|
||||||
|
|
||||||
private readonly MetadataSection description, source, tags;
|
private readonly MetadataSection source, tags;
|
||||||
private readonly Box successRateBackground;
|
private readonly Box successRateBackground;
|
||||||
private readonly SuccessRate successRate;
|
private readonly SuccessRate successRate;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
Child = new Container
|
Child = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = description = new MetadataSection("Description"),
|
Child = new MetadataSection("Description"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
@ -135,8 +135,6 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
successRateBackground.Colour = colours.GrayE;
|
successRateBackground.Colour = colours.GrayE;
|
||||||
source.TextColour = description.TextColour = colours.Gray5;
|
|
||||||
tags.TextColour = colours.BlueDark;
|
|
||||||
|
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
@ -195,7 +193,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
header.Colour = colours.Gray5;
|
header.Colour = textFlow.Colour = colours.Gray5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = $"from {SetInfo.Metadata.Source}",
|
Text = $"{SetInfo.Metadata.Source}",
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
Shadow = false,
|
Shadow = false,
|
||||||
Colour = colours.Gray5,
|
Colour = colours.Gray5,
|
||||||
@ -195,18 +195,18 @@ namespace osu.Game.Overlays.Direct
|
|||||||
new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0),
|
new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
playButton = new PlayButton(SetInfo)
|
|
||||||
{
|
|
||||||
Margin = new MarginPadding { Top = 5, Left = 10 },
|
|
||||||
Size = new Vector2(30),
|
|
||||||
Alpha = 0,
|
|
||||||
},
|
|
||||||
statusContainer = new FillFlowContainer
|
statusContainer = new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Margin = new MarginPadding { Top = 5, Left = 5 },
|
Margin = new MarginPadding { Top = 5, Left = 5 },
|
||||||
Spacing = new Vector2(5),
|
Spacing = new Vector2(5),
|
||||||
},
|
},
|
||||||
|
playButton = new PlayButton(SetInfo)
|
||||||
|
{
|
||||||
|
Margin = new MarginPadding { Top = 5, Left = 10 },
|
||||||
|
Size = new Vector2(30),
|
||||||
|
Alpha = 0,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (SetInfo.OnlineInfo?.HasVideo ?? false)
|
if (SetInfo.OnlineInfo?.HasVideo ?? false)
|
||||||
@ -214,24 +214,31 @@ namespace osu.Game.Overlays.Direct
|
|||||||
statusContainer.Add(new IconPill(FontAwesome.fa_film));
|
statusContainer.Add(new IconPill(FontAwesome.fa_film));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SetInfo.OnlineInfo?.HasStoryboard ?? false)
|
||||||
|
{
|
||||||
|
statusContainer.Add(new IconPill(FontAwesome.fa_image));
|
||||||
|
}
|
||||||
|
|
||||||
statusContainer.Add(new BeatmapSetOnlineStatusPill(12, new MarginPadding { Horizontal = 10, Vertical = 5 })
|
statusContainer.Add(new BeatmapSetOnlineStatusPill(12, new MarginPadding { Horizontal = 10, Vertical = 5 })
|
||||||
{
|
{
|
||||||
Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None,
|
Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PreviewPlaying.ValueChanged += _ => updateStatusContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(InputState state)
|
protected override bool OnHover(InputState state)
|
||||||
{
|
{
|
||||||
statusContainer.FadeOut(120, Easing.InOutQuint);
|
updateStatusContainer();
|
||||||
|
|
||||||
return base.OnHover(state);
|
return base.OnHover(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
protected override void OnHoverLost(InputState state)
|
||||||
{
|
{
|
||||||
base.OnHoverLost(state);
|
base.OnHoverLost(state);
|
||||||
|
updateStatusContainer();
|
||||||
statusContainer.FadeIn(120, Easing.InOutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying ? 0 : 1, 120, Easing.InOutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ namespace osu.Game.Overlays.Direct
|
|||||||
{
|
{
|
||||||
public readonly BeatmapSetInfo SetInfo;
|
public readonly BeatmapSetInfo SetInfo;
|
||||||
|
|
||||||
protected Box BlackBackground;
|
|
||||||
|
|
||||||
private const double hover_transition_time = 400;
|
private const double hover_transition_time = 400;
|
||||||
|
|
||||||
private Container content;
|
private Container content;
|
||||||
@ -81,12 +79,6 @@ namespace osu.Game.Overlays.Direct
|
|||||||
EdgeEffect = edgeEffectNormal,
|
EdgeEffect = edgeEffectNormal,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
// temporary blackness until the actual background loads.
|
|
||||||
BlackBackground = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
},
|
|
||||||
CreateBackground(),
|
CreateBackground(),
|
||||||
progressBar = new ProgressBar
|
progressBar = new ProgressBar
|
||||||
{
|
{
|
||||||
@ -215,21 +207,10 @@ namespace osu.Game.Overlays.Direct
|
|||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Drawable CreateBackground() => new DelayedLoadWrapper(
|
protected Drawable CreateBackground() => new UpdateableBeatmapSetCover
|
||||||
new BeatmapSetCover(SetInfo)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
FillMode = FillMode.Fill,
|
|
||||||
OnLoadComplete = d =>
|
|
||||||
{
|
|
||||||
d.FadeInFromZero(400, Easing.Out);
|
|
||||||
BlackBackground.Delay(400).FadeOut();
|
|
||||||
},
|
|
||||||
}, 300)
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BeatmapSet = SetInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
public class Statistic : FillFlowContainer
|
public class Statistic : FillFlowContainer
|
||||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Direct
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
icon.Icon = playing ? FontAwesome.fa_pause : FontAwesome.fa_play;
|
icon.Icon = playing ? FontAwesome.fa_stop : FontAwesome.fa_play;
|
||||||
icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint);
|
icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint);
|
||||||
|
|
||||||
if (playing)
|
if (playing)
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
@ -14,22 +13,10 @@ namespace osu.Game.Overlays
|
|||||||
/// An overlay which will display a black screen that dims over a period before confirming an exit action.
|
/// An overlay which will display a black screen that dims over a period before confirming an exit action.
|
||||||
/// Action is BYO (derived class will need to call <see cref="BeginConfirm"/> and <see cref="AbortConfirm"/> from a user event).
|
/// Action is BYO (derived class will need to call <see cref="BeginConfirm"/> and <see cref="AbortConfirm"/> from a user event).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class HoldToConfirmOverlay : Container
|
public abstract class HoldToConfirmOverlay : HoldToConfirmContainer
|
||||||
{
|
{
|
||||||
public Action Action;
|
|
||||||
|
|
||||||
private Box overlay;
|
private Box overlay;
|
||||||
|
|
||||||
private const int activate_delay = 400;
|
|
||||||
private const int fadeout_delay = 200;
|
|
||||||
|
|
||||||
private bool fired;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the overlay should be allowed to return from a fired state.
|
|
||||||
/// </summary>
|
|
||||||
protected virtual bool AllowMultipleFires => false;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -45,22 +32,8 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
protected void BeginConfirm()
|
Progress.ValueChanged += v => overlay.Alpha = (float)v;
|
||||||
{
|
|
||||||
if (!AllowMultipleFires && fired) return;
|
|
||||||
overlay.FadeIn(activate_delay * (1 - overlay.Alpha), Easing.Out).OnComplete(_ =>
|
|
||||||
{
|
|
||||||
Action?.Invoke();
|
|
||||||
fired = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void AbortConfirm()
|
|
||||||
{
|
|
||||||
if (!AllowMultipleFires && fired) return;
|
|
||||||
overlay.FadeOut(fadeout_delay, Easing.Out);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ namespace osu.Game.Overlays.KeyBinding
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnWheel(InputState state)
|
protected override bool OnScroll(InputState state)
|
||||||
{
|
{
|
||||||
if (HasFocus)
|
if (HasFocus)
|
||||||
{
|
{
|
||||||
@ -192,7 +192,7 @@ namespace osu.Game.Overlays.KeyBinding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.OnWheel(state);
|
return base.OnScroll(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
protected Color4 LowMultiplierColour, HighMultiplierColour;
|
protected Color4 LowMultiplierColour, HighMultiplierColour;
|
||||||
|
|
||||||
protected readonly TriangleButton DeselectAllButton;
|
protected readonly TriangleButton DeselectAllButton;
|
||||||
protected readonly OsuSpriteText MultiplierLabel;
|
protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel;
|
||||||
private readonly FillFlowContainer footerContainer;
|
private readonly FillFlowContainer footerContainer;
|
||||||
|
|
||||||
protected override bool BlockPassThroughKeyboard => false;
|
protected override bool BlockPassThroughKeyboard => false;
|
||||||
@ -58,6 +58,7 @@ namespace osu.Game.Overlays.Mods
|
|||||||
|
|
||||||
LowMultiplierColour = colours.Red;
|
LowMultiplierColour = colours.Red;
|
||||||
HighMultiplierColour = colours.Green;
|
HighMultiplierColour = colours.Green;
|
||||||
|
UnrankedLabel.Colour = colours.Blue;
|
||||||
|
|
||||||
if (osu != null)
|
if (osu != null)
|
||||||
Ruleset.BindTo(osu.Ruleset);
|
Ruleset.BindTo(osu.Ruleset);
|
||||||
@ -99,15 +100,14 @@ namespace osu.Game.Overlays.Mods
|
|||||||
}
|
}
|
||||||
|
|
||||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||||
if (!ranked)
|
|
||||||
MultiplierLabel.Text += " (Unranked)";
|
|
||||||
|
|
||||||
if (multiplier > 1.0)
|
if (multiplier > 1.0)
|
||||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||||
else if (multiplier < 1.0)
|
else if (multiplier < 1.0)
|
||||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||||
else
|
else
|
||||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||||
|
|
||||||
|
UnrankedLabel.FadeTo(ranked ? 0 : 1, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopOut()
|
protected override void PopOut()
|
||||||
@ -352,23 +352,33 @@ namespace osu.Game.Overlays.Mods
|
|||||||
},
|
},
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = @"Score Multiplier: ",
|
Text = @"Score Multiplier:",
|
||||||
TextSize = 30,
|
TextSize = 30,
|
||||||
Shadow = true,
|
|
||||||
Margin = new MarginPadding
|
Margin = new MarginPadding
|
||||||
{
|
{
|
||||||
Top = 5
|
Top = 5,
|
||||||
|
Right = 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MultiplierLabel = new OsuSpriteText
|
MultiplierLabel = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Font = @"Exo2.0-Bold",
|
Font = @"Exo2.0-Bold",
|
||||||
TextSize = 30,
|
TextSize = 30,
|
||||||
Shadow = true,
|
|
||||||
Margin = new MarginPadding
|
Margin = new MarginPadding
|
||||||
{
|
{
|
||||||
Top = 5
|
Top = 5
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
UnrankedLabel = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Font = @"Exo2.0-Bold",
|
||||||
|
Text = @"(Unranked)",
|
||||||
|
TextSize = 30,
|
||||||
|
Margin = new MarginPadding
|
||||||
|
{
|
||||||
|
Top = 5,
|
||||||
|
Left = 10
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
private void updateSelectedSet()
|
private void updateSelectedSet()
|
||||||
{
|
{
|
||||||
foreach (PlaylistItem s in items.Children)
|
foreach (PlaylistItem s in items.Children)
|
||||||
s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo.ID;
|
s.Selected = s.BeatmapSetInfo.ID == beatmapBacking.Value.BeatmapSetInfo?.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SearchTerm
|
public string SearchTerm
|
||||||
|
@ -79,7 +79,10 @@ namespace osu.Game.Overlays.Music
|
|||||||
{
|
{
|
||||||
BeatmapInfo beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
|
BeatmapInfo beatmap = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
|
||||||
if (beatmap != null)
|
if (beatmap != null)
|
||||||
|
{
|
||||||
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(beatmap);
|
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(beatmap);
|
||||||
|
beatmapBacking.Value.Track.Restart();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +112,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
}
|
}
|
||||||
|
|
||||||
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First());
|
beatmapBacking.Value = beatmaps.GetWorkingBeatmap(set.Beatmaps.First());
|
||||||
|
beatmapBacking.Value.Track.Restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -10,13 +9,13 @@ using osu.Framework.Extensions.Color4Extensions;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Overlays.Profile.Header;
|
using osu.Game.Overlays.Profile.Header;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
@ -105,11 +104,28 @@ namespace osu.Game.Overlays.Profile
|
|||||||
Y = -75,
|
Y = -75,
|
||||||
Size = new Vector2(25, 25)
|
Size = new Vector2(25, 25)
|
||||||
},
|
},
|
||||||
new ProfileLink(user)
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Y = -48,
|
Y = -48,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = user.Username,
|
||||||
|
Font = @"Exo2.0-RegularItalic",
|
||||||
|
TextSize = 30,
|
||||||
|
},
|
||||||
|
new ExternalLinkButton($@"https://osu.ppy.sh/users/{user.Id}")
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
Margin = new MarginPadding { Left = 3, Bottom = 3 }, //To better lineup with the font
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
countryFlag = new DrawableFlag(user.Country)
|
countryFlag = new DrawableFlag(user.Country)
|
||||||
{
|
{
|
||||||
@ -455,28 +471,6 @@ namespace osu.Game.Overlays.Profile
|
|||||||
infoTextRight.NewLine();
|
infoTextRight.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ProfileLink : OsuHoverContainer, IHasTooltip
|
|
||||||
{
|
|
||||||
public string TooltipText => "View Profile in Browser";
|
|
||||||
|
|
||||||
public override bool HandleMouseInput => true;
|
|
||||||
|
|
||||||
public ProfileLink(User user)
|
|
||||||
{
|
|
||||||
Action = () => Process.Start($@"https://osu.ppy.sh/users/{user.Id}");
|
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
|
|
||||||
Child = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = user.Username,
|
|
||||||
Font = @"Exo2.0-RegularItalic",
|
|
||||||
TextSize = 30,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private class GradeBadge : Container
|
private class GradeBadge : Container
|
||||||
{
|
{
|
||||||
private const float width = 50;
|
private const float width = 50;
|
||||||
|
@ -24,19 +24,13 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
|||||||
this.playCount = playCount;
|
this.playCount = playCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateLeftVisual() => new DelayedLoadWrapper(new BeatmapSetCover(beatmap.BeatmapSet, BeatmapSetCoverType.List)
|
protected override Drawable CreateLeftVisual() => new UpdateableBeatmapSetCover
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
FillMode = FillMode.Fit,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
OnLoadComplete = d => d.FadeInFromZero(500, Easing.OutQuint)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.None,
|
Origin = Anchor.CentreLeft,
|
||||||
Size = new Vector2(80, 50),
|
Size = new Vector2(80, 50),
|
||||||
|
BeatmapSet = beatmap.BeatmapSet,
|
||||||
|
CoverType = BeatmapSetCoverType.List,
|
||||||
};
|
};
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public override string ShortenedName => "AT";
|
public override string ShortenedName => "AT";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
|
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
|
||||||
public override string Description => "Watch a perfect automated play through the song.";
|
public override string Description => "Watch a perfect automated play through the song.";
|
||||||
public override double ScoreMultiplier => 0;
|
public override double ScoreMultiplier => 1;
|
||||||
public bool AllowFail => false;
|
public bool AllowFail => false;
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) };
|
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) };
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public override string Name => "Relax";
|
public override string Name => "Relax";
|
||||||
public override string ShortenedName => "RX";
|
public override string ShortenedName => "RX";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax;
|
public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax;
|
||||||
public override double ScoreMultiplier => 0;
|
public override double ScoreMultiplier => 1;
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) };
|
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets
|
namespace osu.Game.Rulesets
|
||||||
@ -114,8 +115,9 @@ namespace osu.Game.Rulesets
|
|||||||
var assembly = Assembly.LoadFrom(file);
|
var assembly = Assembly.LoadFrom(file);
|
||||||
loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset)));
|
loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset)));
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
Logger.Error(e, "Failed to load ruleset");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,8 +121,6 @@ namespace osu.Game.Rulesets.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool validState;
|
private bool validState;
|
||||||
|
|
||||||
protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState;
|
|
||||||
|
|
||||||
private bool isAttached => replayInputHandler != null && !UseParentState;
|
private bool isAttached => replayInputHandler != null && !UseParentState;
|
||||||
|
|
||||||
private const int max_catch_up_updates_per_frame = 50;
|
private const int max_catch_up_updates_per_frame = 50;
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4");
|
||||||
|
|
||||||
public override bool ShowOverlaysOnEnter => false;
|
protected override bool HideOverlaysOnEnter => true;
|
||||||
public override bool AllowBeatmapRulesetChange => false;
|
public override bool AllowBeatmapRulesetChange => false;
|
||||||
|
|
||||||
private Box bottomBackground;
|
private Box bottomBackground;
|
||||||
@ -48,7 +48,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
// TODO: should probably be done at a RulesetContainer level to share logic with Player.
|
// TODO: should probably be done at a RulesetContainer level to share logic with Player.
|
||||||
var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
|
var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
|
||||||
clock = new EditorClock(Beatmap.Value.Beatmap.ControlPointInfo, beatDivisor) { IsCoupled = false };
|
clock = new EditorClock(Beatmap, beatDivisor) { IsCoupled = false };
|
||||||
clock.ChangeSource(sourceClock);
|
clock.ChangeSource(sourceClock);
|
||||||
|
|
||||||
dependencies.CacheAs<IFrameBasedClock>(clock);
|
dependencies.CacheAs<IFrameBasedClock>(clock);
|
||||||
@ -182,9 +182,9 @@ namespace osu.Game.Screens.Edit
|
|||||||
LoadComponentAsync(currentScreen, screenContainer.Add);
|
LoadComponentAsync(currentScreen, screenContainer.Add);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnWheel(InputState state)
|
protected override bool OnScroll(InputState state)
|
||||||
{
|
{
|
||||||
if (state.Mouse.WheelDelta > 0)
|
if (state.Mouse.ScrollDelta.X + state.Mouse.ScrollDelta.Y > 0)
|
||||||
clock.SeekBackward(true);
|
clock.SeekBackward(true);
|
||||||
else
|
else
|
||||||
clock.SeekForward(true);
|
clock.SeekForward(true);
|
||||||
|
@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Screens.Edit.Screens.Compose;
|
using osu.Game.Screens.Edit.Screens.Compose;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit
|
namespace osu.Game.Screens.Edit
|
||||||
{
|
{
|
||||||
@ -15,15 +18,26 @@ namespace osu.Game.Screens.Edit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class EditorClock : DecoupleableInterpolatingFramedClock
|
public class EditorClock : DecoupleableInterpolatingFramedClock
|
||||||
{
|
{
|
||||||
|
public readonly double TrackLength;
|
||||||
|
|
||||||
public ControlPointInfo ControlPointInfo;
|
public ControlPointInfo ControlPointInfo;
|
||||||
|
|
||||||
private readonly BindableBeatDivisor beatDivisor;
|
private readonly BindableBeatDivisor beatDivisor;
|
||||||
|
|
||||||
public EditorClock(ControlPointInfo controlPointInfo, BindableBeatDivisor beatDivisor)
|
public EditorClock(Bindable<WorkingBeatmap> beatmap, BindableBeatDivisor beatDivisor)
|
||||||
|
{
|
||||||
|
this.beatDivisor = beatDivisor;
|
||||||
|
|
||||||
|
ControlPointInfo = beatmap.Value.Beatmap.ControlPointInfo;
|
||||||
|
TrackLength = beatmap.Value.Track.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorClock(ControlPointInfo controlPointInfo, double trackLength, BindableBeatDivisor beatDivisor)
|
||||||
{
|
{
|
||||||
this.beatDivisor = beatDivisor;
|
this.beatDivisor = beatDivisor;
|
||||||
|
|
||||||
ControlPointInfo = controlPointInfo;
|
ControlPointInfo = controlPointInfo;
|
||||||
|
TrackLength = trackLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -111,6 +125,8 @@ namespace osu.Game.Screens.Edit
|
|||||||
if (seekTime > nextTimingPoint?.Time)
|
if (seekTime > nextTimingPoint?.Time)
|
||||||
seekTime = nextTimingPoint.Time;
|
seekTime = nextTimingPoint.Time;
|
||||||
|
|
||||||
|
// Ensure the sought point is within the boundaries
|
||||||
|
seekTime = MathHelper.Clamp(seekTime, 0, TrackLength);
|
||||||
Seek(seekTime);
|
Seek(seekTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,15 +123,15 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private float? localZoomTarget;
|
private float? localZoomTarget;
|
||||||
|
|
||||||
protected override bool OnWheel(InputState state)
|
protected override bool OnScroll(InputState state)
|
||||||
{
|
{
|
||||||
if (!state.Keyboard.ControlPressed)
|
if (!state.Keyboard.ControlPressed)
|
||||||
return base.OnWheel(state);
|
return base.OnScroll(state);
|
||||||
|
|
||||||
relativeContentZoomTarget = Content.ToLocalSpace(state.Mouse.NativeState.Position).X / Content.DrawSize.X;
|
relativeContentZoomTarget = Content.ToLocalSpace(state.Mouse.NativeState.Position).X / Content.DrawSize.X;
|
||||||
localZoomTarget = ToLocalSpace(state.Mouse.NativeState.Position).X;
|
localZoomTarget = ToLocalSpace(state.Mouse.NativeState.Position).X;
|
||||||
|
|
||||||
Zoom += state.Mouse.WheelDelta;
|
Zoom += state.Mouse.ScrollDelta.Y;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -17,7 +16,7 @@ namespace osu.Game.Screens
|
|||||||
{
|
{
|
||||||
private bool showDisclaimer;
|
private bool showDisclaimer;
|
||||||
|
|
||||||
public override bool ShowOverlaysOnEnter => false;
|
protected override bool HideOverlaysOnEnter => true;
|
||||||
|
|
||||||
protected override bool AllowBackButton => false;
|
protected override bool AllowBackButton => false;
|
||||||
|
|
||||||
@ -30,43 +29,48 @@ namespace osu.Game.Screens
|
|||||||
{
|
{
|
||||||
base.LogoArriving(logo, resuming);
|
base.LogoArriving(logo, resuming);
|
||||||
|
|
||||||
|
logo.BeatMatching = false;
|
||||||
logo.Triangles = false;
|
logo.Triangles = false;
|
||||||
logo.Origin = Anchor.BottomRight;
|
logo.Origin = Anchor.BottomRight;
|
||||||
logo.Anchor = Anchor.BottomRight;
|
logo.Anchor = Anchor.BottomRight;
|
||||||
logo.Position = new Vector2(-40);
|
logo.Position = new Vector2(-40);
|
||||||
logo.Scale = new Vector2(0.2f);
|
logo.Scale = new Vector2(0.2f);
|
||||||
|
|
||||||
logo.FadeInFromZero(5000, Easing.OutQuint);
|
logo.Delay(500).FadeInFromZero(1000, Easing.OutQuint);
|
||||||
}
|
|
||||||
|
|
||||||
private OsuScreen loadScreen;
|
|
||||||
private ShaderPrecompiler precompiler;
|
|
||||||
|
|
||||||
protected override void OnEntering(Screen last)
|
|
||||||
{
|
|
||||||
base.OnEntering(last);
|
|
||||||
|
|
||||||
LoadComponentAsync(precompiler = new ShaderPrecompiler(loadIfReady), Add);
|
|
||||||
LoadComponentAsync(loadScreen = showDisclaimer ? (OsuScreen)new Disclaimer() : new Intro(), s => loadIfReady());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadIfReady()
|
|
||||||
{
|
|
||||||
if (ChildScreen == loadScreen) return;
|
|
||||||
|
|
||||||
if (loadScreen.LoadState != LoadState.Ready)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!precompiler.FinishedCompiling)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Push(loadScreen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LogoSuspending(OsuLogo logo)
|
protected override void LogoSuspending(OsuLogo logo)
|
||||||
{
|
{
|
||||||
base.LogoSuspending(logo);
|
base.LogoSuspending(logo);
|
||||||
logo.FadeOut(100);
|
logo.FadeOut(logo.Alpha * 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OsuScreen loadableScreen;
|
||||||
|
private ShaderPrecompiler precompiler;
|
||||||
|
|
||||||
|
protected virtual OsuScreen CreateLoadableScreen() => showDisclaimer ? (OsuScreen)new Disclaimer() : new Intro();
|
||||||
|
|
||||||
|
protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler();
|
||||||
|
|
||||||
|
protected override void OnEntering(Screen last)
|
||||||
|
{
|
||||||
|
base.OnEntering(last);
|
||||||
|
|
||||||
|
LoadComponentAsync(precompiler = CreateShaderPrecompiler(), Add);
|
||||||
|
LoadComponentAsync(loadableScreen = CreateLoadableScreen());
|
||||||
|
|
||||||
|
checkIfLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIfLoaded()
|
||||||
|
{
|
||||||
|
if (loadableScreen.LoadState != LoadState.Ready || !precompiler.FinishedCompiling)
|
||||||
|
{
|
||||||
|
Schedule(checkIfLoaded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Push(loadableScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -80,16 +84,10 @@ namespace osu.Game.Screens
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ShaderPrecompiler : Drawable
|
public class ShaderPrecompiler : Drawable
|
||||||
{
|
{
|
||||||
private readonly Action onLoaded;
|
|
||||||
private readonly List<Shader> loadTargets = new List<Shader>();
|
private readonly List<Shader> loadTargets = new List<Shader>();
|
||||||
|
|
||||||
public bool FinishedCompiling { get; private set; }
|
public bool FinishedCompiling { get; private set; }
|
||||||
|
|
||||||
public ShaderPrecompiler(Action onLoaded)
|
|
||||||
{
|
|
||||||
this.onLoaded = onLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ShaderManager manager)
|
private void load(ShaderManager manager)
|
||||||
{
|
{
|
||||||
@ -103,16 +101,17 @@ namespace osu.Game.Screens
|
|||||||
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE));
|
loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual bool AllLoaded => loadTargets.All(s => s.Loaded);
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
// if our target is null we are done.
|
// if our target is null we are done.
|
||||||
if (loadTargets.All(s => s.Loaded))
|
if (AllLoaded)
|
||||||
{
|
{
|
||||||
FinishedCompiling = true;
|
FinishedCompiling = true;
|
||||||
Expire();
|
Expire();
|
||||||
onLoaded?.Invoke();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
public event Action<MenuState> StateChanged;
|
public event Action<MenuState> StateChanged;
|
||||||
|
|
||||||
private readonly BindableBool showOverlays = new BindableBool();
|
private readonly BindableBool hideOverlaysOnEnter = new BindableBool();
|
||||||
|
private readonly BindableBool allowOpeningOverlays = new BindableBool();
|
||||||
|
|
||||||
public Action OnEdit;
|
public Action OnEdit;
|
||||||
public Action OnExit;
|
public Action OnExit;
|
||||||
@ -135,7 +136,12 @@ namespace osu.Game.Screens.Menu
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(AudioManager audio, OsuGame game)
|
private void load(AudioManager audio, OsuGame game)
|
||||||
{
|
{
|
||||||
if (game != null) showOverlays.BindTo(game.ShowOverlays);
|
if (game != null)
|
||||||
|
{
|
||||||
|
hideOverlaysOnEnter.BindTo(game.HideOverlaysOnEnter);
|
||||||
|
allowOpeningOverlays.BindTo(game.AllowOpeningOverlays);
|
||||||
|
}
|
||||||
|
|
||||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +154,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
case Key.Space:
|
case Key.Space:
|
||||||
logo?.TriggerOnClick(state);
|
logo?.TriggerOnClick(state);
|
||||||
return true;
|
return true;
|
||||||
|
case Key.Escape:
|
||||||
|
return goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -158,17 +166,22 @@ namespace osu.Game.Screens.Menu
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case GlobalAction.Back:
|
case GlobalAction.Back:
|
||||||
switch (State)
|
return goBack();
|
||||||
{
|
default:
|
||||||
case MenuState.TopLevel:
|
return false;
|
||||||
State = MenuState.Initial;
|
}
|
||||||
return true;
|
}
|
||||||
case MenuState.Play:
|
|
||||||
backButton.TriggerOnClick();
|
private bool goBack()
|
||||||
return true;
|
{
|
||||||
default:
|
switch (State)
|
||||||
return false;
|
{
|
||||||
}
|
case MenuState.TopLevel:
|
||||||
|
State = MenuState.Initial;
|
||||||
|
return true;
|
||||||
|
case MenuState.Play:
|
||||||
|
backButton.TriggerOnClick();
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -241,9 +254,6 @@ namespace osu.Game.Screens.Menu
|
|||||||
backButton.ContractStyle = 0;
|
backButton.ContractStyle = 0;
|
||||||
settingsButton.ContractStyle = 0;
|
settingsButton.ContractStyle = 0;
|
||||||
|
|
||||||
if (state == MenuState.TopLevel)
|
|
||||||
buttonArea.FinishTransforms(true);
|
|
||||||
|
|
||||||
updateLogoState(lastState);
|
updateLogoState(lastState);
|
||||||
|
|
||||||
using (buttonArea.BeginDelayedSequence(lastState == MenuState.Initial ? 150 : 0, true))
|
using (buttonArea.BeginDelayedSequence(lastState == MenuState.Initial ? 150 : 0, true))
|
||||||
@ -312,49 +322,57 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
if (logo == null) return;
|
if (logo == null) return;
|
||||||
|
|
||||||
logoDelayedAction?.Cancel();
|
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case MenuState.Exit:
|
case MenuState.Exit:
|
||||||
case MenuState.Initial:
|
case MenuState.Initial:
|
||||||
logoTracking = false;
|
logoDelayedAction?.Cancel();
|
||||||
|
|
||||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||||
{
|
{
|
||||||
showOverlays.Value = false;
|
logoTracking = false;
|
||||||
|
|
||||||
|
hideOverlaysOnEnter.Value = true;
|
||||||
|
allowOpeningOverlays.Value = false;
|
||||||
|
|
||||||
logo.ClearTransforms(targetMember: nameof(Position));
|
logo.ClearTransforms(targetMember: nameof(Position));
|
||||||
logo.RelativePositionAxes = Axes.Both;
|
logo.RelativePositionAxes = Axes.Both;
|
||||||
|
|
||||||
logo.MoveTo(new Vector2(0.5f), 800, Easing.OutExpo);
|
logo.MoveTo(new Vector2(0.5f), 800, Easing.OutExpo);
|
||||||
logo.ScaleTo(1, 800, Easing.OutExpo);
|
logo.ScaleTo(1, 800, Easing.OutExpo);
|
||||||
}, 150);
|
}, buttonArea.Alpha * 150);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MenuState.TopLevel:
|
case MenuState.TopLevel:
|
||||||
case MenuState.Play:
|
case MenuState.Play:
|
||||||
logo.ClearTransforms(targetMember: nameof(Position));
|
|
||||||
logo.RelativePositionAxes = Axes.None;
|
|
||||||
|
|
||||||
switch (lastState)
|
switch (lastState)
|
||||||
{
|
{
|
||||||
case MenuState.TopLevel: // coming from toplevel to play
|
case MenuState.TopLevel: // coming from toplevel to play
|
||||||
|
break;
|
||||||
case MenuState.Initial:
|
case MenuState.Initial:
|
||||||
logoTracking = false;
|
logo.ClearTransforms(targetMember: nameof(Position));
|
||||||
logo.ScaleTo(0.5f, 200, Easing.In);
|
logo.RelativePositionAxes = Axes.None;
|
||||||
|
|
||||||
|
bool impact = logo.Scale.X > 0.6f;
|
||||||
|
|
||||||
|
if (lastState == MenuState.Initial)
|
||||||
|
logo.ScaleTo(0.5f, 200, Easing.In);
|
||||||
|
|
||||||
logo.MoveTo(logoTrackingPosition, lastState == MenuState.EnteringMode ? 0 : 200, Easing.In);
|
logo.MoveTo(logoTrackingPosition, lastState == MenuState.EnteringMode ? 0 : 200, Easing.In);
|
||||||
|
|
||||||
|
logoDelayedAction?.Cancel();
|
||||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||||
{
|
{
|
||||||
logoTracking = true;
|
logoTracking = true;
|
||||||
|
|
||||||
logo.Impact();
|
if (impact)
|
||||||
showOverlays.Value = true;
|
logo.Impact();
|
||||||
|
|
||||||
|
hideOverlaysOnEnter.Value = false;
|
||||||
|
allowOpeningOverlays.Value = true;
|
||||||
}, 200);
|
}, 200);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
logo.ClearTransforms(targetMember: nameof(Position));
|
||||||
|
logo.RelativePositionAxes = Axes.None;
|
||||||
logoTracking = true;
|
logoTracking = true;
|
||||||
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
||||||
break;
|
break;
|
||||||
|
@ -18,7 +18,9 @@ namespace osu.Game.Screens.Menu
|
|||||||
private readonly SpriteIcon icon;
|
private readonly SpriteIcon icon;
|
||||||
private Color4 iconColour;
|
private Color4 iconColour;
|
||||||
|
|
||||||
public override bool ShowOverlaysOnEnter => false;
|
protected override bool HideOverlaysOnEnter => true;
|
||||||
|
protected override bool AllowOpeningOverlays => false;
|
||||||
|
|
||||||
public override bool CursorVisible => false;
|
public override bool CursorVisible => false;
|
||||||
|
|
||||||
public Disclaimer()
|
public Disclaimer()
|
||||||
|
@ -31,7 +31,9 @@ namespace osu.Game.Screens.Menu
|
|||||||
private SampleChannel welcome;
|
private SampleChannel welcome;
|
||||||
private SampleChannel seeya;
|
private SampleChannel seeya;
|
||||||
|
|
||||||
public override bool ShowOverlaysOnEnter => false;
|
protected override bool HideOverlaysOnEnter => true;
|
||||||
|
protected override bool AllowOpeningOverlays => false;
|
||||||
|
|
||||||
public override bool CursorVisible => false;
|
public override bool CursorVisible => false;
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty();
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty();
|
||||||
@ -77,31 +79,6 @@ namespace osu.Game.Screens.Menu
|
|||||||
seeya = audio.Sample.Get(@"seeya");
|
seeya = audio.Sample.Get(@"seeya");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEntering(Screen last)
|
|
||||||
{
|
|
||||||
base.OnEntering(last);
|
|
||||||
|
|
||||||
Game.Beatmap.Value = beatmap;
|
|
||||||
|
|
||||||
if (menuVoice)
|
|
||||||
welcome.Play();
|
|
||||||
|
|
||||||
Scheduler.AddDelayed(delegate
|
|
||||||
{
|
|
||||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
|
||||||
if (menuMusic)
|
|
||||||
track.Start();
|
|
||||||
|
|
||||||
LoadComponentAsync(mainMenu = new MainMenu());
|
|
||||||
|
|
||||||
Scheduler.AddDelayed(delegate
|
|
||||||
{
|
|
||||||
DidLoadMenu = true;
|
|
||||||
Push(mainMenu);
|
|
||||||
}, delay_step_one);
|
|
||||||
}, delay_step_two);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const double delay_step_one = 2300;
|
private const double delay_step_one = 2300;
|
||||||
private const double delay_step_two = 600;
|
private const double delay_step_two = 600;
|
||||||
|
|
||||||
@ -111,6 +88,29 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
base.LogoArriving(logo, resuming);
|
base.LogoArriving(logo, resuming);
|
||||||
|
|
||||||
|
if (!resuming)
|
||||||
|
{
|
||||||
|
Game.Beatmap.Value = beatmap;
|
||||||
|
|
||||||
|
if (menuVoice)
|
||||||
|
welcome.Play();
|
||||||
|
|
||||||
|
Scheduler.AddDelayed(delegate
|
||||||
|
{
|
||||||
|
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
||||||
|
if (menuMusic)
|
||||||
|
track.Start();
|
||||||
|
|
||||||
|
LoadComponentAsync(mainMenu = new MainMenu());
|
||||||
|
|
||||||
|
Scheduler.AddDelayed(delegate
|
||||||
|
{
|
||||||
|
DidLoadMenu = true;
|
||||||
|
Push(mainMenu);
|
||||||
|
}, delay_step_one);
|
||||||
|
}, delay_step_two);
|
||||||
|
}
|
||||||
|
|
||||||
logo.RelativePositionAxes = Axes.Both;
|
logo.RelativePositionAxes = Axes.Both;
|
||||||
logo.Colour = Color4.White;
|
logo.Colour = Color4.White;
|
||||||
logo.Ripple = false;
|
logo.Ripple = false;
|
||||||
|
@ -24,7 +24,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
private readonly ButtonSystem buttons;
|
private readonly ButtonSystem buttons;
|
||||||
|
|
||||||
public override bool ShowOverlaysOnEnter => buttons.State != MenuState.Initial;
|
protected override bool HideOverlaysOnEnter => buttons.State == MenuState.Initial;
|
||||||
|
protected override bool AllowOpeningOverlays => buttons.State != MenuState.Initial;
|
||||||
|
|
||||||
protected override bool AllowBackButton => buttons.State != MenuState.Initial;
|
protected override bool AllowBackButton => buttons.State != MenuState.Initial;
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
private readonly Box leftBox;
|
private Box leftBox;
|
||||||
private readonly Box rightBox;
|
private Box rightBox;
|
||||||
|
|
||||||
private const float amplitude_dead_zone = 0.25f;
|
private const float amplitude_dead_zone = 0.25f;
|
||||||
private const float alpha_multiplier = (1 - amplitude_dead_zone) / 0.55f;
|
private const float alpha_multiplier = (1 - amplitude_dead_zone) / 0.55f;
|
||||||
@ -42,27 +42,6 @@ namespace osu.Game.Screens.Menu
|
|||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
leftBox = new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.CentreLeft,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = box_width,
|
|
||||||
Alpha = 0,
|
|
||||||
Blending = BlendingMode.Additive,
|
|
||||||
},
|
|
||||||
rightBox = new Box
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = box_width,
|
|
||||||
Alpha = 0,
|
|
||||||
Blending = BlendingMode.Additive,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -72,10 +51,34 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
// linear colour looks better in this case, so let's use it for now.
|
// linear colour looks better in this case, so let's use it for now.
|
||||||
Color4 gradientDark = colours.Blue.Opacity(0).ToLinear();
|
Color4 gradientDark = colours.Blue.Opacity(0).ToLinear();
|
||||||
Color4 gradientLight = colours.Blue.Opacity(0.3f).ToLinear();
|
Color4 gradientLight = colours.Blue.Opacity(0.6f).ToLinear();
|
||||||
|
|
||||||
leftBox.Colour = ColourInfo.GradientHorizontal(gradientLight, gradientDark);
|
Children = new Drawable[]
|
||||||
rightBox.Colour = ColourInfo.GradientHorizontal(gradientDark, gradientLight);
|
{
|
||||||
|
leftBox = new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = box_width * 2,
|
||||||
|
// align off-screen to make sure our edges don't become visible during parallax.
|
||||||
|
X = -box_width,
|
||||||
|
Alpha = 0,
|
||||||
|
Blending = BlendingMode.Additive,
|
||||||
|
Colour = ColourInfo.GradientHorizontal(gradientLight, gradientDark)
|
||||||
|
},
|
||||||
|
rightBox = new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = box_width * 2,
|
||||||
|
X = box_width,
|
||||||
|
Alpha = 0,
|
||||||
|
Blending = BlendingMode.Additive,
|
||||||
|
Colour = ColourInfo.GradientHorizontal(gradientDark, gradientLight)
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||||
|
@ -64,6 +64,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool BeatMatching = true;
|
||||||
|
|
||||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => logoContainer.ReceiveMouseInputAt(screenSpacePos);
|
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => logoContainer.ReceiveMouseInputAt(screenSpacePos);
|
||||||
|
|
||||||
public bool Ripple
|
public bool Ripple
|
||||||
@ -264,6 +266,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||||
|
|
||||||
|
if (!BeatMatching) return;
|
||||||
|
|
||||||
lastBeatIndex = beatIndex;
|
lastBeatIndex = beatIndex;
|
||||||
|
|
||||||
var beatLength = timingPoint.BeatLength;
|
var beatLength = timingPoint.BeatLength;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user