1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-30 07:52:56 +08:00

Merge branch 'master' of https://github.com/ppy/osu into Cakefy_osu!

# Conflicts:
#	appveyor.yml
This commit is contained in:
miterosan 2018-08-04 00:04:39 +02:00
commit d186d462a6
75 changed files with 724 additions and 824 deletions

View File

@ -24,7 +24,7 @@ Clone the repository including submodules
Build and run Build and run
- Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included) - Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included)
- From command line using `dotnet run --project osu.Desktop --framework netcoreapp2.1` - From command line using `dotnet run --project osu.Desktop`
If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build. If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build.

View File

@ -16,17 +16,15 @@ build_script:
- cd osu-deploy - cd osu-deploy
- nuget restore -verbosity quiet - nuget restore -verbosity quiet
- msbuild osu.Desktop.Deploy.csproj - msbuild osu.Desktop.Deploy.csproj
- cmd: ..\appveyor-tools\secure-file -decrypt ..\fdc6f19b04.enc -secret %decode_secret% -out bin\Debug\net471\osu.Desktop.Deploy.exe.config - cmd: ..\appveyor-tools\secure-file -decrypt ..\fdc6f19b04.enc -secret %decode_secret% -out bin\Debug\netcoreapp2.1\osu.Desktop.Deploy.dll.config
- cd bin\Debug\net471\ - dotnet bin/Debug/netcoreapp2.1/osu.Desktop.Deploy.dll %code_signing_password% %APPVEYOR_REPO_TAG_NAME%
- osu.Desktop.Deploy.exe %code_signing_password% %APPVEYOR_REPO_TAG_NAME%
environment: environment:
TargetFramework: net471
decode_secret: decode_secret:
secure: i67IC2xj6DjjxmA6Oj2jing3+MwzLkq6CbGsjfZ7rdY= secure: i67IC2xj6DjjxmA6Oj2jing3+MwzLkq6CbGsjfZ7rdY=
code_signing_password: code_signing_password:
secure: 34tLNqvjmmZEi97MLKfrnQ== secure: 34tLNqvjmmZEi97MLKfrnQ==
artifacts: artifacts:
- path: 'Releases\*' - path: 'osu-deploy/releases/*'
deploy: deploy:
- provider: Environment - provider: Environment
name: github name: github

View File

@ -13,6 +13,7 @@ using osu.Game;
using OpenTK.Input; using OpenTK.Input;
using Microsoft.Win32; using Microsoft.Win32;
using osu.Desktop.Updater; using osu.Desktop.Updater;
using osu.Framework;
using osu.Framework.Platform.Windows; using osu.Framework.Platform.Windows;
namespace osu.Desktop namespace osu.Desktop
@ -51,11 +52,10 @@ namespace osu.Desktop
v.State = Visibility.Visible; v.State = Visibility.Visible;
}); });
#if NET_FRAMEWORK if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
Add(new SquirrelUpdateManager()); Add(new SquirrelUpdateManager());
#else else
Add(new SimpleUpdateManager()); Add(new SimpleUpdateManager());
#endif
} }
} }

View File

@ -8,10 +8,6 @@ using osu.Framework;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.IPC; using osu.Game.IPC;
#if NET_FRAMEWORK
using System.Runtime;
#endif
namespace osu.Desktop namespace osu.Desktop
{ {
public static class Program public static class Program
@ -19,8 +15,6 @@ namespace osu.Desktop
[STAThread] [STAThread]
public static int Main(string[] args) public static int Main(string[] args)
{ {
useMultiCoreJit();
// Back up the cwd before DesktopGameHost changes it // Back up the cwd before DesktopGameHost changes it
var cwd = Environment.CurrentDirectory; var cwd = Environment.CurrentDirectory;
@ -51,14 +45,5 @@ namespace osu.Desktop
return 0; return 0;
} }
} }
private static void useMultiCoreJit()
{
#if NET_FRAMEWORK
var directory = Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Profiles"));
ProfileOptimization.SetProfileRoot(directory.FullName);
ProfileOptimization.StartProfile("Startup.Profile");
#endif
}
} }
} }

View File

@ -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
#if NET_FRAMEWORK
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -162,4 +161,3 @@ namespace osu.Desktop.Updater
} }
} }
} }
#endif

View File

@ -13,9 +13,6 @@
<Version>0.0.0</Version> <Version>0.0.0</Version>
<FileVersion>0.0.0</FileVersion> <FileVersion>0.0.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Defines">
<DefineConstants Condition="'$(TargetFramework)' == 'net471'">$(DefineConstants);NET_FRAMEWORK</DefineConstants>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>osu.Desktop.Program</StartupObject> <StartupObject>osu.Desktop.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
@ -29,11 +26,12 @@
<PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="System.IO.Packaging" Version="4.5.0" />
<PackageReference Include="ppy.squirrel.windows" Version="1.8.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" />
<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>

View File

@ -3,7 +3,7 @@
<metadata> <metadata>
<id>osulazer</id> <id>osulazer</id>
<version>0.0.0</version> <version>0.0.0</version>
<title>osulazer</title> <title>osu!lazer</title>
<authors>ppy Pty Ltd</authors> <authors>ppy Pty Ltd</authors>
<owners>Dean Herbert</owners> <owners>Dean Herbert</owners>
<projectUrl>https://osu.ppy.sh/</projectUrl> <projectUrl>https://osu.ppy.sh/</projectUrl>

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Catch.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>

View File

@ -93,13 +93,11 @@ namespace osu.Game.Rulesets.Catch
new CatchModHidden(), new CatchModHidden(),
new CatchModFlashlight(), new CatchModFlashlight(),
}; };
case ModType.Special: case ModType.Automation:
return new Mod[] return new Mod[]
{ {
new CatchModRelax(),
null,
null,
new MultiMod(new CatchModAutoplay(), new ModCinema()), new MultiMod(new CatchModAutoplay(), new ModCinema()),
new CatchModRelax(),
}; };
default: default:
return new Mod[] { }; return new Mod[] { };

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Mania.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>

View File

@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Mania
new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()),
new ManiaModFlashlight(), new ManiaModFlashlight(),
}; };
case ModType.Special: case ModType.Conversion:
return new Mod[] return new Mod[]
{ {
new MultiMod(new ManiaModKey4(), new MultiMod(new ManiaModKey4(),
@ -135,6 +135,10 @@ namespace osu.Game.Rulesets.Mania
new ManiaModRandom(), new ManiaModRandom(),
new ManiaModDualStages(), new ManiaModDualStages(),
new ManiaModMirror(), new ManiaModMirror(),
};
case ModType.Automation:
return new Mod[]
{
new MultiMod(new ManiaModAutoplay(), new ModCinema()), new MultiMod(new ManiaModAutoplay(), new ModCinema()),
}; };
default: default:

View File

@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override string ShortenedName => Name; public override string ShortenedName => Name;
public abstract int KeyCount { get; } public abstract int KeyCount { get; }
public override ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
public override bool Ranked => true; public override bool Ranked => true;

View File

@ -16,6 +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 ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
private bool isForCurrentRuleset; private bool isForCurrentRuleset;

View File

@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override string Name => "Mirror"; public override string Name => "Mirror";
public override string ShortenedName => "MR"; public override string ShortenedName => "MR";
public override ModType Type => ModType.Special; public override ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;

View File

@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override string Name => "Random"; public override string Name => "Random";
public override string ShortenedName => "RD"; public override string ShortenedName => "RD";
public override ModType Type => ModType.Conversion;
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 => 1; public override double ScoreMultiplier => 1;

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Osu.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>

View File

@ -12,6 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Name => "Autopilot"; public override string Name => "Autopilot";
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 ModType Type => ModType.Automation;
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 => 1; public override double ScoreMultiplier => 1;
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) };

