1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-01 21:03:22 +08:00

Merge remote-tracking branch 'upstream/master' into joystick

# Conflicts:
#	osu-framework
#	osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
This commit is contained in:
Dean Herbert 2018-05-13 00:10:55 +09:00
commit a162453e9b
1113 changed files with 97120 additions and 95065 deletions

41
.gitattributes vendored
View File

@ -1,19 +1,24 @@
# This won't normalise line endings, but it will ensure that merge drivers use CRLF # Autodetect text files and ensure that we normalise their
* -text eol=crlf # line endings to lf internally. When checked out they may
# use different line endings.
* text=auto
# Currently in-use binary file extensions # Check out with crlf (Windows) line endings
*.blend binary *.sln text eol=crlf
*.bmp binary *.csproj text eol=crlf
*.dll binary *.cs text diff=csharp eol=crlf
*.exe binary *.resx text eol=crlf
*.icns binary *.vsixmanifest text eol=crlf
*.ico binary packages.config text eol=crlf
*.jpg binary App.config text eol=crlf
*.osz2 binary *.bat text eol=crlf
*.pdn binary *.cmd text eol=crlf
*.psd binary *.snippet text eol=crlf
*.PSD binary *.manifest text eol=crlf
*.tga binary
*.ttf binary # Check out with lf (UNIX) line endings
*.wav binary *.sh text eol=lf
*.xnb binary .gitignore text eol=lf
.gitattributes text eol=lf
*.md text eol=lf
.travis.yml text eol=lf

View File

@ -0,0 +1,22 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RulesetTests (catch)" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests" />
<option name="PASS_PARENT_ENVS" value="1" />
<envs>
<env name="ASPNETCORE_ENVIRONMENT" value="Development" />
<env name="ASPNETCORE_URLS" value="http://localhost:5000" />
</envs>
<option name="USE_MONO" value="0" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<browser url="http://localhost:5000" />
<method />
</configuration>
</component>

View File

@ -0,0 +1,22 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RulesetTests (mania)" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests" />
<option name="PASS_PARENT_ENVS" value="1" />
<envs>
<env name="ASPNETCORE_ENVIRONMENT" value="Development" />
<env name="ASPNETCORE_URLS" value="http://localhost:5000" />
</envs>
<option name="USE_MONO" value="0" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<browser url="http://localhost:5000" />
<method />
</configuration>
</component>

View File

@ -0,0 +1,22 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RulesetTests (osu!)" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests" />
<option name="PASS_PARENT_ENVS" value="1" />
<envs>
<env name="ASPNETCORE_ENVIRONMENT" value="Development" />
<env name="ASPNETCORE_URLS" value="http://localhost:5000" />
</envs>
<option name="USE_MONO" value="0" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<browser url="http://localhost:5000" />
<method />
</configuration>
</component>

View File

@ -0,0 +1,22 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="RulesetTests (taiko)" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests" />
<option name="PASS_PARENT_ENVS" value="1" />
<envs>
<env name="ASPNETCORE_ENVIRONMENT" value="Development" />
<env name="ASPNETCORE_URLS" value="http://localhost:5000" />
</envs>
<option name="USE_MONO" value="0" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<browser url="http://localhost:5000" />
<method />
</configuration>
</component>

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="VisualTests (net461)" type="DotNetProject" factoryName=".NET Project" singleton="true"> <configuration default="false" name="VisualTests (net471)" type="DotNetProject" factoryName=".NET Project" singleton="true">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net461/osu.Game.Tests.exe" /> <option name="EXE_PATH" value="$PROJECT_DIR$/osu.Game.Tests/bin/Debug/net471/osu.Game.Tests.exe" />
<option name="PROGRAM_PARAMETERS" value="" /> <option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Game.Tests" />
<option name="PASS_PARENT_ENVS" value="1" /> <option name="PASS_PARENT_ENVS" value="1" />
@ -12,7 +12,7 @@
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" /> <option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" /> <option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" /> <option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.6.1" /> <option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<method /> <method />
</configuration> </configuration>
</component> </component>

View File

@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="osu! (net461)" type="DotNetProject" factoryName=".NET Project" singleton="true"> <configuration default="false" name="osu! (net471)" type="DotNetProject" factoryName=".NET Project" singleton="true">
<option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net461/osu!.exe" /> <option name="EXE_PATH" value="$PROJECT_DIR$/osu.Desktop/bin/Debug/net471/osu!.exe" />
<option name="PROGRAM_PARAMETERS" value="" /> <option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/osu.Desktop" />
<option name="PASS_PARENT_ENVS" value="1" /> <option name="PASS_PARENT_ENVS" value="1" />
@ -12,7 +12,7 @@
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" /> <option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" /> <option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" /> <option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETFramework,Version=v4.6.1" /> <option name="PROJECT_TFM" value=".NETFramework,Version=v4.7.1" />
<method /> <method />
</configuration> </configuration>
</component> </component>

16
.vscode/launch.json vendored
View File