View File

@ -12,6 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Name => "Spun Out"; public override string Name => "Spun Out";
public override string ShortenedName => "SO"; public override string ShortenedName => "SO";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
public override ModType Type => ModType.DifficultyReduction;
public override string Description => @"Spinners will be automatically completed."; public override string Description => @"Spinners will be automatically completed.";
public override double ScoreMultiplier => 0.9; public override double ScoreMultiplier => 0.9;
public override bool Ranked => true; public override bool Ranked => true;

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override string Name => "Target"; public override string Name => "Target";
public override string ShortenedName => "TP"; public override string ShortenedName => "TP";
public override ModType Type => ModType.Conversion;
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
public override string Description => @"Practice keeping up with the beat of the song."; public override string Description => @"Practice keeping up with the beat of the song.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
@ -20,27 +21,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Masking = true; Child = new SkinnableDrawable("Play/osu/followpoint", _ => new Container
AutoSizeAxes = Axes.Both;
CornerRadius = width / 2;
EdgeEffect = new EdgeEffectParameters
{ {
Type = EdgeEffectType.Glow, Masking = true,
Colour = Color4.White.Opacity(0.2f), AutoSizeAxes = Axes.Both,
Radius = 4, CornerRadius = width / 2,
}; EdgeEffect = new EdgeEffectParameters
{
Children = new Drawable[] Type = EdgeEffectType.Glow,
{ Colour = Color4.White.Opacity(0.2f),
new Box Radius = 4,
},
Child = new Box
{ {
Size = new Vector2(width), Size = new Vector2(width),
Blending = BlendingMode.Additive, Blending = BlendingMode.Additive,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Alpha = 0.5f, Alpha = 0.5f,
}, }
}; }, restrictSize: false);
} }
} }
} }

View File

@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
Vector2 distanceVector = endPosition - startPosition; Vector2 distanceVector = endPosition - startPosition;
int distance = (int)distanceVector.Length; int distance = (int)distanceVector.Length;
float rotation = (float)Math.Atan2(distanceVector.Y, distanceVector.X); float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
double duration = endTime - startTime; double duration = endTime - startTime;
for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance) for (int d = (int)(PointDistance * 1.5); d < distance - PointDistance; d += PointDistance)

View File

@ -10,6 +10,7 @@ using OpenTK;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -33,11 +34,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new SpriteIcon new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_chevron_right Icon = FontAwesome.fa_chevron_right
} }, restrictSize: false)
}; };
} }
@ -74,6 +75,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
private bool hasRotation;
public void UpdateSnakingPosition(Vector2 start, Vector2 end) public void UpdateSnakingPosition(Vector2 start, Vector2 end)
{ {
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0; bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
@ -87,15 +90,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0; int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0;
int direction = isRepeatAtEnd ? -1 : 1; int direction = isRepeatAtEnd ? -1 : 1;
Vector2 aimRotationVector = Vector2.Zero;
// find the next vector2 in the curve which is not equal to our current position to infer a rotation. // find the next vector2 in the curve which is not equal to our current position to infer a rotation.
for (int i = searchStart; i >= 0 && i < curve.Count; i += direction) for (int i = searchStart; i >= 0 && i < curve.Count; i += direction)
{ {
if (Precision.AlmostEquals(curve[i], Position)) if (Precision.AlmostEquals(curve[i], Position))
continue; continue;
Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X)); aimRotationVector = curve[i];
break; break;
} }
float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X));
while (Math.Abs(aimRotation - Rotation) > 180)
aimRotation += aimRotation < Rotation ? 360 : -360;
if (!hasRotation)
{
Rotation = aimRotation;
hasRotation = true;
}
else
{
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
Rotation = Interpolation.ValueAt(MathHelper.Clamp(Clock.ElapsedFrameTime, 0, 100), Rotation, aimRotation, 0, 50, Easing.OutQuint);
}
} }
} }
} }

View File

@ -8,6 +8,8 @@ using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -22,23 +24,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
{ {
Size = new Vector2(16) * sliderTick.Scale; Size = new Vector2(16) * sliderTick.Scale;
Masking = true;
CornerRadius = Size.X / 2;
Origin = Anchor.Centre; Origin = Anchor.Centre;
BorderThickness = 2;
BorderColour = Color4.White;
InternalChildren = new Drawable[] InternalChildren = new Drawable[]
{ {
new Box new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new Container
{ {
Masking = true,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = AccentColour, Origin = Anchor.Centre,
Alpha = 0.3f, CornerRadius = Size.X / 2,
}
BorderThickness = 2,
BorderColour = Color4.White,
Child = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = AccentColour,
Alpha = 0.3f,
}
}, restrictSize: false)
}; };
} }

View File

@ -10,6 +10,7 @@ using osu.Framework.Input.States;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
@ -18,6 +19,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private const float width = 128; private const float width = 128;
private Color4 accentColour = Color4.Black; private Color4 accentColour = Color4.Black;
/// <summary> /// <summary>
/// The colour that is used for the slider ball. /// The colour that is used for the slider ball.
/// </summary> /// </summary>
@ -27,14 +29,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
set set
{ {
accentColour = value; accentColour = value;
if (ball != null) if (drawableBall != null)
ball.Colour = value; drawableBall.Colour = value;
} }
} }
private readonly Slider slider; private readonly Slider slider;
public readonly Box FollowCircle; public readonly Drawable FollowCircle;
private readonly Box ball; private Drawable drawableBall;
public SliderBall(Slider slider) public SliderBall(Slider slider)
{ {
@ -43,19 +45,30 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Blending = BlendingMode.Additive; Blending = BlendingMode.Additive;
Origin = Anchor.Centre; Origin = Anchor.Centre;
BorderThickness = 10;
BorderColour = Color4.Orange;
Children = new Drawable[] Children = new[]
{ {
FollowCircle = new Box FollowCircle = new Container
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Colour = Color4.Orange,
Width = width, Width = width,
Height = width, Height = width,
Alpha = 0, Alpha = 0,
Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = 5,
BorderColour = Color4.Orange,
Blending = BlendingMode.Additive,
Child = new Box
{
Colour = Color4.Orange,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
}
}),
}, },
new CircularContainer new CircularContainer
{ {
@ -63,18 +76,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
BorderThickness = 10,
BorderColour = Color4.White,
Alpha = 1, Alpha = 1,
Children = new[] Child = new Container
{ {
ball = new Box Width = width,
Height = width,
// TODO: support skin filename animation (sliderb0, sliderb1...)
Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer
{ {
Colour = AccentColour, Masking = true,
Alpha = 0.4f, RelativeSizeAxes = Axes.Both,
Width = width, BorderThickness = 10,
Height = width, BorderColour = Color4.White,
}, Alpha = 1,
Child = drawableBall = new Box
{
Colour = AccentColour,
RelativeSizeAxes = Axes.Both,
Alpha = 0.4f,
}
}),
} }
} }
}; };
@ -111,6 +132,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
} }
private bool tracking; private bool tracking;
public bool Tracking public bool Tracking
{ {
get { return tracking; } get { return tracking; }
@ -120,8 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
return; return;
tracking = value; tracking = value;
FollowCircle.ScaleTo(tracking ? 2.8f : 1, 300, Easing.OutQuint); FollowCircle.ScaleTo(tracking ? 2f : 1, 300, Easing.OutQuint);
FollowCircle.FadeTo(tracking ? 0.2f : 0, 300, Easing.OutQuint); FollowCircle.FadeTo(tracking ? 1f : 0, 300, Easing.OutQuint);
} }
} }

View File

@ -16,6 +16,9 @@ namespace osu.Game.Rulesets.Osu.Objects
{ {
base.ApplyDefaultsToSelf(controlPointInfo, difficulty); base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
// Out preempt should be one span early to give the user ample warning.
TimePreempt += SpanDuration;
// We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders // We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders
// we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time. // we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time.
if (RepeatIndex > 0) if (RepeatIndex > 0)

View File

@ -94,6 +94,7 @@ namespace osu.Game.Rulesets.Osu
new OsuModEasy(), new OsuModEasy(),
new OsuModNoFail(), new OsuModNoFail(),
new MultiMod(new OsuModHalfTime(), new OsuModDaycore()), new MultiMod(new OsuModHalfTime(), new OsuModDaycore()),
new OsuModSpunOut(),
}; };
case ModType.DifficultyIncrease: case ModType.DifficultyIncrease:
return new Mod[] return new Mod[]
@ -104,14 +105,17 @@ namespace osu.Game.Rulesets.Osu
new OsuModHidden(), new OsuModHidden(),
new OsuModFlashlight(), new OsuModFlashlight(),
}; };
case ModType.Special: case ModType.Conversion:
return new Mod[] return new Mod[]
{ {
new OsuModTarget(),
};
case ModType.Automation:
return new Mod[]
{
new MultiMod(new OsuModAutoplay(), new ModCinema()),
new OsuModRelax(), new OsuModRelax(),
new OsuModAutopilot(), new OsuModAutopilot(),
new OsuModSpunOut(),
new MultiMod(new OsuModAutoplay(), new ModCinema()),
new OsuModTarget(),
}; };
default: default:
return new Mod[] { }; return new Mod[] { };

View File

@ -2,35 +2,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net471)", "name": "VisualTests (Debug)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Release, net471)",
"windows": {
"type": "clr"
},
"type": "mono",
"request": "launch",
"program": "${workspaceRoot}/bin/Release/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null,
"env": {},
"console": "internalConsole"
},
{
"name": "VisualTests (Debug, netcoreapp2.1)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -38,12 +10,12 @@
"${workspaceRoot}/bin/Debug/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, netcoreapp2.1)", "name": "VisualTests (Release)",
"type": "coreclr", "type": "coreclr",
"request": "launch", "request": "launch",
"program": "dotnet", "program": "dotnet",
@ -51,7 +23,7 @@
"${workspaceRoot}/bin/Release/netcoreapp2.1/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)",
"env": {}, "env": {},
"console": "internalConsole" "console": "internalConsole"
} }

View File

@ -4,43 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build (Debug, msbuild)", "label": "Build (Debug)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Release, msbuild)",
"type": "shell",
"command": "msbuild",
"args": [
"osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:Configuration=Release",
"/p:TargetFramework=net471",
"/p:GenerateFullPaths=true",
"/m",
"/verbosity:m"
],
"group": "build",
"problemMatcher": "$msCompile"
},
{
"label": "Build (Debug, dotnet)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -49,14 +19,13 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Build (Release, dotnet)", "label": "Build (Release)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [
"build", "build",
"--no-restore", "--no-restore",
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=netcoreapp2.1",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
@ -66,16 +35,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net471)", "label": "Restore",
"type": "shell",
"command": "nuget",
"args": [
"restore"
],
"problemMatcher": []
},
{
"label": "Restore (netcoreapp2.1)",
"type": "shell", "type": "shell",
"command": "dotnet", "command": "dotnet",
"args": [ "args": [

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>

View File

@ -93,13 +93,11 @@ namespace osu.Game.Rulesets.Taiko
new TaikoModHidden(), new TaikoModHidden(),
new TaikoModFlashlight(), new TaikoModFlashlight(),
}; };
case ModType.Special: case ModType.Automation:
return new Mod[] return new Mod[]
{ {
new TaikoModRelax(),
null,
null,
new MultiMod(new TaikoModAutoplay(), new ModCinema()), new MultiMod(new TaikoModAutoplay(), new ModCinema()),
new TaikoModRelax(),
}; };
default: default:
return new Mod[] { }; return new Mod[] { };

View File

@ -530,7 +530,7 @@ namespace osu.Game.Tests.Visual
{ {
public new List<DrawableCarouselItem> Items => base.Items; public new List<DrawableCarouselItem> Items => base.Items;
public bool PendingFilterTask => FilterTask != null; public bool PendingFilterTask => PendingFilter != null;
} }
} }
} }

View File

@ -16,6 +16,7 @@ using System.Collections.Generic;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Overlays.Mods.Sections;
using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -36,7 +37,9 @@ namespace osu.Game.Tests.Visual
typeof(ModButtonEmpty), typeof(ModButtonEmpty),
typeof(DifficultyReductionSection), typeof(DifficultyReductionSection),
typeof(DifficultyIncreaseSection), typeof(DifficultyIncreaseSection),
typeof(SpecialSection), typeof(AutomationSection),
typeof(ConversionSection),
typeof(FunSection),
}; };
private RulesetStore rulesets; private RulesetStore rulesets;
@ -95,7 +98,7 @@ namespace osu.Game.Tests.Visual
{ {
var easierMods = ruleset.GetModsFor(ModType.DifficultyReduction); var easierMods = ruleset.GetModsFor(ModType.DifficultyReduction);
var harderMods = ruleset.GetModsFor(ModType.DifficultyIncrease); var harderMods = ruleset.GetModsFor(ModType.DifficultyIncrease);
var assistMods = ruleset.GetModsFor(ModType.Special); var assistMods = ruleset.GetModsFor(ModType.Automation);
var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail);
var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden);
@ -119,7 +122,7 @@ namespace osu.Game.Tests.Visual
private void testManiaMods(ManiaRuleset ruleset) private void testManiaMods(ManiaRuleset ruleset)
{ {
testRankedText(ruleset.GetModsFor(ModType.Special).First(m => m is ManiaModRandom)); testRankedText(ruleset.GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom));
} }
private void testSingleMod(Mod mod) private void testSingleMod(Mod mod)

View File