@ -2,13 +2,13 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net461)", "name": "VisualTests (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net461/osu.Game.Tests.exe", "program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net471/osu.Game.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -16,13 +16,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, net461)", "name": "VisualTests (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net461/osu.Game.Tests.exe", "program": "${workspaceRoot}/osu.Game.Tests/bin/Debug/net471/osu.Game.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -30,13 +30,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "osu! (Debug, net461)", "name": "osu! (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/osu.Desktop/bin/Debug/net461/osu!.exe", "program": "${workspaceRoot}/osu.Desktop/bin/Debug/net471/osu!.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -44,13 +44,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "osu! (Release, net461)", "name": "osu! (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/osu.Desktop/bin/Release/net461/osu!.exe", "program": "${workspaceRoot}/osu.Desktop/bin/Release/net471/osu!.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,

6
.vscode/tasks.json vendored
View File

@ -8,7 +8,7 @@
"type": "shell", "type": "shell",
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -22,7 +22,7 @@
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -64,7 +64,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net461)", "label": "Restore (net471)",
"type": "shell", "type": "shell",
"command": "nuget", "command": "nuget",
"args": [ "args": [

View File

@ -8,7 +8,7 @@ This is still heavily under development and is not intended for end-user use. Th
# Requirements # Requirements
- A desktop platform that can compile .NET 4.6.1. We recommend using [Visual Studio Community Edition](https://www.visualstudio.com/) (Windows), [Visual Studio for Mac](https://www.visualstudio.com/vs/visual-studio-mac/) (macOS) or [MonoDevelop](http://www.monodevelop.com/download/) (Linux), all of which are free. [Visual Studio Code](https://code.visualstudio.com/) may also be used but requires further setup steps which are not covered here. - A desktop platform that can compile .NET 4.7.1. We recommend using [Visual Studio Community Edition](https://www.visualstudio.com/) (Windows), [Visual Studio for Mac](https://www.visualstudio.com/vs/visual-studio-mac/) (macOS) or [MonoDevelop](http://www.monodevelop.com/download/) (Linux), all of which are free. [Visual Studio Code](https://code.visualstudio.com/) may also be used but requires further setup steps which are not covered here.
# Getting Started # Getting Started
- Clone the repository including submodules (`git clone --recurse-submodules https://github.com/ppy/osu`) - Clone the repository including submodules (`git clone --recurse-submodules https://github.com/ppy/osu`)

46
app.manifest Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity version="1.0.0.0" name="osu!" />
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
<applicationRequestMinimum>
<defaultAssemblyRequest permissionSetReference="Custom" />
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
</applicationRequestMinimum>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</asmv1:assembly>

View File

@ -1,4 +1,3 @@
# 2017-09-14
clone_depth: 1 clone_depth: 1
version: '{branch}-{build}' version: '{branch}-{build}'
image: Visual Studio 2017 image: Visual Studio 2017
@ -12,12 +11,12 @@ install:
- cmd: git submodule update --init --recursive --depth=5 - cmd: git submodule update --init --recursive --depth=5
- cmd: choco install resharper-clt -y - cmd: choco install resharper-clt -y
- cmd: choco install nvika -y - cmd: choco install nvika -y
- cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.4/CodeFileSanity.exe - cmd: appveyor DownloadFile https://github.com/peppy/CodeFileSanity/releases/download/v0.2.5/CodeFileSanity.exe
before_build: before_build:
- cmd: CodeFileSanity.exe - cmd: CodeFileSanity.exe
- cmd: nuget restore -verbosity quiet - cmd: nuget restore -verbosity quiet
environment: environment:
TargetFramework: net461 TargetFramework: net471
build: build:
project: osu.sln project: osu.sln
parallel: true parallel: true

34
appveyor_deploy.yml Normal file
View File

@ -0,0 +1,34 @@
branches:
only:
- release
skip_tags: true
skip_branch_with_pr: true
clone_depth: 1
version: '{branch}-{build}'
image: Visual Studio 2017
configuration: Debug
cache:
- packages -> **\packages.config
install:
- cmd: git submodule update --init --recursive --depth=5
before_build:
- cmd: nuget restore -verbosity quiet
build:
project: osu.Desktop.Deploy/osu.Desktop.Deploy.csproj
verbosity: minimal
after_build:
- ps: iex ((New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/appveyor/secure-file/master/install.ps1'))
- appveyor DownloadFile https://puu.sh/A6g5K/4d08705438.enc # signing certificate
- cmd: appveyor-tools\secure-file -decrypt 4d08705438.enc -secret %decode_secret% -out %HOMEPATH%\deanherbert.pfx
- appveyor DownloadFile https://puu.sh/A6g75/fdc6f19b04.enc # deploy configuration
- cmd: appveyor-tools\secure-file -decrypt fdc6f19b04.enc -secret %decode_secret% -out osu.Desktop.Deploy\bin\Debug\net471\osu.Desktop.Deploy.exe.config
- cd osu.Desktop.Deploy\bin\Debug\net471\
- osu.Desktop.Deploy.exe %code_signing_password%
environment:
TargetFramework: net471
decode_secret:
secure: i67IC2xj6DjjxmA6Oj2jing3+MwzLkq6CbGsjfZ7rdY=
code_signing_password:
secure: 34tLNqvjmmZEi97MLKfrnQ==
artifacts:
- path: 'Releases\*'

@ -1 +1 @@
Subproject commit 3388ae24ba5cc75fc966ab1531f44701e74588a9 Subproject commit eaa640972ca9c67f0ea15a942035b5b3a78f1570

View File

@ -7,7 +7,7 @@
"name": "Deploy (Debug)", "name": "Deploy (Debug)",
"request": "launch", "request": "launch",
"type": "mono", "type": "mono",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Desktop.Deploy.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Desktop.Deploy.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug)", "preLaunchTask": "Build (Debug)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -18,7 +18,7 @@
"name": "Deploy (Release)", "name": "Deploy (Release)",
"request": "launch", "request": "launch",
"type": "clr", "type": "clr",
"program": "${workspaceRoot}/bin/Release/net461/osu.Desktop.Deploy.exe", "program": "${workspaceRoot}/bin/Release/net471/osu.Desktop.Deploy.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release)", "preLaunchTask": "Build (Release)",
"runtimeExecutable": null, "runtimeExecutable": null,

View File

@ -7,6 +7,7 @@ using System.Configuration;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Management.Automation;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Framework.IO.Network; using osu.Framework.IO.Network;
using FileWebRequest = osu.Framework.IO.Network.FileWebRequest; using FileWebRequest = osu.Framework.IO.Network.FileWebRequest;
@ -18,7 +19,7 @@ namespace osu.Desktop.Deploy
{ {
private static string packages => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages"); private static string packages => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
private static string nugetPath => Path.Combine(packages, @"nuget.commandline\4.5.1\tools\NuGet.exe"); private static string nugetPath => Path.Combine(packages, @"nuget.commandline\4.5.1\tools\NuGet.exe");
private static string squirrelPath => Path.Combine(packages, @"squirrel.windows\1.7.8\tools\Squirrel.exe"); private static string squirrelPath => Path.Combine(packages, @"squirrel.windows\1.8.0\tools\Squirrel.exe");
private const string msbuild_path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe"; private const string msbuild_path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe";
public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"]; public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"];
@ -57,8 +58,12 @@ namespace osu.Desktop.Deploy
private static string codeSigningPassword; private static string codeSigningPassword;
private static bool interactive;
public static void Main(string[] args) public static void Main(string[] args)
{ {
interactive = args.Length == 0;
displayHeader(); displayHeader();
findSolutionPath(); findSolutionPath();
@ -82,19 +87,20 @@ namespace osu.Desktop.Deploy
string version = $"{verBase}{increment}"; string version = $"{verBase}{increment}";
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
Console.Write($"Ready to deploy {version}: "); Console.Write($"Ready to deploy {version}!");
Console.ReadLine(); pauseIfInteractive();
sw.Start(); sw.Start();
if (!string.IsNullOrEmpty(CodeSigningCertificate)) if (!string.IsNullOrEmpty(CodeSigningCertificate))
{ {
Console.Write("Enter code signing password: "); Console.Write("Enter code signing password: ");
codeSigningPassword = readLineMasked(); codeSigningPassword = args.Length > 0 ? args[0] : readLineMasked();
} }
write("Updating AssemblyInfo..."); write("Updating AssemblyInfo...");
updateCsprojVersion(version); updateCsprojVersion(version);
updateAppveyorVersion(version);
write("Running build process..."); write("Running build process...");
foreach (string targetName in TargetNames.Split(',')) foreach (string targetName in TargetNames.Split(','))
@ -109,7 +115,7 @@ namespace osu.Desktop.Deploy
checkReleaseFiles(); checkReleaseFiles();
write("Running squirrel build..."); write("Running squirrel build...");
runCommand(squirrelPath, $"--releasify {stagingPath}\\{nupkgFilename(version)} --setupIcon {iconPath} --icon {iconPath} {codeSigningCmd} --no-msi"); runCommand(squirrelPath, $"--releasify {stagingPath}\\{nupkgFilename(version)} --framework-version=net471 --setupIcon {iconPath} --icon {iconPath} {codeSigningCmd} --no-msi");
//prune again to clean up before upload. //prune again to clean up before upload.
pruneReleases(); pruneReleases();
@ -124,7 +130,7 @@ namespace osu.Desktop.Deploy
updateCsprojVersion("0.0.0"); updateCsprojVersion("0.0.0");
write("Done!", ConsoleColor.White); write("Done!", ConsoleColor.White);
Console.ReadLine(); pauseIfInteractive();
} }
private static void displayHeader() private static void displayHeader()
@ -388,10 +394,37 @@ namespace osu.Desktop.Deploy
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"FATAL ERROR: {message}"); Console.WriteLine($"FATAL ERROR: {message}");
Console.ReadLine(); pauseIfInteractive();
Environment.Exit(-1); Environment.Exit(-1);
} }
private static void pauseIfInteractive()
{
if (interactive)
Console.ReadLine();
else
Console.WriteLine();
}
private static bool updateAppveyorVersion(string version)
{
try
{
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript($"Update-AppveyorBuild -Version \"{version}\"");
ps.Invoke();
}
return true;
}
catch
{
// we don't have appveyor and don't care
}
return false;
}
private static void write(string message, ConsoleColor col = ConsoleColor.Gray) private static void write(string message, ConsoleColor col = ConsoleColor.Gray)
{ {
if (sw.ElapsedMilliseconds > 0) if (sw.ElapsedMilliseconds > 0)

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.Game.props" /> <Import Project="..\osu.Game.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<TargetFrameworks>net461</TargetFrameworks> <TargetFrameworks>net471</TargetFrameworks>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -11,8 +11,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="NuGet.CommandLine" Version="4.5.1" /> <PackageReference Include="NuGet.CommandLine" Version="4.5.1" />
<PackageReference Include="NUnit" Version="3.8.1" /> <PackageReference Include="NUnit" Version="3.10.1" />
<PackageReference Include="squirrel.windows" Version="1.7.8" Condition="'$(TargetFramework)' == 'net461'" /> <PackageReference Include="squirrel.windows" Version="1.8.0" Condition="'$(TargetFramework)' == 'net471'" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0" /> <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.0" />
<PackageReference Include="System.Management.Automation.dll" Version="10.0.10586" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\osu.Game.props" /> <Import Project="..\osu.Game.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks> <TargetFrameworks>net471;netcoreapp2.0</TargetFrameworks>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -10,11 +10,11 @@
<Title>osu!lazer</Title> <Title>osu!lazer</Title>
<Product>osu!lazer</Product> <Product>osu!lazer</Product>
<ApplicationIcon>lazer.ico</ApplicationIcon> <ApplicationIcon>lazer.ico</ApplicationIcon>
<Version>0.0.0.0</Version> <Version>0.0.0</Version>
<FileVersion>0.0.0.0</FileVersion> <FileVersion>0.0.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Defines"> <PropertyGroup Label="Defines">
<DefineConstants Condition="'$(TargetFramework)' == 'net461'">$(DefineConstants);NET_FRAMEWORK</DefineConstants> <DefineConstants Condition="'$(TargetFramework)' == 'net471'">$(DefineConstants);NET_FRAMEWORK</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>osu.Desktop.Program</StartupObject> <StartupObject>osu.Desktop.Program</StartupObject>
@ -31,7 +31,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.1" />
<PackageReference Include="squirrel.windows" Version="1.7.8" Condition="'$(TargetFramework)' == 'net461'" /> <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" />

View File

@ -2,13 +2,13 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net461)", "name": "VisualTests (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Catch.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -16,13 +16,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, net461)", "name": "VisualTests (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Catch.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Catch.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,

View File

@ -9,7 +9,7 @@
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -24,7 +24,7 @@
"args": [ "args": [
"osu.Game.Rulesets.Catch.Tests.csproj", "osu.Game.Rulesets.Catch.Tests.csproj",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -66,7 +66,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net461)", "label": "Restore (net471)",
"type": "shell", "type": "shell",
"command": "nuget", "command": "nuget",
"args": [ "args": [

View File

@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
public class CatchBeatmapConversionTest : BeatmapConversionTest<ConvertValue> public class CatchBeatmapConversionTest : BeatmapConversionTest<TestCatchRuleset, ConvertValue>
{ {
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Tests
} }
} }
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new CatchBeatmapConverter(); protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
} }
public struct ConvertValue : IEquatable<ConvertValue> public struct ConvertValue : IEquatable<ConvertValue>
@ -64,4 +64,8 @@ namespace osu.Game.Rulesets.Catch.Tests
=> Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience) => Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience)
&& Precision.AlmostEquals(Position, other.Position, conversion_lenience); && Precision.AlmostEquals(Position, other.Position, conversion_lenience);
} }
public class TestCatchRuleset : CatchRuleset
{
}
} }

View File

@ -0,0 +1,62 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
using OpenTK;
namespace osu.Game.Rulesets.Catch.Tests
{
public class TestCaseAutoJuiceStream : TestCasePlayer
{
public TestCaseAutoJuiceStream()
: base(new CatchRuleset())
{
}
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 },
Ruleset = ruleset.RulesetInfo
}
};
for (int i = 0; i < 100; i++)
{
float width = (i % 10 + 1) / 20f;
beatmap.HitObjects.Add(new JuiceStream
{
X = 0.5f - width / 2,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
new Vector2(width * CatchPlayfield.BASE_WIDTH, 0)
},
CurveType = CurveType.Linear,
Distance = width * CatchPlayfield.BASE_WIDTH,
StartTime = i * 2000,
NewCombo = i % 8 == 0
});
}
return beatmap;
}
protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset)
{
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
return base.CreatePlayer(beatmap, ruleset);
}
}
}

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
} }
protected override Beatmap CreateBeatmap(Ruleset ruleset) protected override IBeatmap CreateBeatmap(Ruleset ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
} }
protected override Beatmap CreateBeatmap(Ruleset ruleset) protected override IBeatmap CreateBeatmap(Ruleset ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
} }
protected override Beatmap CreateBeatmap(Ruleset ruleset) protected override IBeatmap CreateBeatmap(Ruleset ruleset)
{ {
var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } }; var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } };

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks> <TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj" />

View File

@ -0,0 +1,43 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Catch.Objects;
namespace osu.Game.Rulesets.Catch.Beatmaps
{
public class CatchBeatmap : Beatmap<CatchHitObject>
{
public override IEnumerable<BeatmapStatistic> GetStatistics()
{
int fruits = HitObjects.Count(s => s is Fruit);
int juiceStreams = HitObjects.Count(s => s is JuiceStream);
int bananaShowers = HitObjects.Count(s => s is BananaShower);
return new[]
{
new BeatmapStatistic
{
Name = @"Fruit Count",
Content = fruits.ToString(),
Icon = FontAwesome.fa_circle_o
},
new BeatmapStatistic
{
Name = @"Juice Stream Count",
Content = juiceStreams.ToString(),
Icon = FontAwesome.fa_circle
},
new BeatmapStatistic
{
Name = @"Banana Shower Count",
Content = bananaShowers.ToString(),
Icon = FontAwesome.fa_circle
}
};
}
}
}

View File

@ -13,9 +13,14 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
public class CatchBeatmapConverter : BeatmapConverter<CatchHitObject> public class CatchBeatmapConverter : BeatmapConverter<CatchHitObject>
{ {
public CatchBeatmapConverter(IBeatmap beatmap)
: base(beatmap)
{
}
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
protected override IEnumerable<CatchHitObject> ConvertHitObject(HitObject obj, Beatmap beatmap) protected override IEnumerable<CatchHitObject> ConvertHitObject(HitObject obj, IBeatmap beatmap)
{ {
var curveData = obj as IHasCurve; var curveData = obj as IHasCurve;
var positionData = obj as IHasXPosition; var positionData = obj as IHasXPosition;
@ -64,5 +69,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
X = positionData.X / CatchPlayfield.BASE_WIDTH X = positionData.X / CatchPlayfield.BASE_WIDTH
}; };
} }
protected override Beatmap<CatchHitObject> CreateBeatmap() => new CatchBeatmap();
} }
} }

View File

@ -12,16 +12,21 @@ using OpenTK;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
public class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject> public class CatchBeatmapProcessor : BeatmapProcessor
{ {
public override void PostProcess(Beatmap<CatchHitObject> beatmap) public CatchBeatmapProcessor(IBeatmap beatmap)
: base(beatmap)
{ {
initialiseHyperDash(beatmap.HitObjects); }
base.PostProcess(beatmap); public override void PostProcess()
{
initialiseHyperDash((List<CatchHitObject>)Beatmap.HitObjects);
base.PostProcess();
int index = 0; int index = 0;
foreach (var obj in beatmap.HitObjects) foreach (var obj in Beatmap.HitObjects.OfType<CatchHitObject>())
obj.IndexInBeatmap = index++; obj.IndexInBeatmap = index++;
} }

View File

@ -2,20 +2,16 @@
// 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.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using System.Collections.Generic; using System.Collections.Generic;
namespace osu.Game.Rulesets.Catch namespace osu.Game.Rulesets.Catch
{ {
public class CatchDifficultyCalculator : DifficultyCalculator<CatchHitObject> public class CatchDifficultyCalculator : DifficultyCalculator
{ {
public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap) public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap)
{ {
} }
public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0; public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0;
protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter(Beatmap beatmap) => new CatchBeatmapConverter();
} }
} }

View File

@ -12,12 +12,16 @@ using osu.Framework.Graphics;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Catch.Beatmaps;
namespace osu.Game.Rulesets.Catch namespace osu.Game.Rulesets.Catch
{ {
public class CatchRuleset : Ruleset public class CatchRuleset : Ruleset
{ {
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset); public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new CatchRulesetContainer(this, beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[] public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
{ {
@ -29,6 +33,44 @@ namespace osu.Game.Rulesets.Catch
new KeyBinding(InputKey.Shift, CatchAction.Dash), new KeyBinding(InputKey.Shift, CatchAction.Dash),
}; };
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
{
if (mods.HasFlag(LegacyMods.Nightcore))
yield return new CatchModNightcore();
else if (mods.HasFlag(LegacyMods.DoubleTime))
yield return new CatchModDoubleTime();
if (mods.HasFlag(LegacyMods.Autoplay))
yield return new CatchModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
yield return new CatchModEasy();
if (mods.HasFlag(LegacyMods.Flashlight))
yield return new CatchModFlashlight();
if (mods.HasFlag(LegacyMods.HalfTime))
yield return new CatchModHalfTime();
if (mods.HasFlag(LegacyMods.HardRock))
yield return new CatchModHardRock();
if (mods.HasFlag(LegacyMods.Hidden))
yield return new CatchModHidden();
if (mods.HasFlag(LegacyMods.NoFail))
yield return new CatchModNoFail();
if (mods.HasFlag(LegacyMods.Perfect))
yield return new CatchModPerfect();
if (mods.HasFlag(LegacyMods.Relax))
yield return new CatchModRelax();
if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new CatchModSuddenDeath();
}
public override IEnumerable<Mod> GetModsFor(ModType type) public override IEnumerable<Mod> GetModsFor(ModType type)
{ {
switch (type) switch (type)
@ -99,7 +141,7 @@ namespace osu.Game.Rulesets.Catch
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap);
public override int? LegacyID => 2; public override int? LegacyID => 2;

View File

@ -1,13 +1,91 @@
// 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.MathUtils;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using System;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Catch.Mods namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModHardRock : ModHardRock public class CatchModHardRock : ModHardRock, IApplicableToHitObject
{ {
public override double ScoreMultiplier => 1.12; public override double ScoreMultiplier => 1.12;
public override bool Ranked => true; public override bool Ranked => true;
private float lastStartX;
private int lastStartTime;
public void ApplyToHitObject(HitObject hitObject)
{
var catchObject = (CatchHitObject)hitObject;
float position = catchObject.X;
int startTime = (int)hitObject.StartTime;
if (lastStartX == 0)
{
lastStartX = position;
lastStartTime = startTime;
return;
}
float diff = lastStartX - position;
int timeDiff = startTime - lastStartTime;
if (timeDiff > 1000)
{
lastStartX = position;
lastStartTime = startTime;
return;
}
if (diff == 0)
{
bool right = RNG.NextBool();
float rand = Math.Min(20, (float)RNG.NextDouble(0, timeDiff / 4d)) / CatchPlayfield.BASE_WIDTH;
if (right)
{
if (position + rand <= 1)
position += rand;
else
position -= rand;
}
else
{
if (position - rand >= 0)
position -= rand;
else
position += rand;
}
catchObject.X = position;
return;
}
if (Math.Abs(diff) < timeDiff / 3d)
{
if (diff > 0)
{
if (position - diff > 0)
position -= diff;
}
else
{
if (position - diff < 1)
position -= diff;
}
}
catchObject.X = position;
lastStartX = position;
lastStartTime = startTime;
}
} }
} }

View File

@ -2,11 +2,10 @@
// 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.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using osu.Framework.Testing;
// We publish our internal attributes to other sub-projects of the framework. // We publish our internal attributes to other sub-projects of the framework.
// Note, that we omit visual tests as they are meant to test the framework // Note, that we omit visual tests as they are meant to test the framework
// behavior "in the wild". // behavior "in the wild".
[assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests")]
[assembly: InternalsVisibleTo(DynamicClassCompiler.DYNAMIC_ASSEMBLY_NAME)] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.Dynamic")]

View File

@ -108,6 +108,7 @@ namespace osu.Game.Rulesets.Catch.Replays
case BananaShower.Banana _: case BananaShower.Banana _:
case TinyDroplet _: case TinyDroplet _:
case Droplet _: case Droplet _:
case Fruit _:
moveToNext(nestedObj); moveToNext(nestedObj);
break; break;
} }

View File

@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Replays
Dashing = dashing; Dashing = dashing;
} }
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
{ {
Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH; Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH;
Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1; Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1;

View File

@ -30,10 +30,10 @@ namespace osu.Game.Rulesets.Catch.UI
Anchor = Anchor.TopCentre; Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre; Origin = Anchor.TopCentre;
ScaledContent.Anchor = Anchor.BottomLeft; base.Content.Anchor = Anchor.BottomLeft;
ScaledContent.Origin = Anchor.BottomLeft; base.Content.Origin = Anchor.BottomLeft;
ScaledContent.AddRange(new Drawable[] base.Content.AddRange(new Drawable[]
{ {
explodingFruitContainer = new Container explodingFruitContainer = new Container
{ {

View File

@ -4,7 +4,6 @@
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Replays;
@ -20,8 +19,8 @@ namespace osu.Game.Rulesets.Catch.UI
{ {
public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchHitObject> public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchHitObject>
{ {
public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap)
{ {
} }
@ -29,10 +28,6 @@ namespace osu.Game.Rulesets.Catch.UI
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
protected override BeatmapProcessor<CatchHitObject> CreateBeatmapProcessor() => new CatchBeatmapProcessor();
protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter() => new CatchBeatmapConverter();
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation);
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);

View File

@ -2,13 +2,13 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net461)", "name": "VisualTests (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Mania.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -16,13 +16,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, net461)", "name": "VisualTests (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Mania.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Mania.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,

View File

@ -9,7 +9,7 @@
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -24,7 +24,7 @@
"args": [ "args": [
"osu.Game.Rulesets.Mania.Tests.csproj", "osu.Game.Rulesets.Mania.Tests.csproj",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -66,7 +66,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net461)", "label": "Restore (net471)",
"type": "shell", "type": "shell",
"command": "nuget", "command": "nuget",
"args": [ "args": [

View File

@ -14,17 +14,14 @@ using osu.Game.Tests.Beatmaps;
namespace osu.Game.Rulesets.Mania.Tests namespace osu.Game.Rulesets.Mania.Tests
{ {
public class ManiaBeatmapConversionTest : BeatmapConversionTest<ConvertValue> public class ManiaBeatmapConversionTest : BeatmapConversionTest<TestManiaRuleset, ConvertValue>
{ {
protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; protected override string ResourceAssembly => "osu.Game.Rulesets.Mania";
private bool isForCurrentRuleset;
[NonParallelizable] [NonParallelizable]
[TestCase("basic", false)] [TestCase("basic")]
public void Test(string name, bool isForCurrentRuleset) public new void Test(string name)
{ {
this.isForCurrentRuleset = isForCurrentRuleset;
base.Test(name); base.Test(name);
} }
@ -38,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Tests
}; };
} }
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new ManiaBeatmapConverter(isForCurrentRuleset, beatmap); protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
} }
public struct ConvertValue : IEquatable<ConvertValue> public struct ConvertValue : IEquatable<ConvertValue>
@ -57,4 +54,8 @@ namespace osu.Game.Rulesets.Mania.Tests
&& Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience) && Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience)
&& Column == other.Column; && Column == other.Column;
} }
public class TestManiaRuleset : ManiaRuleset
{
}
} }

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks> <TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj" />

View File

@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
@ -29,5 +30,27 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
{ {
Stages.Add(defaultStage); Stages.Add(defaultStage);
} }
public override IEnumerable<BeatmapStatistic> GetStatistics()
{
int notes = HitObjects.Count(s => s is Note);
int holdnotes = HitObjects.Count(s => s is HoldNote);
return new[]
{
new BeatmapStatistic
{
Name = @"Note Count",
Content = notes.ToString(),
Icon = FontAwesome.fa_circle_o
},
new BeatmapStatistic
{
Name = @"Hold Note Count",
Content = holdnotes.ToString(),
Icon = FontAwesome.fa_circle
},
};
}
} }
} }

View File