@ -54,6 +54,8 @@ namespace osu.Game.Tests.Visual
public new BeatmapCarousel Carousel => base.Carousel; public new BeatmapCarousel Carousel => base.Carousel;
} }
private TestSongSelect songSelect;
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
factory.ResetDatabase(); factory.ResetDatabase();
@ -63,11 +65,14 @@ namespace osu.Game.Tests.Visual
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
TestSongSelect songSelect = null;
factory = new DatabaseContextFactory(LocalStorage); factory = new DatabaseContextFactory(LocalStorage);
factory.ResetDatabase(); factory.ResetDatabase();
using (var usage = factory.Get())
usage.Migrate();
factory.ResetDatabase();
using (var usage = factory.Get()) using (var usage = factory.Get())
usage.Migrate(); usage.Migrate();
@ -77,42 +82,35 @@ namespace osu.Game.Tests.Visual
DefaultBeatmap = defaultBeatmap = Beatmap.Default DefaultBeatmap = defaultBeatmap = Beatmap.Default
}); });
void loadNewSongSelect(bool deleteMaps = false) => AddStep("reload song select", () => Beatmap.SetDefault();
{ }
if (deleteMaps)
{
manager.Delete(manager.GetAllUsableBeatmapSets());
Beatmap.SetDefault();
}
if (songSelect != null) [SetUp]
{ public virtual void SetUp()
Remove(songSelect); {
songSelect.Dispose(); manager?.Delete(manager.GetAllUsableBeatmapSets());
} Child = songSelect = new TestSongSelect();
}
Add(songSelect = new TestSongSelect());
});
loadNewSongSelect(true);
AddWaitStep(3);
[Test]
public void TestDummy()
{
AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap); AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap);
AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap); AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap);
AddStep("import test maps", () => addManyTestMaps();
{
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i));
});
AddWaitStep(3); AddWaitStep(3);
AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
}
loadNewSongSelect(); [Test]
public void TestSorting()
{
addManyTestMaps();
AddWaitStep(3); AddWaitStep(3);
AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
@ -121,55 +119,84 @@ namespace osu.Game.Tests.Visual
AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; });
} }
private BeatmapSetInfo createTestBeatmapSet(int i) [Test]
[Ignore("needs fixing")]
public void ImportUnderDifferentRuleset()
{ {
changeRuleset(2);
importForRuleset(0);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection");
}
[Test]
public void ImportUnderCurrentRuleset()
{
changeRuleset(2);
importForRuleset(2);
importForRuleset(1);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 2, "has selection");
changeRuleset(1);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 1, "has selection");
changeRuleset(0);
AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection");
}
private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())));
private static int importId;
private int getImportId() => ++importId;
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
private void addManyTestMaps()
{
AddStep("import test maps", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i, usableRulesets));
});
}
private BeatmapSetInfo createTestBeatmapSet(int setId, RulesetInfo[] rulesets)
{
int j = 0;
RulesetInfo getRuleset() => rulesets[j++ % rulesets.Length];
var beatmaps = new List<BeatmapInfo>();
for (int i = 0; i < 6; i++)
{
int beatmapId = setId * 10 + i;
beatmaps.Add(new BeatmapInfo
{
Ruleset = getRuleset(),
OnlineBeatmapID = beatmapId,
Path = "normal.osu",
Version = $"{beatmapId}",
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 3.5f,
}
});
}
return new BeatmapSetInfo return new BeatmapSetInfo
{ {
OnlineBeatmapSetID = 1234 + i, OnlineBeatmapSetID = setId,
Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
Metadata = new BeatmapMetadata Metadata = new BeatmapMetadata
{ {
// Create random metadata, then we can check if sorting works based on these // Create random metadata, then we can check if sorting works based on these
Artist = "MONACA " + RNG.Next(0, 9), Artist = "Some Artist " + RNG.Next(0, 9),
Title = "Black Song " + RNG.Next(0, 9), Title = $"Some Song (set id {setId})",
AuthorString = "Some Guy " + RNG.Next(0, 9), AuthorString = "Some Guy " + RNG.Next(0, 9),
}, },
Beatmaps = new List<BeatmapInfo>(new[] Beatmaps = beatmaps
{
new BeatmapInfo
{
OnlineBeatmapID = 1234 + i,
Ruleset = rulesets.AvailableRulesets.First(),
Path = "normal.osu",
Version = "Normal",
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 3.5f,
}
},
new BeatmapInfo
{
OnlineBeatmapID = 1235 + i,
Ruleset = rulesets.AvailableRulesets.First(),
Path = "hard.osu",
Version = "Hard",
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 5,
}
},
new BeatmapInfo
{
OnlineBeatmapID = 1236 + i,
Ruleset = rulesets.AvailableRulesets.First(),
Path = "insane.osu",
Version = "Insane",
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 7,
}
},
}),
}; };
} }
} }

View File

@ -54,11 +54,11 @@ namespace osu.Game.Tests.Visual
breadcrumbs.Current.TriggerChange(); breadcrumbs.Current.TriggerChange();
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
assertCurrent(); waitForCurrent();
AddStep(@"make start current", () => AddStep(@"make start current", () =>
{ {
@ -66,8 +66,9 @@ namespace osu.Game.Tests.Visual
currentScreen = startScreen; currentScreen = startScreen;
}); });
assertCurrent(); waitForCurrent();
pushNext(); pushNext();
waitForCurrent();
AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2); AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2);
AddStep(@"exit current", () => changedScreen.Exit()); AddStep(@"exit current", () => changedScreen.Exit());
AddAssert(@"current screen is first", () => startScreen == changedScreen); AddAssert(@"current screen is first", () => startScreen == changedScreen);
@ -80,7 +81,7 @@ namespace osu.Game.Tests.Visual
} }
private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext());
private void assertCurrent() => AddAssert(@"changedScreen correct", () => currentScreen == changedScreen); private void waitForCurrent() => AddUntilStep(() => currentScreen.IsCurrentScreen, "current screen");
private abstract class TestScreen : OsuScreen private abstract class TestScreen : OsuScreen
{ {

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.10.0" />
</ItemGroup> </ItemGroup>

View File

@ -134,6 +134,8 @@ namespace osu.Game.Beatmaps
return converted; return converted;
} }
public override string ToString() => BeatmapInfo.ToString();
public bool BackgroundLoaded => background.IsResultAvailable; public bool BackgroundLoaded => background.IsResultAvailable;
public Texture Background => background.Value.Result; public Texture Background => background.Value.Result;
public async Task<Texture> GetBackgroundAsync() => await background.Value; public async Task<Texture> GetBackgroundAsync() => await background.Value;

View File