@ -33,18 +33,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
private ManiaBeatmap beatmap; private ManiaBeatmap beatmap;
public ManiaBeatmapConverter(bool isForCurrentRuleset, Beatmap original) public ManiaBeatmapConverter(IBeatmap beatmap)
: base(beatmap)
{ {
IsForCurrentRuleset = isForCurrentRuleset; IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
var roundedCircleSize = Math.Round(original.BeatmapInfo.BaseDifficulty.CircleSize); var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
var roundedOverallDifficulty = Math.Round(original.BeatmapInfo.BaseDifficulty.OverallDifficulty); var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
if (isForCurrentRuleset) if (IsForCurrentRuleset)
TargetColumns = (int)Math.Max(1, roundedCircleSize); TargetColumns = (int)Math.Max(1, roundedCircleSize);
else else
{ {
float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count; float percentSliderOrSpinner = (float)beatmap.HitObjects.Count(h => h is IHasEndTime) / beatmap.HitObjects.Count();
if (percentSliderOrSpinner < 0.2) if (percentSliderOrSpinner < 0.2)
TargetColumns = 7; TargetColumns = 7;
else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5) else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5)
@ -56,8 +57,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
} }
} }
protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original) protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original)
{ {
BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty;
int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate);
@ -68,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
protected override Beatmap<ManiaHitObject> CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }); protected override Beatmap<ManiaHitObject> CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns });
protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, Beatmap beatmap) protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
{ {
var maniaOriginal = original as ManiaHitObject; var maniaOriginal = original as ManiaHitObject;
if (maniaOriginal != null) if (maniaOriginal != null)
@ -112,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
/// <param name="original">The original hit object.</param> /// <param name="original">The original hit object.</param>
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param> /// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
/// <returns>The hit objects generated.</returns> /// <returns>The hit objects generated.</returns>
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original, Beatmap originalBeatmap) private IEnumerable<ManiaHitObject> generateSpecific(HitObject original, IBeatmap originalBeatmap)
{ {
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap); var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap);
@ -128,7 +130,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
/// <param name="original">The original hit object.</param> /// <param name="original">The original hit object.</param>
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param> /// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
/// <returns>The hit objects generated.</returns> /// <returns>The hit objects generated.</returns>
private IEnumerable<ManiaHitObject> generateConverted(HitObject original, Beatmap originalBeatmap) private IEnumerable<ManiaHitObject> generateConverted(HitObject original, IBeatmap originalBeatmap)
{ {
var endTimeData = original as IHasEndTime; var endTimeData = original as IHasEndTime;
var distanceData = original as IHasDistance; var distanceData = original as IHasDistance;
@ -165,7 +167,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
/// </summary> /// </summary>
private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator
{ {
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
: base(random, hitObject, beatmap, previousPattern, originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap)
{ {
} }

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
private PatternType convertType; private PatternType convertType;
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
: base(random, hitObject, beatmap, previousPattern, originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap)
{ {
convertType = PatternType.None; convertType = PatternType.None;

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
{ {
private readonly double endTime; private readonly double endTime;
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Beatmap originalBeatmap) public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, IBeatmap originalBeatmap)
: base(random, hitObject, beatmap, new Pattern(), originalBeatmap) : base(random, hitObject, beatmap, new Pattern(), originalBeatmap)
{ {
var endtimeData = HitObject as IHasEndTime; var endtimeData = HitObject as IHasEndTime;

View File

@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
private readonly PatternType convertType; private readonly PatternType convertType;
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, Beatmap originalBeatmap) public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap)
: base(random, hitObject, beatmap, previousPattern, originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap)
{ {
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));

View File

@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// <summary> /// <summary>
/// The beatmap which <see cref="HitObject"/> is being converted from. /// The beatmap which <see cref="HitObject"/> is being converted from.
/// </summary> /// </summary>
protected readonly Beatmap OriginalBeatmap; protected readonly IBeatmap OriginalBeatmap;
protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap) protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
: base(hitObject, beatmap, previousPattern) : base(hitObject, beatmap, previousPattern)
{ {
if (random == null) throw new ArgumentNullException(nameof(random)); if (random == null) throw new ArgumentNullException(nameof(random));
@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
drainTime /= 1000; drainTime /= 1000;
BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty; BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty;
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15; conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count() / drainTime * 9f) / 38f * 5f / 1.15;
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12); conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
return conversionDifficulty.Value; return conversionDifficulty.Value;

View File

@ -10,7 +10,7 @@ using System.Collections.Generic;
namespace osu.Game.Rulesets.Mania namespace osu.Game.Rulesets.Mania
{ {
internal class ManiaDifficultyCalculator : DifficultyCalculator<ManiaHitObject> internal class ManiaDifficultyCalculator : DifficultyCalculator
{ {
private const double star_scaling_factor = 0.018; private const double star_scaling_factor = 0.018;
@ -31,12 +31,12 @@ namespace osu.Game.Rulesets.Mania
/// </summary> /// </summary>
private readonly List<ManiaHitObjectDifficulty> difficultyHitObjects = new List<ManiaHitObjectDifficulty>(); private readonly List<ManiaHitObjectDifficulty> difficultyHitObjects = new List<ManiaHitObjectDifficulty>();
public ManiaDifficultyCalculator(Beatmap beatmap) public ManiaDifficultyCalculator(IBeatmap beatmap)
: base(beatmap) : base(beatmap)
{ {
} }
public ManiaDifficultyCalculator(Beatmap beatmap, Mod[] mods) public ManiaDifficultyCalculator(IBeatmap beatmap, Mod[] mods)
: base(beatmap, mods) : base(beatmap, mods)
{ {
} }
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania
int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7; int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7;
foreach (var hitObject in Beatmap.HitObjects) foreach (var hitObject in Beatmap.HitObjects)
difficultyHitObjects.Add(new ManiaHitObjectDifficulty(hitObject, columnCount)); difficultyHitObjects.Add(new ManiaHitObjectDifficulty((ManiaHitObject)hitObject, columnCount));
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
@ -140,7 +140,5 @@ namespace osu.Game.Rulesets.Mania
return difficulty; return difficulty;
} }
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap);
} }
} }

View File

@ -14,12 +14,83 @@ using osu.Framework.Input.Bindings;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Mania.Beatmaps;
namespace osu.Game.Rulesets.Mania namespace osu.Game.Rulesets.Mania
{ {
public class ManiaRuleset : Ruleset public class ManiaRuleset : Ruleset
{ {
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset); public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
{
if (mods.HasFlag(LegacyMods.Nightcore))
yield return new ManiaModNightcore();
else if (mods.HasFlag(LegacyMods.DoubleTime))
yield return new ManiaModDoubleTime();
if (mods.HasFlag(LegacyMods.Autoplay))
yield return new ManiaModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
yield return new ManiaModEasy();
if (mods.HasFlag(LegacyMods.FadeIn))
yield return new ManiaModFadeIn();
if (mods.HasFlag(LegacyMods.Flashlight))
yield return new ManiaModFlashlight();
if (mods.HasFlag(LegacyMods.HalfTime))
yield return new ManiaModHalfTime();
if (mods.HasFlag(LegacyMods.HardRock))
yield return new ManiaModHardRock();
if (mods.HasFlag(LegacyMods.Hidden))
yield return new ManiaModHidden();
if (mods.HasFlag(LegacyMods.Key1))
yield return new ManiaModKey1();
if (mods.HasFlag(LegacyMods.Key2))
yield return new ManiaModKey2();
if (mods.HasFlag(LegacyMods.Key3))
yield return new ManiaModKey3();
if (mods.HasFlag(LegacyMods.Key4))
yield return new ManiaModKey4();
if (mods.HasFlag(LegacyMods.Key5))
yield return new ManiaModKey5();
if (mods.HasFlag(LegacyMods.Key6))
yield return new ManiaModKey6();
if (mods.HasFlag(LegacyMods.Key7))
yield return new ManiaModKey7();
if (mods.HasFlag(LegacyMods.Key8))
yield return new ManiaModKey8();
if (mods.HasFlag(LegacyMods.Key9))
yield return new ManiaModKey9();
if (mods.HasFlag(LegacyMods.NoFail))
yield return new ManiaModNoFail();
if (mods.HasFlag(LegacyMods.Perfect))
yield return new ManiaModPerfect();
if (mods.HasFlag(LegacyMods.Random))
yield return new ManiaModRandom();
if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new ManiaModSuddenDeath();
}
public override IEnumerable<Mod> GetModsFor(ModType type) public override IEnumerable<Mod> GetModsFor(ModType type)
{ {
@ -113,7 +184,7 @@ namespace osu.Game.Rulesets.Mania
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods); public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods);
public override int? LegacyID => 3; public override int? LegacyID => 3;

View File

@ -3,19 +3,18 @@
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods namespace osu.Game.Rulesets.Mania.Mods
{ {
public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter<ManiaHitObject> public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter
{ {
public override string ShortenedName => Name; public override string ShortenedName => Name;
public abstract int KeyCount { get; } public abstract int KeyCount { get; }
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;
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter) public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
{ {
var mbc = (ManiaBeatmapConverter)beatmapConverter; var mbc = (ManiaBeatmapConverter)beatmapConverter;

View File

@ -11,19 +11,23 @@ using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mania.Mods namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter<ManiaHitObject>, IApplicableToRulesetContainer<ManiaHitObject> public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToRulesetContainer<ManiaHitObject>
{ {
public override string Name => "Dual Stages"; public override string Name => "Dual Stages";
public override string ShortenedName => "DS"; public override string ShortenedName => "DS";
public override string Description => @"Double the stages, double the fun!"; public override string Description => @"Double the stages, double the fun!";
public override double ScoreMultiplier => 0; public override double ScoreMultiplier => 0;
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter) private bool isForCurrentRuleset;
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
{ {
var mbc = (ManiaBeatmapConverter)beatmapConverter; var mbc = (ManiaBeatmapConverter)beatmapConverter;
isForCurrentRuleset = mbc.IsForCurrentRuleset;
// Although this can work, for now let's not allow keymods for mania-specific beatmaps // Although this can work, for now let's not allow keymods for mania-specific beatmaps
if (mbc.IsForCurrentRuleset) if (isForCurrentRuleset)
return; return;
mbc.TargetColumns *= 2; mbc.TargetColumns *= 2;
@ -34,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Mods
var mrc = (ManiaRulesetContainer)rulesetContainer; var mrc = (ManiaRulesetContainer)rulesetContainer;
// Although this can work, for now let's not allow keymods for mania-specific beatmaps // Although this can work, for now let's not allow keymods for mania-specific beatmaps
if (mrc.IsForCurrentRuleset) if (isForCurrentRuleset)
return; return;
var newDefinitions = new List<StageDefinition>(); var newDefinitions = new List<StageDefinition>();

View File

@ -2,11 +2,10 @@
// 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.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using osu.Framework.Testing;
// We publish our internal attributes to other sub-projects of the framework. // We publish our internal attributes to other sub-projects of the framework.
// Note, that we omit visual tests as they are meant to test the framework // Note, that we omit visual tests as they are meant to test the framework
// behavior "in the wild". // behavior "in the wild".
[assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests")]
[assembly: InternalsVisibleTo(DynamicClassCompiler.DYNAMIC_ASSEMBLY_NAME)] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.Dynamic")]

View File

@ -24,10 +24,10 @@ namespace osu.Game.Rulesets.Mania.Replays
Actions.AddRange(actions); Actions.AddRange(actions);
} }
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
{ {
// We don't need to fully convert, just create the converter // We don't need to fully convert, just create the converter
var converter = new ManiaBeatmapConverter(beatmap.BeatmapInfo.RulesetID == 3, beatmap); var converter = new ManiaBeatmapConverter(beatmap);
// NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling // NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling
// elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage. // elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage.

View File

@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI
public IEnumerable<BarLine> BarLines; public IEnumerable<BarLine> BarLines;
public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap)
{ {
// Generate the bar lines // Generate the bar lines
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Mania.UI
public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant);
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter(IsForCurrentRuleset, WorkingBeatmap.Beatmap);
protected override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h) protected override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h)
{ {
ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action; ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action;

View File

@ -2,13 +2,13 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net461)", "name": "VisualTests (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Osu.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -16,13 +16,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, net461)", "name": "VisualTests (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Osu.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Osu.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,

View File

@ -9,7 +9,7 @@
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -24,7 +24,7 @@
"args": [ "args": [
"osu.Game.Rulesets.Osu.Tests.csproj", "osu.Game.Rulesets.Osu.Tests.csproj",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -66,7 +66,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net461)", "label": "Restore (net471)",
"type": "shell", "type": "shell",
"command": "nuget", "command": "nuget",
"args": [ "args": [

View File

@ -15,7 +15,7 @@ using OpenTK;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
public class OsuBeatmapConversionTest : BeatmapConversionTest<ConvertValue> public class OsuBeatmapConversionTest : BeatmapConversionTest<TestOsuRuleset, ConvertValue>
{ {
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; protected override string ResourceAssembly => "osu.Game.Rulesets.Osu";
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Tests
}; };
} }
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new OsuBeatmapConverter(); protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
} }
public struct ConvertValue : IEquatable<ConvertValue> public struct ConvertValue : IEquatable<ConvertValue>
@ -67,4 +67,8 @@ namespace osu.Game.Rulesets.Osu.Tests
&& Precision.AlmostEquals(EndX, other.EndX, conversion_lenience) && Precision.AlmostEquals(EndX, other.EndX, conversion_lenience)
&& Precision.AlmostEquals(EndY, other.EndY, conversion_lenience); && Precision.AlmostEquals(EndY, other.EndY, conversion_lenience);
} }
public class TestOsuRuleset : OsuRuleset
{
}
} }

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks> <TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj" />

View File

@ -0,0 +1,43 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Beatmaps
{
public class OsuBeatmap : Beatmap<OsuHitObject>
{
public override IEnumerable<BeatmapStatistic> GetStatistics()
{
int circles = HitObjects.Count(c => c is HitCircle);
int sliders = HitObjects.Count(s => s is Slider);
int spinners = HitObjects.Count(s => s is Spinner);
return new[]
{
new BeatmapStatistic
{
Name = @"Circle Count",
Content = circles.ToString(),
Icon = FontAwesome.fa_circle_o
},
new BeatmapStatistic
{
Name = @"Slider Count",
Content = sliders.ToString(),
Icon = FontAwesome.fa_circle
},
new BeatmapStatistic
{
Name = @"Spinner Count",
Content = spinners.ToString(),
Icon = FontAwesome.fa_circle
}
};
}
}
}

View File

@ -14,9 +14,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
internal class OsuBeatmapConverter : BeatmapConverter<OsuHitObject> internal class OsuBeatmapConverter : BeatmapConverter<OsuHitObject>
{ {
public OsuBeatmapConverter(IBeatmap beatmap)
: base(beatmap)
{
}
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasPosition) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasPosition) };
protected override IEnumerable<OsuHitObject> ConvertHitObject(HitObject original, Beatmap beatmap) protected override IEnumerable<OsuHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
{ {
var curveData = original as IHasCurve; var curveData = original as IHasCurve;
var endTimeData = original as IHasEndTime; var endTimeData = original as IHasEndTime;
@ -60,5 +65,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
}; };
} }
} }
protected override Beatmap<OsuHitObject> CreateBeatmap() => new OsuBeatmap();
} }
} }

View File

@ -8,12 +8,17 @@ using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Beatmaps namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
internal class OsuBeatmapProcessor : BeatmapProcessor<OsuHitObject> internal class OsuBeatmapProcessor : BeatmapProcessor
{ {
public override void PostProcess(Beatmap<OsuHitObject> beatmap) public OsuBeatmapProcessor(IBeatmap beatmap)
: base(beatmap)
{ {
applyStacking(beatmap); }
base.PostProcess(beatmap);
public override void PostProcess()
{
applyStacking((Beatmap<OsuHitObject>)Beatmap);
base.PostProcess();
} }
private void applyStacking(Beatmap<OsuHitObject> beatmap) private void applyStacking(Beatmap<OsuHitObject> beatmap)

View File

@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
Size = hitCircle.Size; Size = hitCircle.Size;
Scale = hitCircle.Scale; Scale = hitCircle.Scale;
CornerRadius = Size.X / 2;
AddInternal(new RingPiece()); AddInternal(new RingPiece());
hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.Position; hitCircle.HitObject.PositionChanged += _ => Position = hitCircle.Position;

View File

@ -38,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
Scale = slider.HeadCircle.Scale; Scale = slider.HeadCircle.Scale;
AddInternal(new RingPiece()); AddInternal(new RingPiece());
Select();
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -52,5 +54,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
RelativeAnchorPosition = hitObject.RelativeAnchorPosition; RelativeAnchorPosition = hitObject.RelativeAnchorPosition;
} }
// Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input.
public override bool HandleMouseInput => false;
} }
} }