@ -37,7 +37,7 @@ namespace osu.Game.Graphics.UserInterface
{ {
TabContainer.Spacing = new Vector2(10f, 0f); TabContainer.Spacing = new Vector2(10f, 0f);
Add(strip = new Box AddInternal(strip = new Box
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,

View File

@ -6,7 +6,7 @@ using osu.Game.Users;
namespace osu.Game.Online.Chat namespace osu.Game.Online.Chat
{ {
public class InfoMessage : Message public class InfoMessage : LocalMessage
{ {
private static int infoID = -1; private static int infoID = -1;

View File

@ -3,7 +3,7 @@
namespace osu.Game.Online.Chat namespace osu.Game.Online.Chat
{ {
public class LocalEchoMessage : Message public class LocalEchoMessage : LocalMessage
{ {
public LocalEchoMessage() : base(null) public LocalEchoMessage() : base(null)
{ {

View File

@ -0,0 +1,16 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Online.Chat
{
/// <summary>
/// A message which is generated and displayed locally.
/// </summary>
public class LocalMessage : Message
{
protected LocalMessage(long? id)
: base(id)
{
}
}
}

View File

@ -197,7 +197,13 @@ namespace osu.Game
return; return;
} }
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First()); var databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID);
// Use first beatmap available for current ruleset, else switch ruleset.
var first = databasedSet.Beatmaps.FirstOrDefault(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First();
ruleset.Value = first.Ruleset;
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);
} }
switch (currentScreen) switch (currentScreen)

View File

@ -1,18 +1,28 @@
// 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 osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Game.Beatmaps; 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.Online.API;
using osu.Game.Users;
using OpenTK; using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Overlays.BeatmapSet.Buttons namespace osu.Game.Overlays.BeatmapSet.Buttons
{ {
public class DownloadButton : HeaderButton public class DownloadButton : HeaderButton, IHasTooltip
{ {
public string TooltipText => Enabled ? null : "You gotta be an osu!supporter to download for now 'yo";
private readonly IBindable<User> localUser = new Bindable<User>();
public DownloadButton(BeatmapSetInfo set, bool noVideo = false) public DownloadButton(BeatmapSetInfo set, bool noVideo = false)
{ {
Width = 120; Width = 120;
@ -86,5 +96,17 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
} }
}; };
} }
[BackgroundDependencyLoader]
private void load(APIAccess api)
{
localUser.BindTo(api.LocalUser);
localUser.BindValueChanged(userChanged, true);
Enabled.BindValueChanged(enabledChanged, true);
}
private void userChanged(User user) => Enabled.Value = user.IsSupporter;
private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint);
} }
} }

View File

@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Chat
if (!IsLoaded) return; if (!IsLoaded) return;
if (scroll.IsScrolledToEnd(10) || !flow.Children.Any()) if (scroll.IsScrolledToEnd(10) || !flow.Children.Any() || newMessages.Any(m => m is LocalMessage))
scrollToEnd(); scrollToEnd();
var staleMessages = flow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray(); var staleMessages = flow.Children.Where(c => c.LifetimeEnd == double.MaxValue).ToArray();

View File

@ -14,6 +14,7 @@ namespace osu.Game.Overlays.Direct
{ {
public class DownloadButton : OsuAnimatedButton public class DownloadButton : OsuAnimatedButton
{ {
private readonly BeatmapSetInfo beatmapSet;
private readonly SpriteIcon icon; private readonly SpriteIcon icon;
private readonly SpriteIcon checkmark; private readonly SpriteIcon checkmark;
private readonly BeatmapSetDownloader downloader; private readonly BeatmapSetDownloader downloader;
@ -21,11 +22,13 @@ namespace osu.Game.Overlays.Direct
private OsuColour colours; private OsuColour colours;
public DownloadButton(BeatmapSetInfo set, bool noVideo = false) public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false)
{ {
this.beatmapSet = beatmapSet;
AddRange(new Drawable[] AddRange(new Drawable[]
{ {
downloader = new BeatmapSetDownloader(set, noVideo), downloader = new BeatmapSetDownloader(beatmapSet, noVideo),
background = new Box background = new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -47,26 +50,6 @@ namespace osu.Game.Overlays.Direct
Icon = FontAwesome.fa_check, Icon = FontAwesome.fa_check,
} }
}); });
Action = () =>
{
if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloading)
{
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged.
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
}
else if (downloader.DownloadState == BeatmapSetDownloader.DownloadStatus.Downloaded)
{
// TODO: Jump to song select with this set when the capability is implemented
}
else
{
downloader.Download();
}
};
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -77,9 +60,29 @@ namespace osu.Game.Overlays.Direct
} }
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours) private void load(OsuColour colours, OsuGame game)
{ {
this.colours = colours; this.colours = colours;
Action = () =>
{
switch (downloader.DownloadState.Value)
{
case BeatmapSetDownloader.DownloadStatus.Downloading:
// todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged.
Content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine);
break;
case BeatmapSetDownloader.DownloadStatus.Downloaded:
game.PresentBeatmap(beatmapSet);
break;
default:
downloader.Download();
break;
}
};
} }
private void updateState(BeatmapSetDownloader.DownloadStatus state) private void updateState(BeatmapSetDownloader.DownloadStatus state)

View File

@ -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 OpenTK; using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input; using OpenTK.Input;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -45,7 +44,6 @@ namespace osu.Game.Overlays.Mods
return new ModButton(m) return new ModButton(m)
{ {
SelectedColour = selectedColour,
SelectionChanged = Action, SelectionChanged = Action,
}; };
}).ToArray(); }).ToArray();
@ -57,25 +55,14 @@ namespace osu.Game.Overlays.Mods
private ModButton[] buttons = { }; private ModButton[] buttons = { };
private Color4 selectedColour = Color4.White;
public Color4 SelectedColour
{
get => selectedColour;
set
{
if (value == selectedColour) return;
selectedColour = value;
foreach (ModButton button in buttons)
button.SelectedColour = value;
}
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{ {
var index = Array.IndexOf(ToggleKeys, args.Key); if (ToggleKeys != null)
if (index > -1 && index < buttons.Length) {
buttons[index].SelectNext(state.Keyboard.ShiftPressed ? -1 : 1); var index = Array.IndexOf(ToggleKeys, args.Key);
if (index > -1 && index < buttons.Length)
buttons[index].SelectNext(state.Keyboard.ShiftPressed ? -1 : 1);
}
return base.OnKeyDown(state, args); return base.OnKeyDown(state, args);
} }
@ -125,6 +112,10 @@ namespace osu.Game.Overlays.Mods
protected ModSection() protected ModSection()
{ {
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X;
Origin = Anchor.TopCentre;
Anchor = Anchor.TopCentre;
Children = new Drawable[] Children = new Drawable[]
{ {

View File

@ -21,6 +21,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Mods.Sections;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
@ -188,6 +189,7 @@ namespace osu.Game.Overlays.Mods
Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e");
Height = 510; Height = 510;
Children = new Drawable[] Children = new Drawable[]
{ {
new Container new Container
@ -211,178 +213,172 @@ namespace osu.Game.Overlays.Mods
}, },
}, },
}, },
new FillFlowContainer new GridContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.Both,
AutoSizeAxes = Axes.Y,
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
Direction = FillDirection.Vertical, RowDimensions = new[]
Spacing = new Vector2(0f, 10f),
Children = new Drawable[]
{ {
// Header new Dimension(GridSizeMode.Absolute, 90),
new Container new Dimension(GridSizeMode.Distributed),
new Dimension(GridSizeMode.Absolute, 70),
},
Content = new[]
{
new Drawable[]
{ {
RelativeSizeAxes = Axes.X, new Container
Height = 82,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Children = new Drawable[]
{ {
new Box RelativeSizeAxes = Axes.Both,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.Both, new Box
Colour = OsuColour.Gray(10).Opacity(100),
},
new FillFlowContainer
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Width = content_width,
Padding = new MarginPadding
{ {
Top = 10, RelativeSizeAxes = Axes.Both,
Bottom = 10, Colour = OsuColour.Gray(10).Opacity(100),
}, },
Children = new Drawable[] new FillFlowContainer
{ {
new OsuSpriteText Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Width = content_width,
Children = new Drawable[]
{ {
Font = @"Exo2.0-Bold", new OsuSpriteText
Text = @"Gameplay Mods",
TextSize = 22,
Shadow = true,
Margin = new MarginPadding
{ {
Bottom = 4, Font = @"Exo2.0-Bold",
Text = @"Gameplay Mods",
TextSize = 22,
Shadow = true,
Margin = new MarginPadding
{
Bottom = 4,
},
},
new OsuTextFlowContainer(text =>
{
text.TextSize = 18;
text.Shadow = true;
})
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Text = "Mods provide different ways to enjoy gameplay. Some have an effect on the score you can achieve during ranked play.\nOthers are just for fun.",
}, },
},
new OsuSpriteText
{
Text = @"Mods provide different ways to enjoy gameplay. Some have an effect on the score you can achieve during ranked play.",
TextSize = 18,
Shadow = true,
},
new OsuSpriteText
{
Text = @"Others are just for fun.",
TextSize = 18,
Shadow = true,
}, },
}, },
}, },
}, },
}, },
// Body new Drawable[]
ModSectionsContainer = new FillFlowContainer<ModSection>
{ {
Origin = Anchor.TopCentre, // Body
Anchor = Anchor.TopCentre, new OsuScrollContainer
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(0f, 10f),
Width = content_width,
Children = new ModSection[]
{ {
new DifficultyReductionSection ScrollbarVisible = false,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Vertical = 10 },
Child = ModSectionsContainer = new FillFlowContainer<ModSection>
{ {
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
new DifficultyIncreaseSection
{
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
new SpecialSection
{
RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Action = modButtonPressed,
},
}
},
// Footer
new Container
{
RelativeSizeAxes = Axes.X,
Height = 70,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = new Color4(172, 20, 116, 255),
Alpha = 0.5f,
},
footerContainer = new FillFlowContainer
{
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X, Spacing = new Vector2(0f, 10f),
Width = content_width, Width = content_width,
Direction = FillDirection.Horizontal, Children = new ModSection[]
Padding = new MarginPadding
{ {
Vertical = 15 new DifficultyReductionSection { Action = modButtonPressed },
new DifficultyIncreaseSection { Action = modButtonPressed },
new AutomationSection { Action = modButtonPressed },
new ConversionSection { Action = modButtonPressed },
new FunSection { Action = modButtonPressed },
}
},
},
},
new Drawable[]
{
// Footer
new Container
{
RelativeSizeAxes = Axes.Both,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = new Color4(172, 20, 116, 255),
Alpha = 0.5f,
}, },
Children = new Drawable[] footerContainer = new FillFlowContainer
{ {
DeselectAllButton = new TriangleButton Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Width = content_width,
Direction = FillDirection.Horizontal,
Padding = new MarginPadding
{ {
Width = 180, Vertical = 15
Text = "Deselect All",
Action = DeselectAll,
Margin = new MarginPadding
{
Right = 20
}
}, },
new OsuSpriteText Children = new Drawable[]
{ {
Text = @"Score Multiplier:", DeselectAllButton = new TriangleButton
TextSize = 30,
Margin = new MarginPadding
{ {
Top = 5, Width = 180,
Right = 10 Text = "Deselect All",
} Action = DeselectAll,
}, Margin = new MarginPadding
MultiplierLabel = new OsuSpriteText {
{ Right = 20
Font = @"Exo2.0-Bold", }
TextSize = 30, },
Margin = new MarginPadding new OsuSpriteText
{ {
Top = 5 Text = @"Score Multiplier:",
} TextSize = 30,
}, Margin = new MarginPadding
UnrankedLabel = new OsuSpriteText {
{ Top = 5,
Font = @"Exo2.0-Bold", Right = 10
Text = @"(Unranked)", }
TextSize = 30, },
Margin = new MarginPadding MultiplierLabel = new OsuSpriteText
{ {
Top = 5, Font = @"Exo2.0-Bold",
Left = 10 TextSize = 30,
Margin = new MarginPadding
{
Top = 5
}
},
UnrankedLabel = new OsuSpriteText
{
Font = @"Exo2.0-Bold",
Text = @"(Unranked)",
TextSize = 30,
Margin = new MarginPadding
{
Top = 5,
Left = 10
}
} }
} }
} }
} },
}, }
}, },
}, },
}, },