View File

@ -3,6 +3,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -59,5 +60,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Layers.Selection.Overlays
} }
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => body.ReceiveMouseInputAt(screenSpacePos); public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => body.ReceiveMouseInputAt(screenSpacePos);
public override Vector2 SelectionPoint => ToScreenSpace(OriginPosition);
public override Quad SelectionQuad => body.PathDrawQuad;
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
public class OsuEditPlayfield : OsuPlayfield public class OsuEditPlayfield : OsuPlayfield
{ {
protected override bool ProxyApproachCircles => false; protected override bool DisplayJudgements => false;
} }
} }

View File

@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
public class OsuEditRulesetContainer : OsuRulesetContainer public class OsuEditRulesetContainer : OsuRulesetContainer
{ {
public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap)
{ {
} }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
} }
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap, true); protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap);
protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[] protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[]
{ {

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModAutoplay : ModAutoplay<OsuHitObject> public class OsuModAutoplay : ModAutoplay<OsuHitObject>
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap)
{ {

View File

@ -5,20 +5,23 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using OpenTK; using OpenTK;
namespace osu.Game.Rulesets.Osu.Mods namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject> public class OsuModHardRock : ModHardRock, IApplicableToHitObject
{ {
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
public override bool Ranked => true; public override bool Ranked => true;
public void ApplyToHitObject(OsuHitObject hitObject) public void ApplyToHitObject(HitObject hitObject)
{ {
hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y); var osuObject = (OsuHitObject)hitObject;
osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y);
var slider = hitObject as Slider; var slider = hitObject as Slider;
if (slider == null) if (slider == null)

View File

@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModNoFail : ModNoFail public class OsuModNoFail : ModNoFail
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModRelax : ModRelax public class OsuModRelax : ModRelax
{ {
public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things.";
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -9,6 +9,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModSuddenDeath : ModSuddenDeath public class OsuModSuddenDeath : ModSuddenDeath
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray();
} }
} }

View File

@ -10,7 +10,6 @@ using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Framework.Graphics.Primitives;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -177,8 +176,5 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public Drawable ProxiedLayer => HeadCircle.ApproachCircle; public Drawable ProxiedLayer => HeadCircle.ApproachCircle;
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Body.ReceiveMouseInputAt(screenSpacePos); public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Body.ReceiveMouseInputAt(screenSpacePos);
public override Vector2 SelectionPoint => ToScreenSpace(OriginPosition);
public override Quad SelectionQuad => Body.PathDrawQuad;
} }
} }

View File

@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Children = new Drawable[] Children = new[]
{ {
Background = new SpinnerBackground Background = new SpinnerBackground
{ {

View File

@ -7,10 +7,11 @@ using osu.Game.Rulesets.Objects;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit.Types;
namespace osu.Game.Rulesets.Osu.Objects namespace osu.Game.Rulesets.Osu.Objects
{ {
public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasEditablePosition
{ {
public const double OBJECT_RADIUS = 64; public const double OBJECT_RADIUS = 64;

View File

@ -5,36 +5,30 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
using osu.Game.Rulesets.Osu.OsuDifficulty.Skills; using osu.Game.Rulesets.Osu.OsuDifficulty.Skills;
namespace osu.Game.Rulesets.Osu.OsuDifficulty namespace osu.Game.Rulesets.Osu.OsuDifficulty
{ {
public class OsuDifficultyCalculator : DifficultyCalculator<OsuHitObject> public class OsuDifficultyCalculator : DifficultyCalculator
{ {
private const int section_length = 400; private const int section_length = 400;
private const double difficulty_multiplier = 0.0675; private const double difficulty_multiplier = 0.0675;
public OsuDifficultyCalculator(Beatmap beatmap) public OsuDifficultyCalculator(IBeatmap beatmap)
: base(beatmap) : base(beatmap)
{ {
} }
public OsuDifficultyCalculator(Beatmap beatmap, Mod[] mods) public OsuDifficultyCalculator(IBeatmap beatmap, Mod[] mods)
: base(beatmap, mods) : base(beatmap, mods)
{ {
} }
protected override void PreprocessHitObjects()
{
new OsuBeatmapProcessor().PostProcess(Beatmap);
}
public override double Calculate(Dictionary<string, double> categoryDifficulty = null) public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
{ {
OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Beatmap.HitObjects, TimeRate); OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap((List<OsuHitObject>)Beatmap.HitObjects, TimeRate);
Skill[] skills = Skill[] skills =
{ {
new Aim(), new Aim(),
@ -72,7 +66,5 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty
return starRating; return starRating;
} }
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter(Beatmap beatmap) => new OsuBeatmapConverter();
} }
} }

View File

@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.OsuDifficulty;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
@ -17,16 +16,18 @@ using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Osu.Beatmaps;
namespace osu.Game.Rulesets.Osu namespace osu.Game.Rulesets.Osu
{ {
public class OsuRuleset : Ruleset public class OsuRuleset : Ruleset
{ {
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset); public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new OsuRulesetContainer(this, beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[] public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
{ {
@ -36,34 +37,51 @@ namespace osu.Game.Rulesets.Osu
new KeyBinding(InputKey.MouseRight, OsuAction.RightButton), new KeyBinding(InputKey.MouseRight, OsuAction.RightButton),
}; };
public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
{ {
IEnumerable<HitObject> hitObjects = beatmap.Beatmap.HitObjects; if (mods.HasFlag(LegacyMods.Nightcore))
IEnumerable<HitObject> circles = hitObjects.Where(c => !(c is IHasEndTime)); yield return new OsuModNightcore();
IEnumerable<HitObject> sliders = hitObjects.Where(s => s is IHasCurve); else if (mods.HasFlag(LegacyMods.DoubleTime))
IEnumerable<HitObject> spinners = hitObjects.Where(s => s is IHasEndTime && !(s is IHasCurve)); yield return new OsuModDoubleTime();
return new[] if (mods.HasFlag(LegacyMods.Autopilot))
{ yield return new OsuModAutopilot();
new BeatmapStatistic
{ if (mods.HasFlag(LegacyMods.Autoplay))
Name = @"Circle Count", yield return new OsuModAutoplay();
Content = circles.Count().ToString(),
Icon = FontAwesome.fa_circle_o if (mods.HasFlag(LegacyMods.Easy))
}, yield return new OsuModEasy();
new BeatmapStatistic
{ if (mods.HasFlag(LegacyMods.Flashlight))
Name = @"Slider Count", yield return new OsuModFlashlight();
Content = sliders.Count().ToString(),
Icon = FontAwesome.fa_circle if (mods.HasFlag(LegacyMods.HalfTime))
}, yield return new OsuModHalfTime();
new BeatmapStatistic
{ if (mods.HasFlag(LegacyMods.HardRock))
Name = @"Spinner Count", yield return new OsuModHardRock();
Content = spinners.Count().ToString(),
Icon = FontAwesome.fa_circle if (mods.HasFlag(LegacyMods.Hidden))
} yield return new OsuModHidden();
};
if (mods.HasFlag(LegacyMods.NoFail))
yield return new OsuModNoFail();
if (mods.HasFlag(LegacyMods.Perfect))
yield return new OsuModPerfect();
if (mods.HasFlag(LegacyMods.Relax))
yield return new OsuModRelax();
if (mods.HasFlag(LegacyMods.SpunOut))
yield return new OsuModSpunOut();
if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new OsuModSuddenDeath();
if (mods.HasFlag(LegacyMods.Target))
yield return new OsuModTarget();
} }
public override IEnumerable<Mod> GetModsFor(ModType type) public override IEnumerable<Mod> GetModsFor(ModType type)
@ -133,9 +151,9 @@ namespace osu.Game.Rulesets.Osu
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods); public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods);
public override PerformanceCalculator CreatePerformanceCalculator(Beatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score);
public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this);

View File

@ -2,11 +2,10 @@
// 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.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using osu.Framework.Testing;
// We publish our internal attributes to other sub-projects of the framework. // We publish our internal attributes to other sub-projects of the framework.
// Note, that we omit visual tests as they are meant to test the framework // Note, that we omit visual tests as they are meant to test the framework
// behavior "in the wild". // behavior "in the wild".
[assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests")]
[assembly: InternalsVisibleTo(DynamicClassCompiler.DYNAMIC_ASSEMBLY_NAME)] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.Dynamic")]

View File

@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays
Actions.AddRange(actions); Actions.AddRange(actions);
} }
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
{ {
Position = legacyFrame.Position; Position = legacyFrame.Position;
if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton);

View File

@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Replays
{ {
new ReplayState<OsuAction> new ReplayState<OsuAction>
{ {
Mouse = new ReplayMouseState(ToScreenSpace(Position ?? Vector2.Zero)), Mouse = new ReplayMouseState(GamefieldToScreenSpace(Position ?? Vector2.Zero)),
PressedActions = CurrentFrame.Actions PressedActions = CurrentFrame.Actions
} }
}; };

View File

@ -6,14 +6,13 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Scoring namespace osu.Game.Rulesets.Osu.Scoring
{ {
public class OsuPerformanceCalculator : PerformanceCalculator<OsuHitObject> public class OsuPerformanceCalculator : PerformanceCalculator
{ {
private readonly int countHitCircles; private readonly int countHitCircles;
private readonly int beatmapMaxCombo; private readonly int beatmapMaxCombo;
@ -27,13 +26,14 @@ namespace osu.Game.Rulesets.Osu.Scoring
private int count50; private int count50;
private int countMiss; private int countMiss;
public OsuPerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score) public OsuPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score)
: base(ruleset, beatmap, score) : base(ruleset, beatmap, score)
{ {
countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle);
beatmapMaxCombo = Beatmap.HitObjects.Count; beatmapMaxCombo = Beatmap.HitObjects.Count();
beatmapMaxCombo += Beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count) + 1; // Add the ticks + tail of the slider. 1 is subtracted because the "headcircle" would be counted twice (once for the slider itself in the line above)
beatmapMaxCombo += Beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count - 1);
} }
public override double Calculate(Dictionary<string, double> categoryRatings = null) public override double Calculate(Dictionary<string, double> categoryRatings = null)
@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
aimValue *= approachRateFactor; aimValue *= approachRateFactor;
if (mods.Any(h => h is OsuModHidden)) if (mods.Any(h => h is OsuModHidden))
aimValue *= 1.18f; aimValue *= 1.03f;
if (mods.Any(h => h is OsuModFlashlight)) if (mods.Any(h => h is OsuModFlashlight))
{ {
@ -153,6 +153,9 @@ namespace osu.Game.Rulesets.Osu.Scoring
if (beatmapMaxCombo > 0) if (beatmapMaxCombo > 0)
speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
if (mods.Any(m => m is OsuModHidden))
speedValue *= 1.18f;
// Scale the speed value with accuracy _slightly_ // Scale the speed value with accuracy _slightly_
speedValue *= 0.5f + accuracy / 2.0f; speedValue *= 0.5f + accuracy / 2.0f;
// It is important to also consider accuracy difficulty when doing that // It is important to also consider accuracy difficulty when doing that
@ -193,7 +196,5 @@ namespace osu.Game.Rulesets.Osu.Scoring
private double totalHits => count300 + count100 + count50 + countMiss; private double totalHits => count300 + count100 + count50 + countMiss;
private double totalSuccessfulHits => count300 + count100 + count50; private double totalSuccessfulHits => count300 + count100 + count50;
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
} }
} }

View File

@ -21,9 +21,7 @@ namespace osu.Game.Rulesets.Osu.UI
private readonly JudgementContainer<DrawableOsuJudgement> judgementLayer; private readonly JudgementContainer<DrawableOsuJudgement> judgementLayer;
private readonly ConnectionRenderer<OsuHitObject> connectionLayer; private readonly ConnectionRenderer<OsuHitObject> connectionLayer;
// Todo: This should not be a thing, but is currently required for the editor protected virtual bool DisplayJudgements => true;
// https://github.com/ppy/osu-framework/issues/1283
protected virtual bool ProxyApproachCircles => true;
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
@ -58,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.UI
h.OnJudgement += onJudgement; h.OnJudgement += onJudgement;
var c = h as IDrawableHitObjectWithProxiedApproach; var c = h as IDrawableHitObjectWithProxiedApproach;
if (c != null && ProxyApproachCircles) if (c != null)
approachCircles.Add(c.ProxiedLayer.CreateProxy()); approachCircles.Add(c.ProxiedLayer.CreateProxy());
base.Add(h); base.Add(h);
@ -73,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.UI
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
{ {
if (!judgedObject.DisplayJudgement) if (!judgedObject.DisplayJudgement || !DisplayJudgements)
return; return;
DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject) DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject)

View File

@ -7,7 +7,6 @@ using OpenTK;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Replays;
@ -21,17 +20,13 @@ namespace osu.Game.Rulesets.Osu.UI
{ {
public class OsuRulesetContainer : RulesetContainer<OsuHitObject> public class OsuRulesetContainer : RulesetContainer<OsuHitObject>
{ {
public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap)
{ {
} }
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this);
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
protected override BeatmapProcessor<OsuHitObject> CreateBeatmapProcessor() => new OsuBeatmapProcessor();
protected override Playfield CreatePlayfield() => new OsuPlayfield(); protected override Playfield CreatePlayfield() => new OsuPlayfield();
public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);

View File

@ -2,13 +2,13 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "VisualTests (Debug, net461)", "name": "VisualTests (Debug, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Taiko.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Debug, msbuild)", "preLaunchTask": "Build (Debug, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,
@ -16,13 +16,13 @@
"console": "internalConsole" "console": "internalConsole"
}, },
{ {
"name": "VisualTests (Release, net461)", "name": "VisualTests (Release, net471)",
"windows": { "windows": {
"type": "clr" "type": "clr"
}, },
"type": "mono", "type": "mono",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/net461/osu.Game.Rulesets.Taiko.Tests.exe", "program": "${workspaceRoot}/bin/Debug/net471/osu.Game.Rulesets.Taiko.Tests.exe",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"preLaunchTask": "Build (Release, msbuild)", "preLaunchTask": "Build (Release, msbuild)",
"runtimeExecutable": null, "runtimeExecutable": null,

View File

@ -9,7 +9,7 @@
"command": "msbuild", "command": "msbuild",
"args": [ "args": [
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -24,7 +24,7 @@
"args": [ "args": [
"osu.Game.Rulesets.Taiko.Tests.csproj", "osu.Game.Rulesets.Taiko.Tests.csproj",
"/p:Configuration=Release", "/p:Configuration=Release",
"/p:TargetFramework=net461", "/p:TargetFramework=net471",
"/p:GenerateFullPaths=true", "/p:GenerateFullPaths=true",
"/m", "/m",
"/verbosity:m" "/verbosity:m"
@ -66,7 +66,7 @@
"problemMatcher": "$msCompile" "problemMatcher": "$msCompile"
}, },
{ {
"label": "Restore (net461)", "label": "Restore (net471)",
"type": "shell", "type": "shell",
"command": "nuget", "command": "nuget",
"args": [ "args": [

View File

@ -14,18 +14,15 @@ using osu.Game.Tests.Beatmaps;
namespace osu.Game.Rulesets.Taiko.Tests namespace osu.Game.Rulesets.Taiko.Tests
{ {
public class TaikoBeatmapConversionTest : BeatmapConversionTest<ConvertValue> public class TaikoBeatmapConversionTest : BeatmapConversionTest<TestTaikoRuleset, ConvertValue>
{ {
protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko";
private bool isForCurrentRuleset;
[NonParallelizable] [NonParallelizable]
[TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2152")] [TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2152")]
[TestCase("slider-generating-drumroll", false)] [TestCase("slider-generating-drumroll", false)]
public void Test(string name, bool isForCurrentRuleset) public new void Test(string name)
{ {
this.isForCurrentRuleset = isForCurrentRuleset;
base.Test(name); base.Test(name);
} }
@ -43,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
}; };
} }
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new TaikoBeatmapConverter(isForCurrentRuleset); protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
} }
public struct ConvertValue : IEquatable<ConvertValue> public struct ConvertValue : IEquatable<ConvertValue>
@ -70,4 +67,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
&& IsSwell == other.IsSwell && IsSwell == other.IsSwell
&& IsStrong == other.IsStrong; && IsStrong == other.IsStrong;
} }
public class TestTaikoRuleset : TaikoRuleset
{
}
} }

View File

@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
private Container playfieldContainer; private Container playfieldContainer;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(RulesetStore rulesets) private void load()
{ {
AddStep("Hit!", () => addHitJudgement(false)); AddStep("Hit!", () => addHitJudgement(false));
AddStep("Kiai hit", () => addHitJudgement(true)); AddStep("Kiai hit", () => addHitJudgement(true));
@ -73,6 +73,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
Title = @"Sample Beatmap", Title = @"Sample Beatmap",
AuthorString = @"peppy", AuthorString = @"peppy",
}, },
Ruleset = new TaikoRuleset().RulesetInfo
}, },
ControlPointInfo = controlPointInfo ControlPointInfo = controlPointInfo
}); });
@ -86,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 768, Height = 768,
Clock = new FramedClock(rateAdjustClock), Clock = new FramedClock(rateAdjustClock),
Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap, true) } Children = new[] { rulesetContainer = new TaikoRulesetContainer(new TaikoRuleset(), beatmap) }
}); });
} }