View File

@ -0,0 +1,19 @@
// 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.Game.Rulesets.Mods;
using OpenTK.Input;
namespace osu.Game.Overlays.Mods.Sections
{
public class AutomationSection : ModSection
{
protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M };
public override ModType ModType => ModType.Automation;
public AutomationSection()
{
Header = @"Automation";
}
}
}

View File

@ -0,0 +1,19 @@
// 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.Game.Rulesets.Mods;
using OpenTK.Input;
namespace osu.Game.Overlays.Mods.Sections
{
public class ConversionSection : ModSection
{
protected override Key[] ToggleKeys => null;
public override ModType ModType => ModType.Conversion;
public ConversionSection()
{
Header = @"Conversion";
}
}
}

View File

@ -1,24 +1,16 @@
// 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 OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using OpenTK.Input;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods.Sections
{ {
public class DifficultyIncreaseSection : ModSection public class DifficultyIncreaseSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L }; protected override Key[] ToggleKeys => new[] { Key.A, Key.S, Key.D, Key.F, Key.G, Key.H, Key.J, Key.K, Key.L };
public override ModType ModType => ModType.DifficultyIncrease; public override ModType ModType => ModType.DifficultyIncrease;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
SelectedColour = colours.YellowLight;
}
public DifficultyIncreaseSection() public DifficultyIncreaseSection()
{ {
Header = @"Difficulty Increase"; Header = @"Difficulty Increase";

View File

@ -1,24 +1,16 @@
// 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 OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using OpenTK.Input;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods.Sections
{ {
public class DifficultyReductionSection : ModSection public class DifficultyReductionSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P }; protected override Key[] ToggleKeys => new[] { Key.Q, Key.W, Key.E, Key.R, Key.T, Key.Y, Key.U, Key.I, Key.O, Key.P };
public override ModType ModType => ModType.DifficultyReduction; public override ModType ModType => ModType.DifficultyReduction;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
SelectedColour = colours.GreenLight;
}
public DifficultyReductionSection() public DifficultyReductionSection()
{ {
Header = @"Difficulty Reduction"; Header = @"Difficulty Reduction";

View File

@ -0,0 +1,19 @@
// 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.Game.Rulesets.Mods;
using OpenTK.Input;
namespace osu.Game.Overlays.Mods.Sections
{
public class FunSection : ModSection
{
protected override Key[] ToggleKeys => null;
public override ModType ModType => ModType.Fun;
public FunSection()
{
Header = @"Fun";
}
}
}

View File

@ -1,27 +0,0 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Input;
using osu.Framework.Allocation;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Overlays.Mods
{
public class SpecialSection : ModSection
{
protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M };
public override ModType ModType => ModType.Special;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
SelectedColour = colours.BlueLight;
}
public SpecialSection()
{
Header = @"Special";
}
}
}

View File

@ -195,7 +195,7 @@ namespace osu.Game.Overlays
TabContainer.AutoSizeAxes |= Axes.X; TabContainer.AutoSizeAxes |= Axes.X;
TabContainer.Anchor |= Anchor.x1; TabContainer.Anchor |= Anchor.x1;
TabContainer.Origin |= Anchor.x1; TabContainer.Origin |= Anchor.x1;
Add(bottom = new Box AddInternal(bottom = new Box
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 1, Height = 1,

View File

@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mods
/// <summary> /// <summary>
/// The type of this mod. /// The type of this mod.
/// </summary> /// </summary>
public virtual ModType Type => ModType.Special; public virtual ModType Type => ModType.Fun;
/// <summary> /// <summary>
/// The user readable description of this mod. /// The user readable description of this mod.

View File

@ -26,6 +26,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => "Autoplay"; public override string Name => "Autoplay";
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 ModType Type => ModType.Automation;
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 => 1; public override double ScoreMultiplier => 1;
public bool AllowFail => false; public bool AllowFail => false;

View File

@ -11,6 +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 ModType Type => ModType.Automation;
public override double ScoreMultiplier => 1; 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) };
} }

View File

@ -7,6 +7,8 @@ namespace osu.Game.Rulesets.Mods
{ {
DifficultyReduction, DifficultyReduction,
DifficultyIncrease, DifficultyIncrease,
Special Conversion,
Automation,
Fun
} }
} }

View File

@ -25,5 +25,7 @@ namespace osu.Game.Rulesets
public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this);
public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo;
public override string ToString() => $"{Name} ({ShortName}) ID: {ID}";
} }
} }

View File

@ -79,10 +79,18 @@ namespace osu.Game.Rulesets.UI
backgroundColour = colours.Green; backgroundColour = colours.Green;
highlightedColour = colours.GreenLight; highlightedColour = colours.GreenLight;
break; break;
case ModType.Special: case ModType.Automation:
backgroundColour = colours.Blue; backgroundColour = colours.Blue;
highlightedColour = colours.BlueLight; highlightedColour = colours.BlueLight;
break; break;
case ModType.Conversion:
backgroundColour = colours.Purple;
highlightedColour = colours.PurpleLight;
break;
case ModType.Fun:
backgroundColour = colours.Pink;
highlightedColour = colours.PinkLight;
break;
} }
applyStyle(); applyStyle();
@ -92,10 +100,7 @@ namespace osu.Game.Rulesets.UI
public bool Highlighted public bool Highlighted
{ {
get get { return highlighted; }
{
return highlighted;
}
set set
{ {

View File

@ -25,7 +25,7 @@ namespace osu.Game.Screens.Edit.Menus
TabContainer.AutoSizeAxes = Axes.X; TabContainer.AutoSizeAxes = Axes.X;
TabContainer.Padding = new MarginPadding(); TabContainer.Padding = new MarginPadding();
Add(new Box AddInternal(new Box
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,

View File

@ -213,7 +213,7 @@ namespace osu.Game.Screens.Play
{ {
if (!IsCurrentScreen) return; if (!IsCurrentScreen) return;
pauseContainer.Hide(); fadeOut(true);
Restart(); Restart();
}, },
} }
@ -364,16 +364,10 @@ namespace osu.Game.Screens.Play
return true; return true;
} }
private void fadeOut() private void fadeOut(bool instant = false)
{ {
const float fade_out_duration = 250; float fadeOutDuration = instant ? 0 : 250;
Content.FadeOut(fadeOutDuration);
RulesetContainer?.FadeOut(fade_out_duration);
Content.FadeOut(fade_out_duration);
hudOverlay?.ScaleTo(0.7f, fade_out_duration * 3, Easing.In);
Background?.FadeTo(1f, fade_out_duration);
} }
protected override bool OnScroll(InputState state) => mouseWheelDisabled.Value && !pauseContainer.IsPaused; protected override bool OnScroll(InputState state) => mouseWheelDisabled.Value && !pauseContainer.IsPaused;

View File

@ -1,12 +1,12 @@
// 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.Tasks; using System.Threading.Tasks;
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.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States; using osu.Framework.Input.States;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Screens; using osu.Framework.Screens;
@ -22,6 +22,8 @@ namespace osu.Game.Screens.Play
{ {
public class PlayerLoader : ScreenWithBeatmapBackground public class PlayerLoader : ScreenWithBeatmapBackground
{ {
private static readonly Vector2 background_blur = new Vector2(15);
private Player player; private Player player;
private BeatmapMetadataDisplay info; private BeatmapMetadataDisplay info;
@ -62,7 +64,7 @@ namespace osu.Game.Screens.Play
Margin = new MarginPadding(25), Margin = new MarginPadding(25),
Children = new PlayerSettingsGroup[] Children = new PlayerSettingsGroup[]
{ {
new VisualSettings(), visualSettings = new VisualSettings(),
new InputSettings() new InputSettings()
} }
}); });
@ -123,23 +125,33 @@ namespace osu.Game.Screens.Play
logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo); logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo);
} }
private bool weHandledMouseDown;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
weHandledMouseDown = true;
return base.OnMouseDown(state, args);
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
weHandledMouseDown = false;
return base.OnMouseUp(state, args);
}
private ScheduledDelegate pushDebounce; private ScheduledDelegate pushDebounce;
private VisualSettings visualSettings;
private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && (!GetContainingInputManager().CurrentState.Mouse.HasAnyButtonPressed || weHandledMouseDown); private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && GetContainingInputManager()?.DraggedDrawable == null;
protected override bool OnHover(InputState state)
{
// restore our screen defaults
InitializeBackgroundElements();
return base.OnHover(state);
}
protected override void OnHoverLost(InputState state)
{
if (GetContainingInputManager().HoveredDrawables.Contains(visualSettings))
{
// show user setting preview
UpdateBackgroundElements();
}
base.OnHoverLost(state);
}
protected override void InitializeBackgroundElements()
{
Background?.FadeTo(1, BACKGROUND_FADE_DURATION, Easing.OutQuint);
Background?.BlurTo(background_blur, BACKGROUND_FADE_DURATION, Easing.OutQuint);
}
private void pushWhenLoaded() private void pushWhenLoaded()
{ {
@ -231,7 +243,7 @@ namespace osu.Game.Screens.Play
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Margin = new MarginPadding { Right = 5 }, Margin = new MarginPadding { Right = 5 },
Colour = OsuColour.Gray(0.5f), Colour = OsuColour.Gray(0.8f),
Text = left, Text = left,
}, },
new OsuSpriteText new OsuSpriteText

View File

@ -128,6 +128,27 @@ namespace osu.Game.Screens.Play.PlayerSettings
}; };
} }
private const float fade_duration = 800;
private const float inactive_alpha = 0.5f;
protected override void LoadComplete()
{
base.LoadComplete();
this.Delay(600).FadeTo(inactive_alpha, fade_duration, Easing.OutQuint);
}
protected override bool OnHover(InputState state)
{
this.FadeIn(fade_duration, Easing.OutQuint);
return true;
}
protected override void OnHoverLost(InputState state)
{
this.FadeTo(inactive_alpha, fade_duration, Easing.OutQuint);
base.OnHoverLost(state);
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
@ -140,7 +161,6 @@ namespace osu.Game.Screens.Play.PlayerSettings
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
protected override bool OnHover(InputState state) => true;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
} }
} }

View File

@ -15,6 +15,8 @@ namespace osu.Game.Screens.Play
{ {
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value);
protected new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background;
public override bool AllowBeatmapRulesetChange => false; public override bool AllowBeatmapRulesetChange => false;
protected const float BACKGROUND_FADE_DURATION = 800; protected const float BACKGROUND_FADE_DURATION = 800;
@ -43,21 +45,30 @@ namespace osu.Game.Screens.Play
DimLevel.ValueChanged += _ => UpdateBackgroundElements(); DimLevel.ValueChanged += _ => UpdateBackgroundElements();
BlurLevel.ValueChanged += _ => UpdateBackgroundElements(); BlurLevel.ValueChanged += _ => UpdateBackgroundElements();
ShowStoryboard.ValueChanged += _ => UpdateBackgroundElements(); ShowStoryboard.ValueChanged += _ => UpdateBackgroundElements();
UpdateBackgroundElements(); InitializeBackgroundElements();
} }
protected override void OnResuming(Screen last) protected override void OnResuming(Screen last)
{ {
base.OnResuming(last); base.OnResuming(last);
UpdateBackgroundElements(); InitializeBackgroundElements();
} }
/// <summary>
/// Called once on entering screen. By Default, performs a full <see cref="UpdateBackgroundElements"/> call.
/// </summary>
protected virtual void InitializeBackgroundElements() => UpdateBackgroundElements();
/// <summary>
/// Called wen background elements require updates, usually due to a user changing a setting.
/// </summary>
/// <param name="userChange"></param>
protected virtual void UpdateBackgroundElements() protected virtual void UpdateBackgroundElements()
{ {
if (!IsCurrentScreen) return; if (!IsCurrentScreen) return;
Background?.FadeTo(BackgroundOpacity, BACKGROUND_FADE_DURATION, Easing.OutQuint); Background?.FadeTo(BackgroundOpacity, BACKGROUND_FADE_DURATION, Easing.OutQuint);
(Background as BackgroundScreenBeatmap)?.BlurTo(new Vector2((float)BlurLevel.Value * 25), BACKGROUND_FADE_DURATION, Easing.OutQuint); Background?.BlurTo(new Vector2((float)BlurLevel.Value * 25), BACKGROUND_FADE_DURATION, Easing.OutQuint);
} }
} }
} }

View File