View File

@ -2,7 +2,7 @@
<Import Project="..\osu.TestProject.props" /> <Import Project="..\osu.TestProject.props" />
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks> <TargetFrameworks>netcoreapp2.0;net471</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Project References"> <ItemGroup Label="Project References">
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />

View File

@ -0,0 +1,43 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Taiko.Objects;
namespace osu.Game.Rulesets.Taiko.Beatmaps
{
public class TaikoBeatmap : Beatmap<TaikoHitObject>
{
public override IEnumerable<BeatmapStatistic> GetStatistics()
{
int hits = HitObjects.Count(s => s is Hit);
int drumrolls = HitObjects.Count(s => s is DrumRoll);
int swells = HitObjects.Count(s => s is Swell);
return new[]
{
new BeatmapStatistic
{
Name = @"Hit Count",
Content = hits.ToString(),
Icon = FontAwesome.fa_circle_o
},
new BeatmapStatistic
{
Name = @"Drumroll Count",
Content = drumrolls.ToString(),
Icon = FontAwesome.fa_circle
},
new BeatmapStatistic
{
Name = @"Swell Count",
Content = swells.ToString(),
Icon = FontAwesome.fa_circle
}
};
}
}
}

View File

@ -42,12 +42,13 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(HitObject) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(HitObject) };
public TaikoBeatmapConverter(bool isForCurrentRuleset) public TaikoBeatmapConverter(IBeatmap beatmap)
: base(beatmap)
{ {
this.isForCurrentRuleset = isForCurrentRuleset; isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new TaikoRuleset().RulesetInfo);
} }
protected override Beatmap<TaikoHitObject> ConvertBeatmap(Beatmap original) protected override Beatmap<TaikoHitObject> ConvertBeatmap(IBeatmap original)
{ {
// Rewrite the beatmap info to add the slider velocity multiplier // Rewrite the beatmap info to add the slider velocity multiplier
BeatmapInfo info = original.BeatmapInfo.DeepClone(); BeatmapInfo info = original.BeatmapInfo.DeepClone();
@ -70,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
return converted; return converted;
} }
protected override IEnumerable<TaikoHitObject> ConvertHitObject(HitObject obj, Beatmap beatmap) protected override IEnumerable<TaikoHitObject> ConvertHitObject(HitObject obj, IBeatmap beatmap)
{ {
var distanceData = obj as IHasDistance; var distanceData = obj as IHasDistance;
var repeatsData = obj as IHasRepeats; var repeatsData = obj as IHasRepeats;
@ -196,5 +197,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
} }
} }
} }
protected override Beatmap<TaikoHitObject> CreateBeatmap() => new TaikoBeatmap();
} }
} }

View File

@ -2,11 +2,10 @@
// 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.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using osu.Framework.Testing;
// We publish our internal attributes to other sub-projects of the framework. // We publish our internal attributes to other sub-projects of the framework.
// Note, that we omit visual tests as they are meant to test the framework // Note, that we omit visual tests as they are meant to test the framework
// behavior "in the wild". // behavior "in the wild".
[assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests")]
[assembly: InternalsVisibleTo(DynamicClassCompiler.DYNAMIC_ASSEMBLY_NAME)] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.Dynamic")]

View File

@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays
Actions.AddRange(actions); Actions.AddRange(actions);
} }
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap) public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
{ {
if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim);
if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim);

View File

@ -2,14 +2,13 @@
// 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.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Taiko.Beatmaps;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
namespace osu.Game.Rulesets.Taiko namespace osu.Game.Rulesets.Taiko
{ {
internal class TaikoDifficultyCalculator : DifficultyCalculator<TaikoHitObject> internal class TaikoDifficultyCalculator : DifficultyCalculator
{ {
private const double star_scaling_factor = 0.04125; private const double star_scaling_factor = 0.04125;
@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko
/// </summary> /// </summary>
private readonly List<TaikoHitObjectDifficulty> difficultyHitObjects = new List<TaikoHitObjectDifficulty>(); private readonly List<TaikoHitObjectDifficulty> difficultyHitObjects = new List<TaikoHitObjectDifficulty>();
public TaikoDifficultyCalculator(Beatmap beatmap) public TaikoDifficultyCalculator(IBeatmap beatmap)
: base(beatmap) : base(beatmap)
{ {
} }
@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko
difficultyHitObjects.Clear(); difficultyHitObjects.Clear();
foreach (var hitObject in Beatmap.HitObjects) foreach (var hitObject in Beatmap.HitObjects)
difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject)); difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject));
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
@ -132,7 +131,5 @@ namespace osu.Game.Rulesets.Taiko
return difficulty; return difficulty;
} }
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter(Beatmap beatmap) => new TaikoBeatmapConverter(true);
} }
} }

View File

@ -12,12 +12,15 @@ using osu.Framework.Graphics;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Taiko.Beatmaps;
namespace osu.Game.Rulesets.Taiko namespace osu.Game.Rulesets.Taiko
{ {
public class TaikoRuleset : Ruleset public class TaikoRuleset : Ruleset
{ {
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset); public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new TaikoRulesetContainer(this, beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[] public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
{ {
@ -31,6 +34,44 @@ namespace osu.Game.Rulesets.Taiko
new KeyBinding(InputKey.MouseRight, TaikoAction.RightRim), new KeyBinding(InputKey.MouseRight, TaikoAction.RightRim),
}; };
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
{
if (mods.HasFlag(LegacyMods.Nightcore))
yield return new TaikoModNightcore();
else if (mods.HasFlag(LegacyMods.DoubleTime))
yield return new TaikoModDoubleTime();
if (mods.HasFlag(LegacyMods.Autoplay))
yield return new TaikoModAutoplay();
if (mods.HasFlag(LegacyMods.Easy))
yield return new TaikoModEasy();
if (mods.HasFlag(LegacyMods.Flashlight))
yield return new TaikoModFlashlight();
if (mods.HasFlag(LegacyMods.HalfTime))
yield return new TaikoModHalfTime();
if (mods.HasFlag(LegacyMods.HardRock))
yield return new TaikoModHardRock();
if (mods.HasFlag(LegacyMods.Hidden))
yield return new TaikoModHidden();
if (mods.HasFlag(LegacyMods.NoFail))
yield return new TaikoModNoFail();
if (mods.HasFlag(LegacyMods.Perfect))
yield return new TaikoModPerfect();
if (mods.HasFlag(LegacyMods.Relax))
yield return new TaikoModRelax();
if (mods.HasFlag(LegacyMods.SuddenDeath))
yield return new TaikoModSuddenDeath();
}
public override IEnumerable<Mod> GetModsFor(ModType type) public override IEnumerable<Mod> GetModsFor(ModType type)
{ {
switch (type) switch (type)
@ -101,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap);
public override int? LegacyID => 1; public override int? LegacyID => 1;

View File

@ -8,7 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Beatmaps;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.Taiko.Scoring;
@ -24,8 +23,8 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject> public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject>
{ {
public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
: base(ruleset, beatmap, isForCurrentRuleset) : base(ruleset, beatmap)
{ {
} }
@ -93,8 +92,6 @@ namespace osu.Game.Rulesets.Taiko.UI
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter(IsForCurrentRuleset);
public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo);
protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo) protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo)

View File

@ -116,8 +116,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
// [TestCase(with_sb)] // [TestCase(with_sb)]
public void TestParity(string beatmap) public void TestParity(string beatmap)
{ {
var beatmaps = decode(beatmap); var legacy = decode(beatmap, out Beatmap json);
beatmaps.jsonDecoded.ShouldDeepEqual(beatmaps.legacyDecoded); json.ShouldDeepEqual(legacy);
} }
/// <summary> /// <summary>
@ -126,15 +126,20 @@ namespace osu.Game.Tests.Beatmaps.Formats
/// </summary> /// </summary>
/// <param name="filename">The .osu file to decode.</param> /// <param name="filename">The .osu file to decode.</param>
/// <returns>The <see cref="Beatmap"/> after being decoded by an <see cref="LegacyBeatmapDecoder"/>.</returns> /// <returns>The <see cref="Beatmap"/> after being decoded by an <see cref="LegacyBeatmapDecoder"/>.</returns>
private Beatmap decodeAsJson(string filename) => decode(filename).jsonDecoded; private Beatmap decodeAsJson(string filename)
{
decode(filename, out Beatmap jsonDecoded);
return jsonDecoded;
}
/// <summary> /// <summary>
/// Reads a .osu file first with a <see cref="LegacyBeatmapDecoder"/>, serializes the resulting <see cref="Beatmap"/> to JSON /// Reads a .osu file first with a <see cref="LegacyBeatmapDecoder"/>, serializes the resulting <see cref="Beatmap"/> to JSON
/// and then deserializes the result back into a <see cref="Beatmap"/> through an <see cref="JsonBeatmapDecoder"/>. /// and then deserializes the result back into a <see cref="Beatmap"/> through an <see cref="JsonBeatmapDecoder"/>.
/// </summary> /// </summary>
/// <param name="filename">The .osu file to decode.</param> /// <param name="filename">The .osu file to decode.</param>
/// <param name="jsonDecoded">The <see cref="Beatmap"/> after being decoded by an <see cref="JsonBeatmapDecoder"/>.</param>
/// <returns>The <see cref="Beatmap"/> after being decoded by an <see cref="LegacyBeatmapDecoder"/>.</returns> /// <returns>The <see cref="Beatmap"/> after being decoded by an <see cref="LegacyBeatmapDecoder"/>.</returns>
private (Beatmap legacyDecoded, Beatmap jsonDecoded) decode(string filename) private Beatmap decode(string filename, out Beatmap jsonDecoded)
{ {
using (var stream = Resource.OpenResource(filename)) using (var stream = Resource.OpenResource(filename))
using (var sr = new StreamReader(stream)) using (var sr = new StreamReader(stream))
@ -149,7 +154,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
sw.Flush(); sw.Flush();
ms.Position = 0; ms.Position = 0;
return (legacyDecoded, new JsonBeatmapDecoder().Decode(sr2));
jsonDecoded = new JsonBeatmapDecoder().Decode(sr2);
return legacyDecoded;
} }
} }
} }

View File

@ -275,13 +275,13 @@ namespace osu.Game.Tests.Beatmaps.IO
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID)); Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID));
Assert.IsTrue(set.Beatmaps.Count > 0); Assert.IsTrue(set.Beatmaps.Count > 0);
var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap;
Assert.IsTrue(beatmap?.HitObjects.Count > 0); Assert.IsTrue(beatmap?.HitObjects.Any() == true);
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap;
Assert.IsTrue(beatmap?.HitObjects.Count > 0); Assert.IsTrue(beatmap?.HitObjects.Any() == true);
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap;
Assert.IsTrue(beatmap?.HitObjects.Count > 0); Assert.IsTrue(beatmap?.HitObjects.Any() == true);
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap;
Assert.IsTrue(beatmap?.HitObjects.Count > 0); Assert.IsTrue(beatmap?.HitObjects.Any() == true);
} }
private void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 60000) private void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 60000)

View File

@ -0,0 +1,62 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Overlays.Profile.Header;
using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
[TestFixture]
public class TestCaseBadgeContainer : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BadgeContainer) };
public TestCaseBadgeContainer()
{
BadgeContainer badgeContainer;
Child = badgeContainer = new BadgeContainer
{
RelativeSizeAxes = Axes.Both
};
AddStep("Show 1 badge", () => badgeContainer.ShowBadges(new[]
{
new Badge
{
AwardedAt = DateTimeOffset.Now,
Description = "Appreciates compasses",
ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png",
}
}));
AddStep("Show 2 badges", () => badgeContainer.ShowBadges(new[]
{
new Badge
{
AwardedAt = DateTimeOffset.Now,
Description = "Contributed to osu!lazer testing",
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.png",
},
new Badge
{
AwardedAt = DateTimeOffset.Now,
Description = "Appreciates compasses",
ImageUrl = "https://assets.ppy.sh/profile-badges/mg2018-1star.png",
}
}));
AddStep("Show many badges", () => badgeContainer.ShowBadges(Enumerable.Range(1, 20).Select(i => new Badge
{
AwardedAt = DateTimeOffset.Now,
Description = $"Contributed to osu!lazer testing {i} times",
ImageUrl = "https://assets.ppy.sh/profile-badges/contributor.jpg",
}).ToArray()));
}
}
}

View File

@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual
private readonly Stack<BeatmapSetInfo> selectedSets = new Stack<BeatmapSetInfo>(); private readonly Stack<BeatmapSetInfo> selectedSets = new Stack<BeatmapSetInfo>();
private readonly HashSet<int> eagerSelectedIDs = new HashSet<int>();
private BeatmapInfo currentSelection; private BeatmapInfo currentSelection;
@ -80,6 +81,7 @@ namespace osu.Game.Tests.Visual
testEmptyTraversal(); testEmptyTraversal();
testHiding(); testHiding();
testSelectingFilteredRuleset(); testSelectingFilteredRuleset();
testCarouselRootIsRandom();
} }
private void ensureRandomFetchSuccess() => private void ensureRandomFetchSuccess() =>
@ -151,6 +153,17 @@ namespace osu.Game.Tests.Visual
AddAssert("Selection is visible", selectedBeatmapVisible); AddAssert("Selection is visible", selectedBeatmapVisible);
} }
private void checkNonmatchingFilter()
{
AddStep("Toggle non-matching filter", () =>
{
carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false);
carousel.Filter(new FilterCriteria(), false);
eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID);
}
);
}
/// <summary> /// <summary>
/// Test keyboard traversal /// Test keyboard traversal
/// </summary> /// </summary>
@ -403,6 +416,23 @@ namespace osu.Game.Tests.Visual
AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle)); AddStep("remove single ruleset set", () => carousel.RemoveBeatmapSet(testSingle));
} }
private void testCarouselRootIsRandom()
{
List<BeatmapSetInfo> beatmapSets = new List<BeatmapSetInfo>();
for (int i = 1; i <= 50; i++)
beatmapSets.Add(createTestBeatmapSet(i));
AddStep("Load 50 Beatmaps", () => { carousel.BeatmapSets = beatmapSets; });
advanceSelection(direction: 1, diff: false);
checkNonmatchingFilter();
checkNonmatchingFilter();
checkNonmatchingFilter();
checkNonmatchingFilter();
checkNonmatchingFilter();
AddAssert("Selection was random", () => eagerSelectedIDs.Count > 1);
}
private BeatmapSetInfo createTestBeatmapSet(int id) private BeatmapSetInfo createTestBeatmapSet(int id)
{ {
return new BeatmapSetInfo return new BeatmapSetInfo

View File

@ -12,8 +12,12 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps;
@ -24,7 +28,7 @@ namespace osu.Game.Tests.Visual
{ {
private RulesetStore rulesets; private RulesetStore rulesets;
private TestBeatmapInfoWedge infoWedge; private TestBeatmapInfoWedge infoWedge;
private readonly List<Beatmap> beatmaps = new List<Beatmap>(); private readonly List<IBeatmap> beatmaps = new List<IBeatmap>();
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>(); private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -52,6 +56,9 @@ namespace osu.Game.Tests.Visual
infoWedge.UpdateBeatmap(beatmap); infoWedge.UpdateBeatmap(beatmap);
}); });
// select part is redundant, but wait for load isn't
selectBeatmap(beatmap.Value.Beatmap);
AddWaitStep(3); AddWaitStep(3);
AddStep("hide", () => { infoWedge.State = Visibility.Hidden; }); AddStep("hide", () => { infoWedge.State = Visibility.Hidden; });
@ -63,18 +70,29 @@ namespace osu.Game.Tests.Visual
foreach (var rulesetInfo in rulesets.AvailableRulesets) foreach (var rulesetInfo in rulesets.AvailableRulesets)
{ {
var ruleset = rulesetInfo.CreateInstance(); var ruleset = rulesetInfo.CreateInstance();
beatmaps.Add(createTestBeatmap(rulesetInfo)); var testBeatmap = createTestBeatmap(rulesetInfo);
var name = rulesetInfo.ShortName; beatmaps.Add(testBeatmap);
selectBeatmap(name);
selectBeatmap(testBeatmap);
testBeatmapLabels(ruleset);
// TODO: adjust cases once more info is shown for other gamemodes // TODO: adjust cases once more info is shown for other gamemodes
switch (ruleset) switch (ruleset)
{ {
case OsuRuleset osu: case OsuRuleset _:
testOsuBeatmap(osu);
testInfoLabels(5); testInfoLabels(5);
break; break;
case TaikoRuleset _:
testInfoLabels(5);
break;
case CatchRuleset _:
testInfoLabels(5);
break;
case ManiaRuleset _:
testInfoLabels(4);
break;
default: default:
testInfoLabels(2); testInfoLabels(2);
break; break;
@ -84,7 +102,7 @@ namespace osu.Game.Tests.Visual
testNullBeatmap(); testNullBeatmap();
} }
private void testOsuBeatmap(OsuRuleset ruleset) private void testBeatmapLabels(Ruleset ruleset)
{ {
AddAssert("check version", () => infoWedge.Info.VersionLabel.Text == $"{ruleset.ShortName}Version"); AddAssert("check version", () => infoWedge.Info.VersionLabel.Text == $"{ruleset.ShortName}Version");
AddAssert("check title", () => infoWedge.Info.TitleLabel.Text == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title"); AddAssert("check title", () => infoWedge.Info.TitleLabel.Text == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title");
@ -108,14 +126,14 @@ namespace osu.Game.Tests.Visual
AddAssert("check no infolabels", () => !infoWedge.Info.InfoLabelContainer.Children.Any()); AddAssert("check no infolabels", () => !infoWedge.Info.InfoLabelContainer.Children.Any());
} }
private void selectBeatmap(string name) private void selectBeatmap(IBeatmap b)
{ {
var infoBefore = infoWedge.Info; BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null;
AddStep($"select {name} beatmap", () => AddStep($"select {b.Metadata.Title} beatmap", () =>
{ {
beatmap.Value = new TestWorkingBeatmap(beatmaps.First(b => b.BeatmapInfo.Ruleset.ShortName == name)); infoBefore = infoWedge.Info;
infoWedge.UpdateBeatmap(beatmap); infoWedge.UpdateBeatmap(beatmap.Value = new TestWorkingBeatmap(b));
}); });
AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load"); AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load");
@ -130,11 +148,11 @@ namespace osu.Game.Tests.Visual
}); });
} }
private Beatmap createTestBeatmap(RulesetInfo ruleset) private IBeatmap createTestBeatmap(RulesetInfo ruleset)
{ {
List<HitObject> objects = new List<HitObject>(); List<HitObject> objects = new List<HitObject>();
for (double i = 0; i < 50000; i += 1000) for (double i = 0; i < 50000; i += 1000)
objects.Add(new HitObject { StartTime = i }); objects.Add(new TestHitObject { StartTime = i });
return new Beatmap return new Beatmap
{ {
@ -149,7 +167,8 @@ namespace osu.Game.Tests.Visual
}, },
Ruleset = ruleset, Ruleset = ruleset,
StarDifficulty = 6, StarDifficulty = 6,
Version = $"{ruleset.ShortName}Version" Version = $"{ruleset.ShortName}Version",
BaseDifficulty = new BeatmapDifficulty()
}, },
HitObjects = objects HitObjects = objects
}; };
@ -159,5 +178,12 @@ namespace osu.Game.Tests.Visual
{ {
public new BufferedWedgeInfo Info => base.Info; public new BufferedWedgeInfo Info => base.Info;
} }
private class TestHitObject : HitObject, IHasPosition
{
public float X { get; } = 0;
public float Y { get; } = 0;
public Vector2 Position { get; } = Vector2.Zero;
}
} }
} }

Some files were not shown because too many files have changed in this diff Show More