@ -330,13 +330,13 @@ namespace osu.Game.Screens.Select
private FilterCriteria activeCriteria = new FilterCriteria(); private FilterCriteria activeCriteria = new FilterCriteria();
protected ScheduledDelegate FilterTask; protected ScheduledDelegate PendingFilter;
public bool AllowSelection = true; public bool AllowSelection = true;
public void FlushPendingFilterOperations() public void FlushPendingFilterOperations()
{ {
if (FilterTask?.Completed == false) if (PendingFilter?.Completed == false)
{ {
applyActiveCriteria(false, false); applyActiveCriteria(false, false);
Update(); Update();
@ -357,18 +357,18 @@ namespace osu.Game.Screens.Select
void perform() void perform()
{ {
FilterTask = null; PendingFilter = null;
root.Filter(activeCriteria); root.Filter(activeCriteria);
itemsCache.Invalidate(); itemsCache.Invalidate();
if (scroll) scrollPositionCache.Invalidate(); if (scroll) scrollPositionCache.Invalidate();
} }
FilterTask?.Cancel(); PendingFilter?.Cancel();
FilterTask = null; PendingFilter = null;
if (debounce) if (debounce)
FilterTask = Scheduler.AddDelayed(perform, 250); PendingFilter = Scheduler.AddDelayed(perform, 250);
else else
perform(); perform();
} }

View File

@ -182,7 +182,7 @@ namespace osu.Game.Screens.Select
showConverted.ValueChanged += val => updateCriteria(); showConverted.ValueChanged += val => updateCriteria();
ruleset.BindTo(parentRuleset); ruleset.BindTo(parentRuleset);
ruleset.BindValueChanged(val => updateCriteria(), true); ruleset.BindValueChanged(_ => updateCriteria(), true);
} }
private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria());

View File

@ -12,6 +12,7 @@ using osu.Framework.Audio.Track;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Framework.Input.EventArgs; using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States; using osu.Framework.Input.States;
using osu.Framework.Screens; using osu.Framework.Screens;
@ -199,10 +200,6 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours)
{ {
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
if (Footer != null) if (Footer != null)
{ {
Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2);
@ -225,15 +222,6 @@ namespace osu.Game.Screens.Select
sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand");
Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable(); Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable();
Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
Beatmap.BindValueChanged(workingBeatmapChanged);
}
protected override void LoadComplete()
{
base.LoadComplete();
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
} }
public void Edit(BeatmapInfo beatmap) public void Edit(BeatmapInfo beatmap)
@ -296,59 +284,86 @@ namespace osu.Game.Screens.Select
private BeatmapInfo beatmapNoDebounce; private BeatmapInfo beatmapNoDebounce;
private RulesetInfo rulesetNoDebounce; private RulesetInfo rulesetNoDebounce;
private void updateSelectedBeatmap(BeatmapInfo beatmap)
{
if (beatmap?.Equals(beatmapNoDebounce) == true)
return;
beatmapNoDebounce = beatmap;
performUpdateSelected();
}
private void updateSelectedRuleset(RulesetInfo ruleset)
{
if (ruleset?.Equals(rulesetNoDebounce) == true)
return;
rulesetNoDebounce = ruleset;
performUpdateSelected();
}
/// <summary> /// <summary>
/// selection has been changed as the result of a user interaction. /// selection has been changed as the result of a user interaction.
/// </summary> /// </summary>
private void updateSelectedBeatmap(BeatmapInfo beatmap) private void performUpdateSelected()
{ {
var ruleset = base.Ruleset.Value; var beatmap = beatmapNoDebounce;
var ruleset = rulesetNoDebounce;
void performLoad() void run()
{ {
Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}");
WorkingBeatmap working = Beatmap.Value; WorkingBeatmap working = Beatmap.Value;
bool preview = false; bool preview = false;
if (ruleset?.Equals(Ruleset.Value) == false)
{
Logger.Log($"ruleset changed from \"{Ruleset.Value}\" to \"{ruleset}\"");
Ruleset.Value = ruleset;
// force a filter before attempting to change the beatmap.
// we may still be in the wrong ruleset as there is a debounce delay on ruleset changes.
Carousel.Filter(null, false);
// Filtering only completes after the carousel runs Update.
// If we also have a pending beatmap change we should delay it one frame.
selectionChangedDebounce = Schedule(run);
return;
}
// We may be arriving here due to another component changing the bindable Beatmap. // We may be arriving here due to another component changing the bindable Beatmap.
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true) if (!Equals(beatmap, Beatmap.Value.BeatmapInfo))
{ {
Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\"");
preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID; preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
if (beatmap != null)
{
if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID)
sampleChangeDifficulty.Play();
else
sampleChangeBeatmap.Play();
}
} }
working.Mods.Value = Enumerable.Empty<Mod>(); working.Mods.Value = Enumerable.Empty<Mod>();
Beatmap.Value = working; Beatmap.Value = working;
Ruleset.Value = ruleset;
ensurePlayingSelected(preview); ensurePlayingSelected(preview);
UpdateBeatmap(Beatmap.Value); UpdateBeatmap(Beatmap.Value);
} }
if (beatmap?.Equals(beatmapNoDebounce) == true && ruleset?.Equals(rulesetNoDebounce) == true)
return;
selectionChangedDebounce?.Cancel(); selectionChangedDebounce?.Cancel();
beatmapNoDebounce = beatmap;
rulesetNoDebounce = ruleset;
if (beatmap == null) if (beatmap == null)
performLoad(); run();
else else
{ selectionChangedDebounce = Scheduler.AddDelayed(run, 200);
if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID)
sampleChangeDifficulty.Play();
else
sampleChangeBeatmap.Play();
if (beatmap == Beatmap.Value.BeatmapInfo)
performLoad();
else
selectionChangedDebounce = Scheduler.AddDelayed(performLoad, 200);
}
} }
private void triggerRandom() private void triggerRandom()
@ -464,6 +479,8 @@ namespace osu.Game.Screens.Select
/// <param name="beatmap">The working beatmap.</param> /// <param name="beatmap">The working beatmap.</param>
protected virtual void UpdateBeatmap(WorkingBeatmap beatmap) protected virtual void UpdateBeatmap(WorkingBeatmap beatmap)
{ {
Logger.Log($"working beatmap updated to {beatmap}");
if (Background is BackgroundScreenBeatmap backgroundModeBeatmap) if (Background is BackgroundScreenBeatmap backgroundModeBeatmap)
{ {
backgroundModeBeatmap.Beatmap = beatmap; backgroundModeBeatmap.Beatmap = beatmap;
@ -495,6 +512,17 @@ namespace osu.Game.Screens.Select
private void carouselBeatmapsLoaded() private void carouselBeatmapsLoaded()
{ {
if (rulesetNoDebounce == null)
{
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
rulesetNoDebounce = Ruleset.Value = base.Ruleset.Value;
base.Ruleset.ValueChanged += updateSelectedRuleset;
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true);
Beatmap.BindValueChanged(workingBeatmapChanged);
}
if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false
&& Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false))
return; return;
@ -503,7 +531,7 @@ namespace osu.Game.Screens.Select
{ {
// in the case random selection failed, we want to trigger selectionChanged // in the case random selection failed, we want to trigger selectionChanged
// to show the dummy beatmap (we have nothing else to display). // to show the dummy beatmap (we have nothing else to display).
updateSelectedBeatmap(null); performUpdateSelected();
} }
} }

View File

@ -18,8 +18,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="ppy.osu.Framework" Version="2018.730.0" /> <PackageReference Include="ppy.osu.Framework" Version="2018.803.0" />
<PackageReference Include="SharpCompress" Version="0.17.1" /> <PackageReference Include="SharpCompress" Version="0.22.0" />
<PackageReference Include="NUnit" Version="3.10.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
</ItemGroup> </ItemGroup>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>osulazer</id>
<version>0.0.0</version>
<title>osulazer</title>
<authors>ppy Pty Ltd</authors>
<owners>Dean Herbert</owners>
<projectUrl>https://osu.ppy.sh/</projectUrl>
<iconUrl>https://puu.sh/tYyXZ/9a01a5d1b0.ico</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>click the circles. to the beat.</description>
<summary>click the circles.</summary>
<releaseNotes>testing</releaseNotes>
<copyright>Copyright ppy Pty Ltd 2007-2018</copyright>
<language>en-AU</language>
</metadata>
<files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/>
</files>
</package>