diff --git a/.gitattributes b/.gitattributes index e3ffd343db..c61ca25cd2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,6 +15,7 @@ App.config text eol=crlf *.cmd text eol=crlf *.snippet text eol=crlf *.manifest text eol=crlf +*.licenseheader text eol=crlf # Check out with lf (UNIX) line endings *.sh text eol=lf diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 221e4746cb..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,8 +0,0 @@ -Add any details pertaining to developers above the break. - -- [ ] Depends on #PR -- Closes #ISSUE - ---- - -Add a sentence or two describing this change in plain english. This will be displayed on the [changelog](https://osu.ppy.sh/home/changelog). A single screenshot or short gif is also welcomed. \ No newline at end of file diff --git a/.gitignore b/.gitignore index f95a04e517..0e2850a01c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,10 @@ *.userprefs ### Cake ### -tools/* -!tools/cakebuild.csproj +tools/** +build/tools/** + +fastlane/report.xml # Build results bin/[Dd]ebug/ diff --git a/.gitmodules b/.gitmodules index f1c4f5d172..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "osu-resources"] - path = osu-resources - url = https://github.com/ppy/osu-resources \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 10c6f02314..c3306c2db7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -68,6 +68,20 @@ } }, "console": "internalConsole" + }, + { + "name": "Cake: Debug Script", + "type": "coreclr", + "request": "launch", + "program": "${workspaceRoot}/build/tools/Cake.CoreCLR/0.30.0/Cake.dll", + "args": [ + "${workspaceRoot}/build/build.cake", + "--debug", + "--verbosity=diagnostic" + ], + "cwd": "${workspaceRoot}/build", + "stopAtEntry": true, + "externalConsole": false } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2e9bec22c2..de799a7c03 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -70,7 +70,8 @@ "type": "shell", "command": "dotnet", "args": [ - "restore" + "restore", + "osu.sln" ], "problemMatcher": [] } diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..cdd3a6b349 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "fastlane" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..17c0db12e7 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,173 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.0) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) + atomos (0.1.3) + babosa (1.0.2) + claide (1.0.2) + colored (1.2) + colored2 (3.1.2) + commander-fastlane (4.4.6) + highline (~> 1.7.2) + declarative (0.0.10) + declarative-option (0.1.0) + digest-crc (0.4.1) + domain_name (0.5.20180417) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.7.1) + emoji_regex (1.0.1) + excon (0.62.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.6) + faraday (>= 0.7.4) + http-cookie (~> 1.0.0) + faraday_middleware (0.13.1) + faraday (>= 0.7.4, < 1.0) + fastimage (2.1.5) + fastlane (2.117.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.3, < 3.0.0) + babosa (>= 1.0.2, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander-fastlane (>= 4.4.6, < 5.0.0) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 2.0) + excon (>= 0.45.0, < 1.0.0) + faraday (~> 0.9) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 0.9) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-api-client (>= 0.21.2, < 0.24.0) + google-cloud-storage (>= 1.15.0, < 2.0.0) + highline (>= 1.7.2, < 2.0.0) + json (< 3.0.0) + mini_magick (~> 4.5.1) + multi_json + multi_xml (~> 0.5) + multipart-post (~> 2.0.0) + plist (>= 3.1.0, < 4.0.0) + public_suffix (~> 2.0.0) + rubyzip (>= 1.2.2, < 2.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + slack-notifier (>= 2.0.0, < 3.0.0) + terminal-notifier (>= 1.6.2, < 2.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.6.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-clean_testflight_testers (0.2.0) + fastlane-plugin-souyuz (0.8.1) + souyuz (>= 0.8.1) + fastlane-plugin-xamarin (0.6.3) + gh_inspector (1.1.3) + google-api-client (0.23.9) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.5, < 0.7.0) + httpclient (>= 2.8.1, < 3.0) + mime-types (~> 3.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.9) + google-cloud-core (1.3.0) + google-cloud-env (~> 1.0) + google-cloud-env (1.0.5) + faraday (~> 0.11) + google-cloud-storage (1.16.0) + digest-crc (~> 0.4) + google-api-client (~> 0.23) + google-cloud-core (~> 1.2) + googleauth (>= 0.6.2, < 0.10.0) + googleauth (0.6.7) + faraday (~> 0.12) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.7) + highline (1.7.10) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + json (2.2.0) + jwt (2.1.0) + memoist (0.16.0) + mime-types (3.2.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2018.0812) + mini_magick (4.5.1) + mini_portile2 (2.4.0) + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nanaimo (0.2.6) + naturally (2.2.0) + nokogiri (1.10.1) + mini_portile2 (~> 2.4.0) + os (1.0.0) + plist (3.5.0) + public_suffix (2.0.5) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rouge (2.0.7) + rubyzip (1.2.2) + security (0.1.3) + signet (0.11.0) + addressable (~> 2.3) + faraday (~> 0.9) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.5) + CFPropertyList + naturally + slack-notifier (2.3.2) + souyuz (0.8.1) + fastlane (>= 2.29.0) + highline (~> 1.7) + nokogiri (~> 1.7) + terminal-notifier (1.8.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + tty-cursor (0.6.1) + tty-screen (0.6.5) + tty-spinner (0.9.0) + tty-cursor (~> 0.6.0) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.5) + unicode-display_width (1.4.1) + word_wrap (1.0.0) + xcodeproj (1.8.1) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.6) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.0) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + fastlane + fastlane-plugin-clean_testflight_testers + fastlane-plugin-souyuz + fastlane-plugin-xamarin + +BUNDLED WITH + 2.0.1 diff --git a/LICENCE b/LICENCE index a11a7ce75b..21c6a7090f 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2018 ppy Pty Ltd . +Copyright (c) 2019 ppy Pty Ltd . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a2f6472371..abddb1faa1 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,85 @@ -# osu! [![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) +# osu! + +[![Build status](https://ci.appveyor.com/api/projects/status/u2p01nx7l6og8buh?svg=true)](https://ci.appveyor.com/project/peppy/osu) [![CodeFactor](https://www.codefactor.io/repository/github/ppy/osu/badge)](https://www.codefactor.io/repository/github/ppy/osu) [![dev chat](https://discordapp.com/api/guilds/188630481301012481/widget.png?style=shield)](https://discord.gg/ppy) Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the beginning of an open era! Commonly known by the codename "osu!lazer". Pew pew. -# Status +## Status This project is still heavily under development, but is in a state where users are encouraged to try it out and keep it installed alongside the stable osu! client. It will continue to evolve over the coming months and hopefully bring some new unique features to the table. We are accepting bug reports (please report with as much detail as possible). Feature requests are welcome as long as you read and understand the contribution guidelines listed below. -# Requirements +## Requirements - A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed. -- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio Community Edition](https://www.visualstudio.com/) (Windows), [Visual Studio Code](https://code.visualstudio.com/) (with the C# plugin installed) or [Jetbrains Rider](https://www.jetbrains.com/rider/) (commercial). +- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). +- Note that there are **[additional requirements for Windows 7 and Windows 8.1](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** which you may need to manually install if your operating system is not up-to-date. -# Building and running +## Running osu! -If you are not interested in developing the game, please head over to the [releases](https://github.com/ppy/osu/releases) to download a precompiled build with automatic updating enabled (download and run the install executable for your platform). +### Releases -Clone the repository including submodules +If you are not interested in developing the game, please head over to the [releases](https://github.com/ppy/osu/releases) to download a precompiled build with automatic updating enabled. -`git clone --recurse-submodules https://github.com/ppy/osu` +- Windows (x64) users should download and run `install.exe`. +- macOS users (10.12 "Sierra" and higher) should download and run `osu.app.zip`. +- iOS users can join the [TestFlight beta program](https://t.co/xQJmHkfC18). -Build and run +If your platform is not listed above, there is still a chance you can manually build it by following the instructions below. -- Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included) -- From command line using `dotnet run --project osu.Desktop`. When building for non-development purposes, add `-c Release` to gain higher performance. -- To run with code analysis, instead use `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternative, you can install resharper or use rider to get inline support in your IDE of choice. +### Downloading the source code -Note: If you run from command line under linux, you will need to prefix the output folder to your `LD_LIBRARY_PATH`. See `.vscode/launch.json` for an example +Clone the repository **including submodules**: -If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build. +```shell +git clone https://github.com/ppy/osu +cd osu +``` -# Contributing +To update the source code to the latest commit, run the following command inside the `osu` directory: + +```shell +git pull +``` + +### Building + +Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided below. + +> Visual Studio Code users must run the `Restore` task before any build attempt. + +You can also build and run osu! from the command-line with a single command: + +```shell +dotnet run --project osu.Desktop +``` + +If you are not interested in debugging osu!, you can add `-c Release` to gain performance. In this case, you must replace `Debug` with `Release` in any commands mentioned in this document. + +If the build fails, try to restore nuget packages with `dotnet restore`. + +#### A note for Linux users + +On Linux, the environment variable `LD_LIBRARY_PATH` must point to the build directory, located at `osu.Desktop/bin/Debug/$NETCORE_VERSION`. + +`$NETCORE_VERSION` is the version of .NET Core SDK. You can have it with `grep TargetFramework osu.Desktop/osu.Desktop.csproj | sed -r 's/.*>(.*)<\/.*/\1/'`. + +For example, you can run osu! with the following command: + +```shell +LD_LIBRARY_PATH="$(pwd)/osu.Desktop/bin/Debug/netcoreapp2.2" dotnet run --project osu.Desktop +``` + +### Testing with resource/framework modifications + +Sometimes it may be necessary to cross-test changes in [osu-resources](https://github.com/ppy/osu-resources) or [osu-framework](https://github.com/ppy/osu-framework). This can be achieved by running some commands as documented on the [osu-resources](https://github.com/ppy/osu-resources/wiki/Testing-local-resources-checkout-with-other-projects) and [osu-framework](https://github.com/ppy/osu-framework/wiki/Testing-local-framework-checkout-with-other-projects) wiki pages. + +### Code analysis + +Code analysis can be run with `powershell ./build.ps1` or `build.sh`. This is currently only supported under windows due to [resharper cli shortcomings](https://youtrack.jetbrains.com/issue/RSRP-410004). Alternatively, you can install resharper or use rider to get inline support in your IDE of choice. + +## Contributing We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention on having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted. @@ -41,7 +89,7 @@ Contributions can be made via pull requests to this repository. We hope to credi Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. I welcome all feedback so we can make contributing to this project as pain-free as possible. -# Licence +## Licence The osu! client code and framework are licensed under the [MIT licence](https://opensource.org/licenses/MIT). Please see [the licence file](LICENCE) for more information. [tl;dr](https://tldrlegal.com/license/mit-license) you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. diff --git a/build.ps1 b/build.ps1 index 9968673c90..c6a0bf6d4a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -41,27 +41,28 @@ Param( [switch]$ShowDescription, [Alias("WhatIf", "Noop")] [switch]$DryRun, - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)] [string[]]$ScriptArgs ) Write-Host "Preparing to run build script..." # Determine the script root for resolving other paths. -if(!$PSScriptRoot){ +if(!$PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # Resolve the paths for resources used for debugging. -$TOOLS_DIR = Join-Path $PSScriptRoot "tools" -$CAKE_CSPROJ = Join-Path $TOOLS_DIR "cakebuild.csproj" +$BUILD_DIR = Join-Path $PSScriptRoot "build" +$TOOLS_DIR = Join-Path $BUILD_DIR "tools" +$CAKE_CSPROJ = Join-Path $BUILD_DIR "cakebuild.csproj" # Install the required tools locally. Write-Host "Restoring cake tools..." Invoke-Expression "dotnet restore `"$CAKE_CSPROJ`" --packages `"$TOOLS_DIR`"" | Out-Null # Find the Cake executable -$CAKE_EXECUTABLE = (Get-ChildItem -Path ./tools/cake.coreclr/ -Filter Cake.dll -Recurse).FullName +$CAKE_EXECUTABLE = (Get-ChildItem -Path "$TOOLS_DIR/cake.coreclr/" -Filter Cake.dll -Recurse).FullName # Build Cake arguments $cakeArguments = @("$Script"); @@ -75,5 +76,7 @@ $cakeArguments += $ScriptArgs # Start Cake Write-Host "Running build script..." +Push-Location -Path $BUILD_DIR Invoke-Expression "dotnet `"$CAKE_EXECUTABLE`" $cakeArguments" +Pop-Location exit $LASTEXITCODE diff --git a/build.sh b/build.sh index caf1702f41..8f1ef5b455 100755 --- a/build.sh +++ b/build.sh @@ -6,12 +6,13 @@ echo "Preparing to run build script..." +cd build SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) TOOLS_DIR=$SCRIPT_DIR/tools CAKE_BINARY_PATH=$TOOLS_DIR/"cake.coreclr" SCRIPT="build.cake" -CAKE_CSPROJ=$TOOLS_DIR/"cakebuild.csproj" +CAKE_CSPROJ=$SCRIPT_DIR/"cakebuild.csproj" # Parse arguments. CAKE_ARGUMENTS=() diff --git a/build.cake b/build/build.cake similarity index 75% rename from build.cake rename to build/build.cake index bc7dfafb8c..81deeb3bc7 100644 --- a/build.cake +++ b/build/build.cake @@ -1,6 +1,7 @@ #addin "nuget:?package=CodeFileSanity&version=0.0.21" #addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.2" #tool "nuget:?package=NVika.MSBuild&version=1.0.1" +var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); /////////////////////////////////////////////////////////////////////////////// // ARGUMENTS @@ -9,30 +10,24 @@ var target = Argument("target", "Build"); var configuration = Argument("configuration", "Release"); -var osuSolution = new FilePath("./osu.sln"); +var rootDirectory = new DirectoryPath(".."); +var solution = rootDirectory.CombineWithFilePath("osu.sln"); /////////////////////////////////////////////////////////////////////////////// // TASKS /////////////////////////////////////////////////////////////////////////////// -Task("Restore") - .Does(() => { - DotNetCoreRestore(osuSolution.FullPath); - }); - Task("Compile") - .IsDependentOn("Restore") .Does(() => { - DotNetCoreBuild(osuSolution.FullPath, new DotNetCoreBuildSettings { + DotNetCoreBuild(solution.FullPath, new DotNetCoreBuildSettings { Configuration = configuration, - NoRestore = true, }); }); Task("Test") .IsDependentOn("Compile") .Does(() => { - var testAssemblies = GetFiles("**/*.Tests/bin/**/*.Tests.dll"); + var testAssemblies = GetFiles(rootDirectory + "/**/*.Tests/bin/**/*.Tests.dll"); DotNetCoreVSTest(testAssemblies, new DotNetCoreVSTestSettings { Logger = AppVeyor.IsRunningOnAppVeyor ? "Appveyor" : $"trx", @@ -46,9 +41,7 @@ Task("InspectCode") .WithCriteria(IsRunningOnWindows()) .IsDependentOn("Compile") .Does(() => { - var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); - - InspectCode(osuSolution, new InspectCodeSettings { + InspectCode(solution, new InspectCodeSettings { CachesHome = "inspectcode", OutputFile = "inspectcodereport.xml", }); @@ -59,7 +52,7 @@ Task("InspectCode") Task("CodeFileSanity") .Does(() => { ValidateCodeSanity(new ValidateCodeSanitySettings { - RootDirectory = ".", + RootDirectory = rootDirectory.FullPath, IsAppveyorBuild = AppVeyor.IsRunningOnAppVeyor }); }); diff --git a/tools/cakebuild.csproj b/build/cakebuild.csproj similarity index 100% rename from tools/cakebuild.csproj rename to build/cakebuild.csproj diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 0000000000..083de66985 --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,2 @@ +app_identifier("sh.ppy.osulazer") # The bundle identifier of your app +apple_id("apple-dev@ppy.sh") # Your Apple email address diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000000..3f64bcdf19 --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,65 @@ +update_fastlane + +default_platform(:ios) + +platform :ios do + lane :testflight_prune_dry do + clean_testflight_testers(days_of_inactivity:45, dry_run: true) + end + + # Specify a custom number for what's "inactive" + lane :testflight_prune do + clean_testflight_testers(days_of_inactivity: 45) # 120 days, so about 4 months + end + + lane :update_version do |options| + options[:plist_path] = '../osu.iOS/Info.plist' + app_version(options) + end + + desc 'Deploy to testflight' + lane :beta do |options| + update_version(options) + + provision( + type: 'appstore' + ) + + build( + build_configuration: 'Release', + build_platform: 'iPhone' + ) + + client = HTTPClient.new + changelog = client.get_content 'https://gist.githubusercontent.com/peppy/ab89c29dcc0dce95f39eb218e8fad197/raw' + changelog.gsub!('$BUILD_ID', options[:build]) + + pilot( + wait_processing_interval: 900, + changelog: changelog, + ipa: './osu.iOS/bin/iPhone/Release/osu.iOS.ipa' + ) + end + + desc 'Compile the project' + lane :build do + nuget_restore( + project_path: 'osu.iOS.sln' + ) + + souyuz( + platform: "ios", + build_target: "osu_iOS", + plist_path: "../osu.iOS/Info.plist" + ) + end + + desc 'Install provisioning profiles using match' + lane :provision do |options| + if Helper.is_ci? + options[:readonly] = true + end + + match(options) + end +end diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 0000000000..40c974b09e --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1 @@ +git_url('https://github.com/peppy/apple-certificates') diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 0000000000..9f4f47f213 --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,7 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-clean_testflight_testers' +gem 'fastlane-plugin-souyuz' +gem 'fastlane-plugin-xamarin' diff --git a/fastlane/README.md b/fastlane/README.md new file mode 100644 index 0000000000..53bbc62cae --- /dev/null +++ b/fastlane/README.md @@ -0,0 +1,54 @@ +fastlane documentation +================ +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +``` +xcode-select --install +``` + +Install _fastlane_ using +``` +[sudo] gem install fastlane -NV +``` +or alternatively using `brew cask install fastlane` + +# Available Actions +## iOS +### ios testflight_prune_dry +``` +fastlane ios testflight_prune_dry +``` + +### ios testflight_prune +``` +fastlane ios testflight_prune +``` + +### ios update_version +``` +fastlane ios update_version +``` + +### ios beta +``` +fastlane ios beta +``` +Deploy to testflight +### ios build +``` +fastlane ios build +``` +Compile the project +### ios provision +``` +fastlane ios provision +``` +Install provisioning profiles using match + +---- + +This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. +More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). +The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/osu-resources b/osu-resources deleted file mode 160000 index 9880089b4e..0000000000 --- a/osu-resources +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9880089b4e8fcd78d68f30c8a40d43bf8dccca86 diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 2eeb112450..7e5b003f03 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -16,7 +16,6 @@ using osu.Desktop.Updater; using osu.Framework; using osu.Framework.Platform.Windows; using osu.Framework.Screens; -using osu.Game.Screens; using osu.Game.Screens.Menu; namespace osu.Desktop @@ -63,9 +62,10 @@ namespace osu.Desktop } } - protected override void ScreenChanged(OsuScreen current, Screen newScreen) + protected override void ScreenChanged(IScreen lastScreen, IScreen newScreen) { - base.ScreenChanged(current, newScreen); + base.ScreenChanged(lastScreen, newScreen); + switch (newScreen) { case Intro _: @@ -83,8 +83,7 @@ namespace osu.Desktop public override void SetHost(GameHost host) { base.SetHost(host); - var desktopWindow = host.Window as DesktopGameWindow; - if (desktopWindow != null) + if (host.Window is DesktopGameWindow desktopWindow) { desktopWindow.CursorState |= CursorState.Hidden; @@ -97,7 +96,7 @@ namespace osu.Desktop private void fileDrop(object sender, FileDropEventArgs e) { - var filePaths = new[] { e.FileName }; + var filePaths = e.FileNames; var firstExtension = Path.GetExtension(filePaths.First()); diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index c1fd34d009..b8a0e337b6 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -60,7 +60,7 @@ namespace osu.Desktop.Overlays { new OsuSpriteText { - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = game.Name }, new OsuSpriteText @@ -74,9 +74,8 @@ namespace osu.Desktop.Overlays { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Colour = colours.Yellow, - Font = @"Venera", Text = @"Development Build" }, new Sprite diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 257155478f..ff9972ac48 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs index 6956eb30b0..ab05888408 100644 --- a/osu.Desktop/Updater/SimpleUpdateManager.cs +++ b/osu.Desktop/Updater/SimpleUpdateManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Threading.Tasks; diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs index 19383d617f..6400fd776d 100644 --- a/osu.Desktop/Updater/SquirrelUpdateManager.cs +++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index ad08f57c3a..66db439c82 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -22,14 +22,13 @@ - - - + + diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index cdd232a9b2..a26b35fcd5 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -12,7 +12,7 @@ click the circles. to the beat. click the circles. testing - Copyright ppy Pty Ltd 2007-2018 + Copyright (c) 2019 ppy Pty Ltd en-AU diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs new file mode 100644 index 0000000000..39fe3dac25 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.iOS/AppDelegate.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; +using osu.Game.Tests; + +namespace osu.Game.Rulesets.Catch.Tests.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs new file mode 100644 index 0000000000..44817c1304 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.Game.Rulesets.Catch.Tests.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Entitlements.plist b/osu.Game.Rulesets.Catch.Tests.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist new file mode 100644 index 0000000000..5115746cbb --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleName + osu.Game.Rulesets.Catch.Tests.iOS + CFBundleIdentifier + ppy.osu-Game-Rulesets-Catch-Tests-iOS + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj new file mode 100644 index 0000000000..37e7c45a4e --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests.iOS/osu.Game.Rulesets.Catch.Tests.iOS.csproj @@ -0,0 +1,45 @@ + + + + + Debug + iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70} + Exe + osu.Game.Rulesets.Catch.Tests + osu.Game.Rulesets.Catch.Tests.iOS + + + + + + + libbass.a + PreserveNewest + + + libbass_fx.a + PreserveNewest + + + Linker.xml + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} + osu.Game.Rulesets.Catch + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs index 162624da57..7f85d4ccce 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchBeatmapConversionTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -21,6 +21,7 @@ namespace osu.Game.Rulesets.Catch.Tests [TestCase("basic")] [TestCase("spinner")] [TestCase("spinner-and-circles")] + [TestCase("slider")] public new void Test(string name) { base.Test(name); @@ -33,13 +34,16 @@ namespace osu.Game.Rulesets.Catch.Tests case JuiceStream stream: foreach (var nested in stream.NestedHitObjects) yield return new ConvertValue((CatchHitObject)nested); + break; case BananaShower shower: foreach (var nested in shower.NestedHitObjects) yield return new ConvertValue((CatchHitObject)nested); + break; default: yield return new ConvertValue((CatchHitObject)hitObject); + break; } } diff --git a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs new file mode 100644 index 0000000000..51fe0b035d --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Difficulty; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Catch.Tests +{ + public class CatchDifficultyCalculatorTest : DifficultyCalculatorTest + { + protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; + + [TestCase(4.2058561036909863d, "diffcalc-test")] + public void Test(double expected, string name) + => base.Test(expected, name); + + protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(new CatchRuleset(), beatmap); + + protected override Ruleset CreateRuleset() => new CatchRuleset(); + } +} diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs index fc3809fae4..fbb2db33b0 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseAutoJuiceStream.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Game.Beatmaps; @@ -13,7 +13,7 @@ using osuTK; namespace osu.Game.Rulesets.Catch.Tests { - public class TestCaseAutoJuiceStream : TestCasePlayer + public class TestCaseAutoJuiceStream : PlayerTestCase { public TestCaseAutoJuiceStream() : base(new CatchRuleset()) diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs index b5cf0e3d1d..d413b53d17 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseBananaShower.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,11 +8,12 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer + public class TestCaseBananaShower : PlayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -20,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.Tests typeof(DrawableBananaShower), typeof(CatchRuleset), - typeof(CatchRulesetContainer), + typeof(DrawableCatchRuleset), }; public TestCaseBananaShower() diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs index a2c886f1f3..5b242d05d7 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchPlayer.cs @@ -1,14 +1,16 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer + public class TestCaseCatchPlayer : PlayerTestCase { - public TestCaseCatchPlayer() : base(new CatchRuleset()) + public TestCaseCatchPlayer() + : base(new CatchRuleset()) { } } diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs index 8a90b48180..5a16a23a4e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatchStacker.cs @@ -1,14 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer + public class TestCaseCatchStacker : PlayerTestCase { public TestCaseCatchStacker() : base(new CatchRuleset()) @@ -26,7 +27,6 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - for (int i = 0; i < 512; i++) beatmap.HitObjects.Add(new Fruit { X = 0.5f + i / 2048f * (i % 10 - 5), StartTime = i * 100, NewCombo = i % 8 == 0 }); diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs index 25f7ca108d..5e3fcd239f 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseCatcherArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs index 7b6773ad58..a59f4ce150 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseFruitObjects.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs index 14487b2c7f..a7e7f0ab14 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestCaseHyperDash.cs @@ -1,28 +1,46 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests { [TestFixture] - public class TestCaseHyperDash : Game.Tests.Visual.TestCasePlayer + public class TestCaseHyperDash : PlayerTestCase { public TestCaseHyperDash() : base(new CatchRuleset()) { } + [BackgroundDependencyLoader] + private void load() + { + AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash); + } + protected override IBeatmap CreateBeatmap(Ruleset ruleset) { - var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } }; + var beatmap = new Beatmap + { + BeatmapInfo = + { + Ruleset = ruleset.RulesetInfo, + BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f } + } + }; + // Should produce a hyper-dash + beatmap.HitObjects.Add(new Fruit { StartTime = 816, X = 308 / 512f, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 1008, X = 56 / 512f, }); for (int i = 0; i < 512; i++) if (i % 5 < 3) - beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = i * 100, NewCombo = i % 8 == 0 }); + beatmap.HitObjects.Add(new Fruit { X = i % 10 < 5 ? 0.02f : 0.98f, StartTime = 2000 + i * 100, NewCombo = i % 8 == 0 }); return beatmap; } diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index e875af5a30..3f8b3bf086 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,9 +2,9 @@ - + - + diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs index 5b4af6ea8a..c5ced26e42 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index c3dc9499c2..0d9a663b9f 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 22c1180c09..78b5a510b2 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -56,6 +56,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps rng.Next(); // osu!stable retrieved a random banana rotation rng.Next(); // osu!stable retrieved a random banana colour } + break; case JuiceStream juiceStream: foreach (var nested in juiceStream.NestedHitObjects) @@ -67,6 +68,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps rng.Next(); // osu!stable retrieved a random droplet rotation hitObject.X = MathHelper.Clamp(hitObject.X, 0, 1); } + break; } } @@ -98,7 +100,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps CatchHitObject nextObject = objectWithDroplets[i + 1]; int thisDirection = nextObject.X > currentObject.X ? 1 : -1; - double timeToNext = nextObject.StartTime - currentObject.StartTime; + double timeToNext = nextObject.StartTime - currentObject.StartTime - 1000f / 60f / 4; // 1/4th of a frame of grace time, taken from osu-stable double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth); float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext); if (distanceToHyper < 0) diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 4f976bb7b2..021d7a7efe 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Framework.Input.Bindings; @@ -19,8 +19,10 @@ namespace osu.Game.Rulesets.Catch { [Description("Move left")] MoveLeft, + [Description("Move right")] MoveRight, + [Description("Engage dash")] Dash, } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 2b0de183d3..388cff9aee 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -10,6 +10,7 @@ using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new CatchRulesetContainer(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableCatchRuleset(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); @@ -100,6 +101,11 @@ namespace osu.Game.Rulesets.Catch new MultiMod(new CatchModAutoplay(), new ModCinema()), new CatchModRelax(), }; + case ModType.Fun: + return new Mod[] + { + new MultiMod(new ModWindUp(), new ModWindDown()) + }; default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs index f6535380c8..75f5b18607 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -10,10 +9,5 @@ namespace osu.Game.Rulesets.Catch.Difficulty { public double ApproachRate; public int MaxCombo; - - public CatchDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index a763989750..b4998347f4 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,149 +1,102 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; +using osu.Game.Rulesets.Catch.Difficulty.Skills; +using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { - - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 750; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.94; - private const double star_scaling_factor = 0.145; + protected override int SectionLength => 750; + public CatchDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new CatchDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new CatchDifficultyAttributes { Mods = mods }; - var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty); - float halfCatchWidth = catcher.CatchWidth * 0.5f; + // this is the same as osu!, so there's potential to share the implementation... maybe + double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; - var difficultyHitObjects = new List(); - - foreach (var hitObject in beatmap.HitObjects) + return new CatchDifficultyAttributes { + StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor, + Mods = mods, + ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, + MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)) + }; + } + + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + float halfCatchWidth; + + using (var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty)) + { + halfCatchWidth = catcher.CatchWidth * 0.5f; + halfCatchWidth *= 0.8f; // We're only using 80% of the catcher's width to simulate imperfect gameplay. + } + + CatchHitObject lastObject = null; + + foreach (var hitObject in beatmap.HitObjects.OfType()) + { + if (lastObject == null) + { + lastObject = hitObject; + continue; + } + switch (hitObject) { // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. case Fruit fruit: - difficultyHitObjects.Add(new CatchDifficultyHitObject(fruit, halfCatchWidth)); + yield return new CatchDifficultyHitObject(fruit, lastObject, clockRate, halfCatchWidth); + + lastObject = hitObject; break; case JuiceStream _: - difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); + foreach (var nested in hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet))) + { + yield return new CatchDifficultyHitObject(nested, lastObject, clockRate, halfCatchWidth); + + lastObject = nested; + } + break; } } - - difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new CatchDifficultyAttributes(mods, 0); - - // this is the same as osu!, so there's potential to share the implementation... maybe - double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; - double starRating = Math.Sqrt(calculateDifficulty(difficultyHitObjects, timeRate)) * star_scaling_factor; - - return new CatchDifficultyAttributes(mods, starRating) - { - ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, - MaxCombo = difficultyHitObjects.Count - }; } - private bool calculateStrainValues(List objects, double timeRate) + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] { - CatchDifficultyHitObject lastObject = null; + new Movement(), + }; - if (!objects.Any()) return false; - - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - foreach (var currentObject in objects) - { - if (lastObject != null) - currentObject.CalculateStrains(lastObject, timeRate); - - lastObject = currentObject; - } - - return true; - } - - private double calculateDifficulty(List objects, double timeRate) + protected override Mod[] DifficultyAdjustmentMods => new Mod[] { - // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - var highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - CatchDifficultyHitObject previousHitObject = null; - foreach (CatchDifficultyHitObject hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double decay = Math.Pow(CatchDifficultyHitObject.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.Strain * decay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - maximumStrain = Math.Max(hitObject.Strain, maximumStrain); - - previousHitObject = hitObject; - } - - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= decay_weight; - } - - return difficulty; - } + new CatchModDoubleTime(), + new CatchModHalfTime(), + new CatchModHardRock(), + new CatchModEasy(), + }; } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs deleted file mode 100644 index bd7796ed91..0000000000 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.UI; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Difficulty -{ - public class CatchDifficultyHitObject - { - internal static readonly double DECAY_BASE = 0.20; - private const float normalized_hitobject_radius = 41.0f; - private const float absolute_player_positioning_error = 16f; - private readonly float playerPositioningError; - - internal CatchHitObject BaseHitObject; - - /// - /// Measures jump difficulty. CtB doesn't have something like button pressing speed or accuracy - /// - internal double Strain = 1; - - /// - /// This is required to keep track of lazy player movement (always moving only as far as necessary) - /// Without this quick repeat sliders / weirdly shaped streams might become ridiculously overrated - /// - internal float PlayerPositionOffset; - internal float LastMovement; - - internal float NormalizedPosition; - internal float ActualNormalizedPosition => NormalizedPosition + PlayerPositionOffset; - - internal CatchDifficultyHitObject(CatchHitObject baseHitObject, float catcherWidthHalf) - { - BaseHitObject = baseHitObject; - - // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. - float scalingFactor = normalized_hitobject_radius / catcherWidthHalf; - - playerPositioningError = absolute_player_positioning_error; // * scalingFactor; - NormalizedPosition = baseHitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; - } - - private const double direction_change_bonus = 12.5; - internal void CalculateStrains(CatchDifficultyHitObject previousHitObject, double timeRate) - { - // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. - // See Taiko feedback thread. - double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); - - // Update new position with lazy movement. - PlayerPositionOffset = - MathHelper.Clamp( - previousHitObject.ActualNormalizedPosition, - NormalizedPosition - (normalized_hitobject_radius - playerPositioningError), - NormalizedPosition + (normalized_hitobject_radius - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. - - NormalizedPosition; // Subtract HitObject position to obtain offset - - LastMovement = DistanceTo(previousHitObject); - double addition = spacingWeight(LastMovement); - - if (NormalizedPosition < previousHitObject.NormalizedPosition) - { - LastMovement = -LastMovement; - } - - CatchHitObject previousHitCircle = previousHitObject.BaseHitObject; - - double additionBonus = 0; - double sqrtTime = Math.Sqrt(Math.Max(timeElapsed, 25)); - - // Direction changes give an extra point! - if (Math.Abs(LastMovement) > 0.1) - { - if (Math.Abs(previousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(previousHitObject.LastMovement)) - { - double bonus = direction_change_bonus / sqrtTime; - - // Weight bonus by how - double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; - - // We want time to play a role twice here! - addition += bonus * bonusFactor; - - // Bonus for tougher direction switches and "almost" hyperdashes at this point - if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) - { - additionBonus += 0.3 * bonusFactor; - } - } - - // Base bonus for every movement, giving some weight to streams. - addition += 7.5 * Math.Min(Math.Abs(LastMovement), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtTime; - } - - // Bonus for "almost" hyperdashes at corner points - if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) - { - if (!previousHitCircle.HyperDash) - { - additionBonus += 1.0; - } - else - { - // After a hyperdash we ARE in the correct position. Always! - PlayerPositionOffset = 0; - } - - addition *= 1.0 + additionBonus * ((10 - previousHitCircle.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); - } - - addition *= 850.0 / Math.Max(timeElapsed, 25); - - Strain = previousHitObject.Strain * decay + addition; - } - - private static double spacingWeight(float distance) - { - return Math.Pow(distance, 1.3) / 500; - } - - internal float DistanceTo(CatchDifficultyHitObject other) - { - return Math.Abs(ActualNormalizedPosition - other.ActualNormalizedPosition); - } - } -} diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs new file mode 100644 index 0000000000..24e526ed19 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing +{ + public class CatchDifficultyHitObject : DifficultyHitObject + { + private const float normalized_hitobject_radius = 41.0f; + + public new CatchHitObject BaseObject => (CatchHitObject)base.BaseObject; + + public new CatchHitObject LastObject => (CatchHitObject)base.LastObject; + + public readonly float NormalizedPosition; + public readonly float LastNormalizedPosition; + + /// + /// Milliseconds elapsed since the start time of the previous , with a minimum of 25ms. + /// + public readonly double StrainTime; + + public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth) + : base(hitObject, lastObject, clockRate) + { + // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. + var scalingFactor = normalized_hitobject_radius / halfCatcherWidth; + + NormalizedPosition = BaseObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; + LastNormalizedPosition = LastObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; + + // Every strain interval is hard capped at the equivalent of 600 BPM streaming speed as a safety measure + StrainTime = Math.Max(25, DeltaTime); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs new file mode 100644 index 0000000000..d146153294 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Difficulty.Skills +{ + public class Movement : Skill + { + private const float absolute_player_positioning_error = 16f; + private const float normalized_hitobject_radius = 41.0f; + private const double direction_change_bonus = 12.5; + + protected override double SkillMultiplier => 850; + protected override double StrainDecayBase => 0.2; + + protected override double DecayWeight => 0.94; + + private float? lastPlayerPosition; + private float lastDistanceMoved; + + protected override double StrainValueOf(DifficultyHitObject current) + { + var catchCurrent = (CatchDifficultyHitObject)current; + + if (lastPlayerPosition == null) + lastPlayerPosition = catchCurrent.LastNormalizedPosition; + + float playerPosition = MathHelper.Clamp( + lastPlayerPosition.Value, + catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), + catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) + ); + + float distanceMoved = playerPosition - lastPlayerPosition.Value; + + double distanceAddition = Math.Pow(Math.Abs(distanceMoved), 1.3) / 500; + double sqrtStrain = Math.Sqrt(catchCurrent.StrainTime); + + double bonus = 0; + + // Direction changes give an extra point! + if (Math.Abs(distanceMoved) > 0.1) + { + if (Math.Abs(lastDistanceMoved) > 0.1 && Math.Sign(distanceMoved) != Math.Sign(lastDistanceMoved)) + { + double bonusFactor = Math.Min(absolute_player_positioning_error, Math.Abs(distanceMoved)) / absolute_player_positioning_error; + + distanceAddition += direction_change_bonus / sqrtStrain * bonusFactor; + + // Bonus for tougher direction switches and "almost" hyperdashes at this point + if (catchCurrent.LastObject.DistanceToHyperDash <= 10 / CatchPlayfield.BASE_WIDTH) + bonus = 0.3 * bonusFactor; + } + + // Base bonus for every movement, giving some weight to streams. + distanceAddition += 7.5 * Math.Min(Math.Abs(distanceMoved), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtStrain; + } + + // Bonus for "almost" hyperdashes at corner points + if (catchCurrent.LastObject.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) + { + if (!catchCurrent.LastObject.HyperDash) + bonus += 1.0; + else + { + // After a hyperdash we ARE in the correct position. Always! + playerPosition = catchCurrent.NormalizedPosition; + } + + distanceAddition *= 1.0 + bonus * ((10 - catchCurrent.LastObject.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); + } + + lastPlayerPosition = playerPosition; + lastDistanceMoved = distanceMoved; + + return distanceAddition / catchCurrent.StrainTime; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index d89d987f95..4e64753a65 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs index 1fbf1db7f7..2598dee156 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchDropletJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index b20bc43886..5d7ef04dd2 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs index fc933020d3..b8c51b7b60 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchTinyDropletJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs index 5b3835755a..b3605b013b 100644 --- a/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Catch/MathUtils/FastRandom.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; @@ -33,11 +33,11 @@ namespace osu.Game.Rulesets.Catch.MathUtils /// The random value. public uint NextUInt() { - uint t = _x ^ _x << 11; + uint t = _x ^ (_x << 11); _x = _y; _y = _z; _z = _w; - return _w = _w ^ _w >> 19 ^ t ^ t >> 8; + return _w = _w ^ (_w >> 19) ^ t ^ (t >> 8); } /// diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 8bba73ed64..692e63fa69 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Mods { public class CatchModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) => new Score + public override Score CreateReplayScore(IBeatmap beatmap) => new Score { ScoreInfo = new ScoreInfo { User = new User { Username = "osu!salad!" } }, Replay = new CatchAutoGenerator(beatmap).Generate(), diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs index 6d4caef8d2..cae19e9468 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs index dcf417c405..178909387f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs index d20a2ec727..a82d0af102 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs index 9cfba0236a..71268d899d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; @@ -20,10 +21,10 @@ namespace osu.Game.Rulesets.Catch.Mods private CatchPlayfield playfield; - public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public override void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - playfield = (CatchPlayfield)rulesetContainer.Playfield; - base.ApplyToRulesetContainer(rulesetContainer); + playfield = (CatchPlayfield)drawableRuleset.Playfield; + base.ApplyToDrawableRuleset(drawableRuleset); } private class CatchFlashlight : Flashlight @@ -55,9 +56,9 @@ namespace osu.Game.Rulesets.Catch.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs index 4e48de454f..ce06b841aa 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs index 8e19c0614a..060e51e31d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects; @@ -15,77 +15,107 @@ namespace osu.Game.Rulesets.Catch.Mods public override double ScoreMultiplier => 1.12; public override bool Ranked => true; - private float lastStartX; - private int lastStartTime; + private float? lastPosition; + private double lastStartTime; public void ApplyToHitObject(HitObject hitObject) { + if (hitObject is JuiceStream stream) + { + lastPosition = stream.EndX; + lastStartTime = stream.EndTime; + return; + } + + if (!(hitObject is Fruit)) + return; + var catchObject = (CatchHitObject)hitObject; float position = catchObject.X; - int startTime = (int)hitObject.StartTime; + double startTime = hitObject.StartTime; - if (lastStartX == 0) + if (lastPosition == null) { - lastStartX = position; + lastPosition = position; lastStartTime = startTime; + return; } - float diff = lastStartX - position; - int timeDiff = startTime - lastStartTime; + float positionDiff = position - lastPosition.Value; + double timeDiff = startTime - lastStartTime; if (timeDiff > 1000) { - lastStartX = position; + lastPosition = position; lastStartTime = startTime; return; } - if (diff == 0) + if (positionDiff == 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; - } - + applyRandomOffset(ref position, timeDiff / 4d); 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; - } - } + if (Math.Abs(positionDiff * CatchPlayfield.BASE_WIDTH) < timeDiff / 3d) + applyOffset(ref position, positionDiff); catchObject.X = position; - lastStartX = position; + lastPosition = position; lastStartTime = startTime; } + + /// + /// Applies a random offset in a random direction to a position, ensuring that the final position remains within the boundary of the playfield. + /// + /// The position which the offset should be applied to. + /// The maximum offset, cannot exceed 20px. + private void applyRandomOffset(ref float position, double maxOffset) + { + bool right = RNG.NextBool(); + float rand = Math.Min(20, (float)RNG.NextDouble(0, Math.Max(0, maxOffset))) / CatchPlayfield.BASE_WIDTH; + + if (right) + { + // Clamp to the right bound + if (position + rand <= 1) + position += rand; + else + position -= rand; + } + else + { + // Clamp to the left bound + if (position - rand >= 0) + position -= rand; + else + position += rand; + } + } + + /// + /// Applies an offset to a position, ensuring that the final position remains within the boundary of the playfield. + /// + /// The position which the offset should be applied to. + /// The amount to offset by. + private void applyOffset(ref float position, float amount) + { + if (amount > 0) + { + // Clamp to the right bound + if (position + amount < 1) + position += amount; + } + else + { + // Clamp to the left bound + if (position + amount > 0) + position += amount; + } + } } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs index f2716f351e..9990b01427 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs index 687db172cf..da2edcee44 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs index 914419438d..3c02646e99 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs index de00ff31ce..fb92399102 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs index 8bf9f32572..0454bc969d 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs index 71461cfc40..68e01391ce 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index e1af4c1075..0b3d1d23e0 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 25af7e4bdf..6d44e4660e 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 0c50dae9fb..2153b8dc85 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs index 1cf2694a90..837662f5fe 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitWindows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs index 8756a5178f..5afdb14888 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Catch.Objects.Drawable { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 697fab85c9..aaf723fae6 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 2db252ebc6..294fd97d59 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable base.SkinChanged(skin, allowFallback); if (HitObject is IHasComboInformation combo) - AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; } private const float preempt = 1000; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index a896d13132..8fed8eb4cd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 4bd50f29f6..fac4b8098c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index e66852c5c2..7bb12453a8 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs index 2f167121aa..d41aea1e7b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs index f21c14f076..2e18c5f2ad 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -23,9 +23,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index 8b54922959..7b0bb3f0ae 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 2c2cd013c3..6f0423b420 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index d8bd3e0edc..2adc156efd 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Audio; @@ -25,6 +24,11 @@ namespace osu.Game.Rulesets.Catch.Objects public double Velocity; public double TickDistance; + /// + /// The length of one span of this . + /// + public double SpanDuration => Duration / this.SpanCount(); + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -41,93 +45,67 @@ namespace osu.Game.Rulesets.Catch.Objects protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); - createTicks(); - } - private void createTicks() - { - if (TickDistance == 0) - return; - - var length = Path.Distance; - var tickDistance = Math.Min(TickDistance, length); - var spanDuration = length / Velocity; - - var minDistanceFromEnd = Velocity * 0.01; - - AddNested(new Fruit + var tickSamples = Samples.Select(s => new SampleInfo { - Samples = Samples, - StartTime = StartTime, - X = X - }); + Bank = s.Bank, + Name = @"slidertick", + Volume = s.Volume + }).ToList(); - double lastDropletTime = StartTime; + SliderEventDescriptor? lastEvent = null; - for (int span = 0; span < this.SpanCount(); span++) + foreach (var e in SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - var spanStartTime = StartTime + span * spanDuration; - var reversed = span % 2 == 1; - - for (double d = 0; d <= length; d += tickDistance) + // generate tiny droplets since the last point + if (lastEvent != null) { - var timeProgress = d / length; - var distanceProgress = reversed ? 1 - timeProgress : timeProgress; + double sinceLastTick = e.Time - lastEvent.Value.Time; - double time = spanStartTime + timeProgress * spanDuration; - - if (LegacyLastTickOffset != null) + if (sinceLastTick > 80) { - // If we're the last tick, apply the legacy offset - if (span == this.SpanCount() - 1 && d + tickDistance > length) - time = Math.Max(StartTime + Duration / 2, time - LegacyLastTickOffset.Value); - } + double timeBetweenTiny = sinceLastTick; + while (timeBetweenTiny > 100) + timeBetweenTiny /= 2; - double tinyTickInterval = time - lastDropletTime; - while (tinyTickInterval > 100) - tinyTickInterval /= 2; - - for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval) - { - double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration; - - AddNested(new TinyDroplet + for (double t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) { - StartTime = t, - X = X + Path.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, - Samples = new List(Samples.Select(s => new SampleInfo + AddNested(new TinyDroplet { - Bank = s.Bank, - Name = @"slidertick", - Volume = s.Volume - })) - }); + Samples = tickSamples, + StartTime = t + lastEvent.Value.Time, + X = X + Path.PositionAt( + lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X / CatchPlayfield.BASE_WIDTH, + }); + } } - - if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd) - { - AddNested(new Droplet - { - StartTime = time, - X = X + Path.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH, - Samples = new List(Samples.Select(s => new SampleInfo - { - Bank = s.Bank, - Name = @"slidertick", - Volume = s.Volume - })) - }); - } - - lastDropletTime = time; } - AddNested(new Fruit + // this also includes LegacyLastTick and this is used for TinyDroplet generation above. + // this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied. + lastEvent = e; + + switch (e.Type) { - Samples = Samples, - StartTime = spanStartTime + spanDuration, - X = X + Path.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH - }); + case SliderEventType.Tick: + AddNested(new Droplet + { + Samples = tickSamples, + StartTime = e.Time, + X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, + }); + break; + case SliderEventType.Head: + case SliderEventType.Tail: + case SliderEventType.Repeat: + AddNested(new Fruit + { + Samples = Samples, + StartTime = e.Time, + X = X + Path.PositionAt(e.PathProgress).X / CatchPlayfield.BASE_WIDTH, + }); + break; + } } } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 39f1cadad5..1bf160b5a6 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs index 045d0824c6..dba76eef49 100644 --- a/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Catch.Tests.iOS")] diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 20bf2ee5c7..daa3f61de3 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -1,22 +1,25 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Replays; +using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Catch.Replays { - internal class CatchAutoGenerator : AutoGenerator + internal class CatchAutoGenerator : AutoGenerator { public const double RELEASE_DELAY = 20; - public CatchAutoGenerator(Beatmap beatmap) + public new CatchBeatmap Beatmap => (CatchBeatmap)base.Beatmap; + + public CatchAutoGenerator(IBeatmap beatmap) : base(beatmap) { Replay = new Replay(); diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index c907fec653..dd0223314d 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Input.StateChanges; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 8c32b75959..1e88b35c3b 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Replays.Legacy; diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/diffcalc-test.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/diffcalc-test.osu new file mode 100644 index 0000000000..ebad654404 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/diffcalc-test.osu @@ -0,0 +1,138 @@ +osu file format v14 + +[General] +StackLeniency: 0.3 +Mode: 2 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +34500,-50,4,2,1,50,0,0 + +[HitObjects] +// fruits spaced 1/1 beat apart +32,128,0,5,0,0:0:0:0: +96,128,500,1,0,0:0:0:0: +160,128,1000,1,0,0:0:0:0: +224,128,1500,1,0,0:0:0:0: +288,128,2000,1,0,0:0:0:0: +352,128,2500,1,0,0:0:0:0: +416,128,3000,1,0,0:0:0:0: +480,128,3500,1,0,0:0:0:0: + +// fruits spaced 1/2 beat apart +32,160,4500,1,0,0:0:0:0: +64,160,4750,1,0,0:0:0:0: +96,160,5000,1,0,0:0:0:0: +128,160,5250,1,0,0:0:0:0: +160,160,5500,1,0,0:0:0:0: +192,160,5750,1,0,0:0:0:0: +224,160,6000,1,0,0:0:0:0: +256,160,6250,1,0,0:0:0:0: +288,160,6500,1,0,0:0:0:0: + +// fruits spaced 1/4 beat apart +96,128,7500,1,0,0:0:0:0: +128,128,7625,1,0,0:0:0:0: +160,128,7750,1,0,0:0:0:0: +192,128,7875,1,0,0:0:0:0: +224,128,8000,1,0,0:0:0:0: +256,128,8125,1,0,0:0:0:0: +288,128,8250,1,0,0:0:0:0: +320,128,8375,1,0,0:0:0:0: +352,128,8500,1,0,0:0:0:0: + +// fruit hyperdashes, spaced 1/2 beat apart +32,160,9500,1,0,0:0:0:0: +480,160,9750,1,0,0:0:0:0: +32,160,10000,1,0,0:0:0:0: +480,160,10250,1,0,0:0:0:0: +32,160,10500,1,0,0:0:0:0: +480,160,10750,1,0,0:0:0:0: +32,160,11000,1,0,0:0:0:0: + +// fruit hyperdashes, spaced 1/4 beat apart +32,192,12000,1,0,0:0:0:0: +480,192,12125,1,0,0:0:0:0: +32,192,12250,1,0,0:0:0:0: +480,192,12375,1,0,0:0:0:0: +32,192,12500,1,0,0:0:0:0: +480,192,12625,1,0,0:0:0:0: +32,192,12750,1,0,0:0:0:0: +480,192,12875,1,0,0:0:0:0: +32,192,13000,1,0,0:0:0:0: + +// stream + hyperdash + stream, spaced 1/4 beat apart +32,192,14000,1,0,0:0:0:0: +64,192,14125,1,0,0:0:0:0: +96,192,14250,1,0,0:0:0:0: +128,192,14375,1,0,0:0:0:0: +480,192,14500,1,0,0:0:0:0: +448,192,14625,1,0,0:0:0:0: +416,192,14750,1,0,0:0:0:0: +384,192,14875,1,0,0:0:0:0: +32,192,15000,1,0,0:0:0:0: + +// basic sliders +32,192,16000,2,0,L|192:192,1,160 +224,192,17000,2,0,L|384:192,1,160 +416,192,17875,2,0,L|480:192,1,40 + +// slider hyperdashes, spaced 1/4 beat apart +32,192,19000,2,0,L|128:192,1,80 +480,192,19375,2,0,L|384:192,1,80 +352,192,19750,2,0,L|256:192,1,80 +0,192,20125,2,0,L|128:192,1,120 + +// stream + slider hyperdashes, spaced 1/4 beat apart +32,192,21500,1,0,0:0:0:0: +64,192,21625,1,0,0:0:0:0: +96,192,21750,1,0,0:0:0:0: +512,192,21875,2,0,L|320:192,1,160 +320,192,22500,1,0,0:0:0:0: +288,192,22625,1,0,0:0:0:0: +256,192,22750,1,0,0:0:0:0: +0,192,22875,2,0,L|64:192,1,40 + +// streams, spaced 1/4 beat apart +64,192,24000,1,0,0:0:0:0: +160,192,24125,1,0,0:0:0:0: +64,192,24250,1,0,0:0:0:0: +160,192,24375,1,0,0:0:0:0: +64,192,24500,1,0,0:0:0:0: +160,192,24625,1,0,0:0:0:0: +64,192,24750,1,0,0:0:0:0: +160,192,24875,1,0,0:0:0:0: +64,192,25000,1,0,0:0:0:0: +160,192,25125,1,0,0:0:0:0: +64,192,25250,1,0,0:0:0:0: +160,192,25375,1,0,0:0:0:0: +64,192,25500,1,0,0:0:0:0: + +// stream + spinner combo, spaced 1/4 beat apart +256,192,26500,12,0,27000,0:0:0:0: +128,192,27250,5,0,0:0:0:0: +128,192,27375,1,0,0:0:0:0: +160,192,27500,1,0,0:0:0:0: +192,192,27625,1,0,0:0:0:0: +256,192,27750,12,0,28500,0:0:0:0: +192,192,28625,5,0,0:0:0:0: +224,192,28750,1,0,0:0:0:0: +256,192,28875,1,0,0:0:0:0: +256,192,29000,1,0,0:0:0:0: +256,192,29125,12,0,29500,0:0:0:0: + +// long slow slider +0,192,30500,6,0,B|480:192|480:192|0:192,2,960 + +// long fast slider +0,192,37500,6,0,B|480:192|480:192|0:192,2,960 + +// long hyperdash slider +0,192,41500,2,0,P|544:192|544:192,5,480 diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider-expected-conversion.json b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider-expected-conversion.json new file mode 100644 index 0000000000..58c52b6867 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider-expected-conversion.json @@ -0,0 +1 @@ +{"Mappings":[{"StartTime":19184.0,"Objects":[{"StartTime":19184.0,"Position":320.0},{"StartTime":19263.0,"Position":311.730255},{"StartTime":19343.0,"Position":324.6205},{"StartTime":19423.0,"Position":343.0907},{"StartTime":19503.0,"Position":372.2917},{"StartTime":19582.0,"Position":385.194733},{"StartTime":19662.0,"Position":379.0426},{"StartTime":19742.0,"Position":385.1066},{"StartTime":19822.0,"Position":391.624664},{"StartTime":19919.0,"Position":386.27832},{"StartTime":20016.0,"Position":380.117035},{"StartTime":20113.0,"Position":381.664154},{"StartTime":20247.0,"Position":370.872864}]}]} \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider.osu b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider.osu new file mode 100644 index 0000000000..d48b2d7769 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Resources/Testing/Beatmaps/slider.osu @@ -0,0 +1,18 @@ +osu file format v14 + +[General] +Mode: 2 + +[Difficulty] +HPDrainRate:3 +CircleSize:2 +OverallDifficulty:4 +ApproachRate:4 +SliderMultiplier:0.9 +SliderTickRate:1 + +[TimingPoints] +35.4473684210527,638.298947368422,4,2,1,60,1,0 + +[HitObjects] +320,176,19184,2,8,P|384:168|368:232,1,150 diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 57f4355d6a..af614f95d0 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; @@ -13,8 +13,8 @@ namespace osu.Game.Rulesets.Catch.Scoring { public class CatchScoreProcessor : ScoreProcessor { - public CatchScoreProcessor(RulesetContainer rulesetContainer) - : base(rulesetContainer) + public CatchScoreProcessor(DrawableRuleset drawableRuleset) + : base(drawableRuleset) { } @@ -43,6 +43,6 @@ namespace osu.Game.Rulesets.Catch.Scoring Health.Value += Math.Max(result.Judgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; } - protected override HitWindows CreateHitWindows() => new CatchHitWindows(); + public override HitWindows CreateHitWindows() => new CatchHitWindows(); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 0697a72325..4dae95b53c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 3637fe0c36..c6dd0a86a0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatcherArea : Container { - public const float CATCHER_SIZE = 100; + public const float CATCHER_SIZE = 106.75f; protected internal readonly Catcher MovableCatcher; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.UI public Container ExplodingFruitTarget { - set { MovableCatcher.ExplodingFruitTarget = value; } + set => MovableCatcher.ExplodingFruitTarget = value; } public CatcherArea(BeatmapDifficulty difficulty = null) @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Catch.UI if (lastPlateableFruit.IsLoaded) action(); else - lastPlateableFruit.OnLoadComplete = _ => action(); + lastPlateableFruit.OnLoadComplete += _ => action(); } if (result.IsHit && fruit.CanBePlated) @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets.Catch.UI protected bool Dashing { - get { return dashing; } + get => dashing; set { if (value == dashing) return; @@ -176,7 +176,7 @@ namespace osu.Game.Rulesets.Catch.UI /// protected bool Trail { - get { return trail; } + get => trail; set { if (value == trail) return; diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs similarity index 82% rename from osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs rename to osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs index 3673657cd8..406dc10eea 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input; using osu.Game.Beatmaps; @@ -17,13 +17,13 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { - public class CatchRulesetContainer : ScrollingRulesetContainer + public class DrawableCatchRuleset : DrawableScrollingRuleset { protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Constant; protected override bool UserScrollSpeedAdjustment => false; - public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { Direction.Value = ScrollingDirection.Down; @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); - public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); public override DrawableHitObject GetVisualRepresentation(CatchHitObject h) { diff --git a/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs index fa1a7ee868..76daee2bbf 100644 --- a/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/PlayfieldAdjustmentContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs new file mode 100644 index 0000000000..9cd1e47023 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.iOS/AppDelegate.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; +using osu.Game.Tests; + +namespace osu.Game.Rulesets.Mania.Tests.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs new file mode 100644 index 0000000000..d47ac4643f --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.Game.Rulesets.Mania.Tests.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Entitlements.plist b/osu.Game.Rulesets.Mania.Tests.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist new file mode 100644 index 0000000000..8780204d5b --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleName + osu.Game.Rulesets.Mania.Tests.iOS + CFBundleIdentifier + ppy.osu-Game-Rulesets-Mania-Tests-iOS + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj new file mode 100644 index 0000000000..24abccb19d --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj @@ -0,0 +1,45 @@ + + + + + Debug + iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C} + Exe + osu.Game.Rulesets.Mania.Tests + osu.Game.Rulesets.Mania.Tests.iOS + + + + + + + libbass.a + PreserveNewest + + + libbass_fx.a + PreserveNewest + + + Linker.xml + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {48F4582B-7687-4621-9CBE-5C24197CB536} + osu.Game.Rulesets.Mania + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs index 58f2ab7747..6b95975059 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -40,29 +40,29 @@ namespace osu.Game.Rulesets.Mania.Tests protected override Ruleset CreateRuleset() => new ManiaRuleset(); } - public class ManiaConvertMapping : ConvertMapping, IEquatable - { - public uint RandomW; - public uint RandomX; - public uint RandomY; - public uint RandomZ; + public class ManiaConvertMapping : ConvertMapping, IEquatable + { + public uint RandomW; + public uint RandomX; + public uint RandomY; + public uint RandomZ; - public ManiaConvertMapping() - { - } + public ManiaConvertMapping() + { + } - public ManiaConvertMapping(IBeatmapConverter converter) - { - var maniaConverter = (ManiaBeatmapConverter)converter; - RandomW = maniaConverter.Random.W; - RandomX = maniaConverter.Random.X; - RandomY = maniaConverter.Random.Y; - RandomZ = maniaConverter.Random.Z; - } + public ManiaConvertMapping(IBeatmapConverter converter) + { + var maniaConverter = (ManiaBeatmapConverter)converter; + RandomW = maniaConverter.Random.W; + RandomX = maniaConverter.Random.X; + RandomY = maniaConverter.Random.Y; + RandomZ = maniaConverter.Random.Z; + } - public bool Equals(ManiaConvertMapping other) => other != null && RandomW == other.RandomW && RandomX == other.RandomX && RandomY == other.RandomY && RandomZ == other.RandomZ; - public override bool Equals(ConvertMapping other) => base.Equals(other) && Equals(other as ManiaConvertMapping); - } + public bool Equals(ManiaConvertMapping other) => other != null && RandomW == other.RandomW && RandomX == other.RandomX && RandomY == other.RandomY && RandomZ == other.RandomZ; + public override bool Equals(ConvertMapping other) => base.Equals(other) && Equals(other as ManiaConvertMapping); + } public struct ConvertValue : IEquatable { diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs new file mode 100644 index 0000000000..2c36e81190 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mania.Difficulty; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class ManiaDifficultyCalculatorTest : DifficultyCalculatorTest + { + protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; + + [TestCase(2.3683365342338796d, "diffcalc-test")] + public void Test(double expected, string name) + => base.Test(expected, name); + + protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(new ManiaRuleset(), beatmap); + + protected override Ruleset CreateRuleset() => new ManiaRuleset(); + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs index 75c8fc7e79..f281883e0c 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaInputTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs index fb8c740d16..13bbe87513 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs index 50de5ce7a3..a22e599681 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs index bab3a4db32..e8a056bbff 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseAutoGeneration.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index eecc578861..b14f999f61 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs index 6c0f931cda..e721eb6fd9 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; @@ -25,8 +25,8 @@ namespace osu.Game.Rulesets.Mania.Tests [BackgroundDependencyLoader] private void load(RulesetConfigCache configCache) { - var config = (ManiaConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); - config.BindWith(ManiaSetting.ScrollDirection, direction); + var config = (ManiaRulesetConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaRulesetSetting.ScrollDirection, direction); } } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs index ea7433268d..411412e127 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs index 756031a463..ae614ae4b8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNoteSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs index 9ae49d200e..12cbeb81f3 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs index 4023f97eb3..99fe464cfd 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNoteSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 6344aee6bd..0bc2c3ea28 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -141,7 +142,7 @@ namespace osu.Game.Rulesets.Mania.Tests { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = description } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index 7acc37cb67..ac430037e4 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 0c6fbfa7d3..fd17285a38 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,9 +2,9 @@ - + - + diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs index ad5f8e447d..77a10131a6 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 2770a6ff5b..71df68c087 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mania.Objects; using System; @@ -27,6 +27,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; public int TargetColumns; + public bool Dual; public readonly bool IsForCurrentRuleset; // Internal for testing purposes @@ -45,7 +46,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); if (IsForCurrentRuleset) + { TargetColumns = (int)Math.Max(1, roundedCircleSize); + if (TargetColumns >= 10) + { + TargetColumns = TargetColumns / 2; + Dual = true; + } + } else { float percentSliderOrSpinner = (float)beatmap.HitObjects.Count(h => h is IHasEndTime) / beatmap.HitObjects.Count; @@ -70,14 +78,22 @@ namespace osu.Game.Rulesets.Mania.Beatmaps return base.ConvertBeatmap(original); } - protected override Beatmap CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }); + protected override Beatmap CreateBeatmap() + { + beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }); + + if (Dual) + beatmap.Stages.Add(new StageDefinition { Columns = TargetColumns }); + + return beatmap; + } protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap) { - var maniaOriginal = original as ManiaHitObject; - if (maniaOriginal != null) + if (original is ManiaHitObject maniaOriginal) { yield return maniaOriginal; + yield break; } @@ -92,6 +108,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private readonly List prevNoteTimes = new List(max_notes_for_density); private double density = int.MaxValue; + private void computeDensity(double newNoteTime) { if (prevNoteTimes.Count == max_notes_for_density) @@ -104,6 +121,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private double lastTime; private Vector2 lastPosition; private PatternType lastStair = PatternType.Stair; + private void recordNote(double time, Vector2 position) { lastTime = time; @@ -180,7 +198,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps foreach (var obj in newPattern.HitObjects) yield return obj; - } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 635004d2f6..ed52bdd23f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -65,6 +65,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (originalPattern.HitObjects.Count() == 1) { yield return originalPattern; + yield break; } @@ -135,6 +136,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.78, 0.3, 0); + return generateNRandomNotes(HitObject.StartTime, 0.85, 0.36, 0.03); } @@ -142,6 +144,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.43, 0.08, 0); + return generateNRandomNotes(HitObject.StartTime, 0.56, 0.18, 0); } @@ -149,11 +152,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.3, 0, 0); + return generateNRandomNotes(HitObject.StartTime, 0.37, 0.08, 0); } if (convertType.HasFlag(PatternType.LowProbability)) return generateNRandomNotes(HitObject.StartTime, 0.17, 0, 0); + return generateNRandomNotes(HitObject.StartTime, 0.27, 0, 0); } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 775a4145e6..0bf6c055ac 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Rulesets.Mania.MathUtils; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 8463e209e4..34f5f5c415 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -116,10 +116,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } if (convertType.HasFlag(PatternType.Cycle) && PreviousPattern.HitObjects.Count() == 1 - // If we convert to 7K + 1, let's not overload the special key - && (TotalColumns != 8 || lastColumn != 0) - // Make sure the last column was not the centre column - && (TotalColumns % 2 == 0 || lastColumn != TotalColumns / 2)) + // If we convert to 7K + 1, let's not overload the special key + && (TotalColumns != 8 || lastColumn != 0) + // Make sure the last column was not the centre column + && (TotalColumns % 2 == 0 || lastColumn != TotalColumns / 2)) { // Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object) int column = RandomStart + TotalColumns - lastColumn - 1; @@ -172,6 +172,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return pattern = generateRandomPatternWithMirrored(0.12, 0.38, 0.12); if (ConversionDifficulty > 4) return pattern = generateRandomPatternWithMirrored(0.12, 0.17, 0); + return pattern = generateRandomPatternWithMirrored(0.12, 0, 0); } @@ -179,6 +180,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.78, 0.42, 0, 0); + return pattern = generateRandomPattern(1, 0.62, 0, 0); } @@ -186,6 +188,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.35, 0.08, 0, 0); + return pattern = generateRandomPattern(0.52, 0.15, 0, 0); } @@ -193,6 +196,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { if (convertType.HasFlag(PatternType.LowProbability)) return pattern = generateRandomPattern(0.18, 0, 0, 0); + return pattern = generateRandomPattern(0.45, 0, 0, 0); } @@ -250,6 +254,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else last = GetRandomColumn(); + return last; } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index f412e127c5..b702291c5d 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -87,6 +87,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return 4; if (val >= 1 - p3) return 3; + return val >= 1 - p2 ? 2 : 1; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs index 2eba2d5843..a3cd455886 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; @@ -12,51 +12,63 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy internal enum PatternType { None = 0, + /// /// Keep the same as last row. /// ForceStack = 1 << 0, + /// /// Keep different from last row. /// ForceNotStack = 1 << 1, + /// /// Keep as single note at its original position. /// KeepSingle = 1 << 2, + /// /// Use a lower random value. /// LowProbability = 1 << 3, + /// /// Reserved. /// Alternate = 1 << 4, + /// /// Ignore the repeat count. /// ForceSigSlider = 1 << 5, + /// /// Convert slider to circle. /// ForceNotSlider = 1 << 6, + /// /// Notes gathered together. /// Gathered = 1 << 7, Mirror = 1 << 8, + /// /// Change 0 -> 6. /// Reverse = 1 << 9, + /// /// 1 -> 5 -> 1 -> 5 like reverse. /// Cycle = 1 << 10, + /// /// Next note will be at column + 1. /// Stair = 1 << 11, + /// /// Next note will be at column - 1. /// diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs index 32d2d096b2..f095a0ffce 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index a42d57cdd1..71b3f6ecf2 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs index afec607a7c..dff7cb72ce 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs deleted file mode 100644 index 1c9e1e4c73..0000000000 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration.Tracking; -using osu.Game.Configuration; -using osu.Game.Rulesets.Configuration; -using osu.Game.Rulesets.Mania.UI; - -namespace osu.Game.Rulesets.Mania.Configuration -{ - public class ManiaConfigManager : RulesetConfigManager - { - public ManiaConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) - { - } - - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); - - Set(ManiaSetting.ScrollTime, 2250.0, 50.0, 10000.0, 50.0); - Set(ManiaSetting.ScrollDirection, ManiaScrollingDirection.Down); - } - - public override TrackedSettings CreateTrackedSettings() => new TrackedSettings - { - new TrackedSetting(ManiaSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms")) - }; - } - - public enum ManiaSetting - { - ScrollTime, - ScrollDirection - } -} diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs new file mode 100644 index 0000000000..b591f9da22 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Configuration.Tracking; +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Configuration +{ + public class ManiaRulesetConfigManager : RulesetConfigManager + { + public ManiaRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) + { + } + + protected override void InitialiseDefaults() + { + base.InitialiseDefaults(); + + Set(ManiaRulesetSetting.ScrollTime, 2250.0, 50.0, 10000.0, 50.0); + Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); + } + + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + { + new TrackedSetting(ManiaRulesetSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms")) + }; + } + + public enum ManiaRulesetSetting + { + ScrollTime, + ScrollDirection + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs index c7f6890b93..3ff665d2c8 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -1,18 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaDifficultyAttributes : DifficultyAttributes { public double GreatHitWindow; - - public ManiaDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 7b4d4b12ed..59fed1031f 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -1,34 +1,24 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.Mods; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty { - internal class ManiaDifficultyCalculator : DifficultyCalculator + public class ManiaDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.018; - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size strain_step. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 400; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.9; - private readonly bool isForCurrentRuleset; public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) @@ -37,109 +27,70 @@ namespace osu.Game.Rulesets.Mania.Difficulty isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new ManiaDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new ManiaDifficultyAttributes { Mods = mods }; - var difficultyHitObjects = new List(); - - int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; - - // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. - // Note: Stable sort is done so that the ordering of hitobjects with equal start times doesn't change - difficultyHitObjects.AddRange(beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new DifficultyAttributes(mods, 0); - - - double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - - return new ManiaDifficultyAttributes(mods, starRating) + return new ManiaDifficultyAttributes { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate + StarRating = difficultyValue(skills) * star_scaling_factor, + Mods = mods, + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, }; } - private bool calculateStrainValues(List objects, double timeRate) + private double difficultyValue(Skill[] skills) { - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (var hitObjectsEnumerator = objects.GetEnumerator()) + // Preprocess the strains to find the maximum overall + individual (aggregate) strain from each section + var overall = skills.OfType().Single(); + var aggregatePeaks = new List(Enumerable.Repeat(0.0, overall.StrainPeaks.Count)); + + foreach (var individual in skills.OfType()) { - if (!hitObjectsEnumerator.MoveNext()) - return false; - - ManiaHitObjectDifficulty current = hitObjectsEnumerator.Current; - - // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. - while (hitObjectsEnumerator.MoveNext()) + for (int i = 0; i < individual.StrainPeaks.Count; i++) { - var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, timeRate); - current = next; + double aggregate = individual.StrainPeaks[i] + overall.StrainPeaks[i]; + + if (aggregate > aggregatePeaks[i]) + aggregatePeaks[i] = aggregate; } - - return true; - } - } - - private double calculateDifficulty(List objects, double timeRate) - { - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - List highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - ManiaHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double individualDecay = Math.Pow(ManiaHitObjectDifficulty.INDIVIDUAL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - double overallDecay = Math.Pow(ManiaHitObjectDifficulty.OVERALL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.IndividualStrain * individualDecay + previousHitObject.OverallStrain * overallDecay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - double strain = hitObject.IndividualStrain + hitObject.OverallStrain; - maximumStrain = Math.Max(strain, maximumStrain); - - previousHitObject = hitObject; } - // Build the weighted sum over the highest strains for each interval + aggregatePeaks.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. + double difficulty = 0; double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - foreach (double strain in highestStrains) + // Difficulty is the weighted sum of the highest strains from every section. + foreach (double strain in aggregatePeaks) { - difficulty += weight * strain; - weight *= decay_weight; + difficulty += strain * weight; + weight *= 0.9; } return difficulty; } + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + for (int i = 1; i < beatmap.HitObjects.Count; i++) + yield return new ManiaDifficultyHitObject(beatmap.HitObjects[i], beatmap.HitObjects[i - 1], clockRate); + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) + { + int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; + + var skills = new List { new Overall(columnCount) }; + + for (int i = 0; i < columnCount; i++) + skills.Add(new Individual(i, columnCount)); + + return skills.ToArray(); + } + protected override Mod[] DifficultyAdjustmentMods { get diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 610c7a8fee..b99bddee96 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -114,8 +114,8 @@ namespace osu.Game.Rulesets.Mania.Difficulty // Lots of arbitrary values from testing. // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution double accuracyValue = Math.Max(0.0, 0.2 - (Attributes.GreatHitWindow - 34) * 0.006667) - * strainValue - * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); + * strainValue + * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); // Bonus for many hitcircles - it's harder to keep good accuracy up for longer // accuracyValue *= Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); diff --git a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs new file mode 100644 index 0000000000..29ba934e9f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Preprocessing +{ + public class ManiaDifficultyHitObject : DifficultyHitObject + { + public new ManiaHitObject BaseObject => (ManiaHitObject)base.BaseObject; + + public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs new file mode 100644 index 0000000000..059cd39641 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs @@ -0,0 +1,47 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Skills +{ + public class Individual : Skill + { + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.125; + + private readonly double[] holdEndTimes; + + private readonly int column; + + public Individual(int column, int columnCount) + { + this.column = column; + + holdEndTimes = new double[columnCount]; + } + + protected override double StrainValueOf(DifficultyHitObject current) + { + var maniaCurrent = (ManiaDifficultyHitObject)current; + var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + + try + { + if (maniaCurrent.BaseObject.Column != column) + return 0; + + // We give a slight bonus if something is held meanwhile + return holdEndTimes.Any(t => t > endTime) ? 2.5 : 2; + } + finally + { + holdEndTimes[maniaCurrent.BaseObject.Column] = endTime; + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs new file mode 100644 index 0000000000..ed25173d38 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Skills +{ + public class Overall : Skill + { + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.3; + + private readonly double[] holdEndTimes; + + private readonly int columnCount; + + public Overall(int columnCount) + { + this.columnCount = columnCount; + + holdEndTimes = new double[columnCount]; + } + + protected override double StrainValueOf(DifficultyHitObject current) + { + var maniaCurrent = (ManiaDifficultyHitObject)current; + var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + + double holdFactor = 1.0; // Factor in case something else is held + double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly + + for (int i = 0; i < columnCount; i++) + { + // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... + if (current.BaseObject.StartTime < holdEndTimes[i] && endTime > holdEndTimes[i]) + holdAddition = 1.0; + + // ... this addition only is valid if there is _no_ other note with the same ending. + // Releasing multiple notes at the same time is just as easy as releasing one + if (endTime == holdEndTimes[i]) + holdAddition = 0; + + // We give a slight bonus if something is held meanwhile + if (holdEndTimes[i] > endTime) + holdFactor = 1.25; + } + + holdEndTimes[maniaCurrent.BaseObject.Column] = endTime; + + return (1 + holdAddition) * holdFactor; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index 41b2e950f9..b99a1157f3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs index 424ff1118c..6f85fd9167 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditNotePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 081bdffc27..26115311f7 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 4b78dd68cb..d64c5dbc6a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index d76d20f2b8..d3779e2e18 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index f190843f5d..d3c12b1944 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index acb43e38ba..32c6a6fd07 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs index 440a539412..d345b14e84 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NoteSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs similarity index 65% rename from osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs rename to osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs index f605ad0a22..acafaffee6 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/DrawableManiaEditRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osuTK; @@ -10,11 +10,11 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaEditRulesetContainer : ManiaRulesetContainer + public class DrawableManiaEditRuleset : DrawableManiaRuleset { public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - public ManiaEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs index b1872c200f..295bf417c4 100644 --- a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index d9de400ac5..f64bab1fae 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mania.UI; using osuTK; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs index e7bc526471..a42f793a77 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index d73ce3966f..56c9471462 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Edit [Cached(Type = typeof(IManiaHitObjectComposer))] public class ManiaHitObjectComposer : HitObjectComposer, IManiaHitObjectComposer { - protected new ManiaEditRulesetContainer RulesetContainer { get; private set; } + protected new DrawableManiaEditRuleset DrawableRuleset { get; private set; } public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) @@ -32,23 +32,23 @@ namespace osu.Game.Rulesets.Mania.Edit /// /// The screen-space position. /// The column which intersects with . - public Column ColumnAt(Vector2 screenSpacePosition) => RulesetContainer.GetColumnByPosition(screenSpacePosition); + public Column ColumnAt(Vector2 screenSpacePosition) => DrawableRuleset.GetColumnByPosition(screenSpacePosition); private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - public int TotalColumns => ((ManiaPlayfield)RulesetContainer.Playfield).TotalColumns; + public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; - protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap) { - RulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); + DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap); // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it - dependencies.CacheAs(RulesetContainer.ScrollingInfo); + dependencies.CacheAs(DrawableRuleset.ScrollingInfo); - return RulesetContainer; + return DrawableRuleset; } protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 828f6d87bc..6f49c7f0c4 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs index 81a2728ad4..30b0f09a94 100644 --- a/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Masks/ManiaSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Rulesets.Edit; diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs index 93f49d1cc0..50b5f9a8fe 100644 --- a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs index 9055e48a4c..e8b48768a1 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 6eb5a79200..015eb1310e 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 4e0649c708..b6fb37f054 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index 61356d96dc..292990fd7e 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Framework.Input.Bindings; @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Mania { [Description("Special 1")] Special1 = 1, + [Description("Special 2")] Special2, @@ -26,38 +27,55 @@ namespace osu.Game.Rulesets.Mania // above at a later time, without breaking replays/configs. [Description("Key 1")] Key1 = 10, + [Description("Key 2")] Key2, + [Description("Key 3")] Key3, + [Description("Key 4")] Key4, + [Description("Key 5")] Key5, + [Description("Key 6")] Key6, + [Description("Key 7")] Key7, + [Description("Key 8")] Key8, + [Description("Key 9")] Key9, + [Description("Key 10")] Key10, + [Description("Key 11")] Key11, + [Description("Key 12")] Key12, + [Description("Key 13")] Key13, + [Description("Key 14")] Key14, + [Description("Key 15")] Key15, + [Description("Key 16")] Key16, + [Description("Key 17")] Key17, + [Description("Key 18")] Key18, } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 392d10b414..a4a10f1742 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; @@ -12,6 +12,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; @@ -30,7 +31,7 @@ namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableManiaRuleset(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); @@ -145,6 +146,11 @@ namespace osu.Game.Rulesets.Mania { new MultiMod(new ManiaModAutoplay(), new ModCinema()), }; + case ModType.Fun: + return new Mod[] + { + new MultiMod(new ModWindUp(), new ModWindDown()) + }; default: return new Mod[] { }; } @@ -162,7 +168,7 @@ namespace osu.Game.Rulesets.Mania public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new ManiaReplayFrame(); - public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaConfigManager(settings, RulesetInfo); + public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new ManiaRulesetConfigManager(settings, RulesetInfo); public override RulesetSettingsSubsection CreateSettings() => new ManiaSettingsSubsection(this); @@ -330,12 +336,12 @@ namespace osu.Game.Rulesets.Mania for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++) bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++)); - for (int i = 0; i < columns / 2; i++) - bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); - if (columns % 2 == 1) bindings.Add(new KeyBinding(SpecialKey, SpecialAction)); + for (int i = 0; i < columns / 2; i++) + bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); + nextNormalAction = currentNormalAction; return bindings; } @@ -349,6 +355,7 @@ namespace osu.Game.Rulesets.Mania /// Number of columns in this stage lies at (item - Single). /// Single = 0, + /// /// Columns are grouped into two stages. /// Overall number of columns lies at (item - Dual), further computation is required for diff --git a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs index 783142fadc..2ebfd0cfc1 100644 --- a/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs +++ b/osu.Game.Rulesets.Mania/ManiaSettingsSubsection.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; @@ -21,14 +22,26 @@ namespace osu.Game.Rulesets.Mania [BackgroundDependencyLoader] private void load() { + var config = (ManiaRulesetConfigManager)Config; + Children = new Drawable[] { new SettingsEnumDropdown { LabelText = "Scrolling direction", - Bindable = ((ManiaConfigManager)Config).GetBindable(ManiaSetting.ScrollDirection) - } + Bindable = config.GetBindable(ManiaRulesetSetting.ScrollDirection) + }, + new SettingsSlider + { + LabelText = "Scroll speed", + Bindable = config.GetBindable(ManiaRulesetSetting.ScrollTime) + }, }; } + + private class TimeSlider : OsuSliderBar + { + public override string TooltipText => Current.Value.ToString("N0") + "ms"; + } } } diff --git a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs index 785cd5ab06..a9cd7f2476 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; @@ -37,11 +37,11 @@ namespace osu.Game.Rulesets.Mania.MathUtils /// The random value. public uint NextUInt() { - uint t = X ^ X << 11; + uint t = X ^ (X << 11); X = Y; Y = Z; Z = W; - return W = W ^ W >> 19 ^ t ^ t >> 8; + return W = W ^ (W >> 19) ^ t ^ (t >> 8); } /// diff --git a/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs index e08c9aa2a8..410386c9d5 100644 --- a/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index d4164ec1f6..13fdd74113 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index f53943ec85..c05e979e9a 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) => new Score + public override Score CreateReplayScore(IBeatmap beatmap) => new Score { ScoreInfo = new ScoreInfo { User = new User { Username = "osu!topus!" } }, Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs index 506879bb96..bec0a6a1d3 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs index bd93f0db38..a302f95966 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs index 5a8ce05873..c78bf72979 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -1,15 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToBeatmap + public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter { public override string Name => "Dual Stages"; public override string Acronym => "DS"; @@ -29,24 +27,7 @@ namespace osu.Game.Rulesets.Mania.Mods if (isForCurrentRuleset) return; - mbc.TargetColumns *= 2; - } - - public void ApplyToBeatmap(Beatmap beatmap) - { - if (isForCurrentRuleset) - return; - - var maniaBeatmap = (ManiaBeatmap)beatmap; - - var newDefinitions = new List(); - foreach (var existing in maniaBeatmap.Stages) - { - newDefinitions.Add(new StageDefinition { Columns = existing.Columns / 2 }); - newDefinitions.Add(new StageDefinition { Columns = existing.Columns / 2 }); - } - - maniaBeatmap.Stages = newDefinitions; + mbc.Dual = true; } public PlayfieldType PlayfieldType => PlayfieldType.Dual; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs index 8c85846ed1..ff77df0ae0 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs index 229170cea8..269e318a73 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs index cd84483eb9..6893e1e73b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects; @@ -51,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Mods } } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs index 978554362d..014954dd60 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs index 7b766cab85..d9de06a811 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs index 9bc2502a8f..66b90984b4 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Rulesets.Mania.Objects; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs index 11143f715e..948979505c 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs index 0169d4ecac..de91902ca8 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs index 12e84eda0f..8575a96bde 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs index ab5ed91d9d..54ea3afa07 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs index be9f0f8066..e9a9bba5bd 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs index 571e533078..b9606d1cb5 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs index 89c6bd997d..b80d794085 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs index 8d043651d3..3462d634a4 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs index 20471ebffc..83c505c048 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Mods { diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs index 68325b40bf..17f4098420 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModMirror.cs @@ -1,16 +1,16 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModMirror : Mod, IApplicableToRulesetContainer + public class ManiaModMirror : Mod, IApplicableToBeatmap { public override string Name => "Mirror"; public override string Acronym => "MR"; @@ -18,11 +18,11 @@ namespace osu.Game.Rulesets.Mania.Mods public override double ScoreMultiplier => 1; public override bool Ranked => true; - public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public void ApplyToBeatmap(Beatmap beatmap) { - var availableColumns = ((ManiaRulesetContainer)rulesetContainer).Beatmap.TotalColumns; + var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; - rulesetContainer.Objects.OfType().ForEach(h => h.Column = availableColumns - 1 - h.Column); + beatmap.HitObjects.OfType().ForEach(h => h.Column = availableColumns - 1 - h.Column); } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs index b3e73be4ee..2d94fb6af5 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs index c22549bfc7..e8988be548 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs index abada804fb..2e22e23dbd 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs index b3a3d4280b..5d5023abae 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -1,18 +1,18 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.MathUtils; +using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.Mods { - public class ManiaModRandom : Mod, IApplicableToRulesetContainer + public class ManiaModRandom : Mod, IApplicableToBeatmap { public override string Name => "Random"; public override string Acronym => "RD"; @@ -21,12 +21,12 @@ namespace osu.Game.Rulesets.Mania.Mods public override string Description => @"Shuffle around the keys!"; public override double ScoreMultiplier => 1; - public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public void ApplyToBeatmap(Beatmap beatmap) { - var availableColumns = ((ManiaRulesetContainer)rulesetContainer).Beatmap.TotalColumns; + var availableColumns = ((ManiaBeatmap)beatmap).TotalColumns; var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList(); - rulesetContainer.Objects.OfType().ForEach(h => h.Column = shuffledColumns[h.Column]); + beatmap.HitObjects.OfType().ForEach(h => h.Column = shuffledColumns[h.Column]); } } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs index 05843b3af8..ecc343ecaa 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 0ceb10cc89..4c644a8f09 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index cf718ebdb0..9c3197504f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 5fcc71a039..4bfd940aa0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -75,16 +76,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(Tail); } - protected override void OnDirectionChanged(ScrollingDirection direction) + protected override void OnDirectionChanged(ValueChangedEvent e) { - base.OnDirectionChanged(direction); + base.OnDirectionChanged(e); - bodyPiece.Anchor = bodyPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 3e014ec35c..43aac7907f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 70ff7b4124..a78524011f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -41,9 +41,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override bool ShouldBeAlive => AlwaysAlive || base.ShouldBeAlive; - protected virtual void OnDirectionChanged(ScrollingDirection direction) + protected virtual void OnDirectionChanged(ValueChangedEvent e) { - Anchor = Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 423712b026..7ef90cdb9c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osuTK.Graphics; using osu.Framework.Graphics; @@ -31,16 +32,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables InternalChild = headPiece = new NotePiece(); } - protected override void OnDirectionChanged(ScrollingDirection direction) + protected override void OnDirectionChanged(ValueChangedEvent e) { - base.OnDirectionChanged(direction); + base.OnDirectionChanged(e); - headPiece.Anchor = headPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + headPiece.Anchor = headPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 8dbf33c183..2baf1ad520 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Caching; @@ -77,11 +77,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { if (accentColour == value) return; + accentColour = value; updateAccentColour(); @@ -90,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public bool Hitting { - get { return hitting; } + get => hitting; set { hitting = value; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs index 3a524bfc90..b146a33fd3 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -35,13 +35,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { if (accentColour == value) return; + accentColour = value; updateGlow(); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs index 8325cb8ac0..9e0307c5c2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; @@ -78,8 +78,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces public Color4 AccentColour { - get { return Colour; } - set { Colour = value; } + get => Colour; + set => Colour = value; } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 26d5a7f188..bb33693783 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -49,20 +49,22 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces private void load(IScrollingInfo scrollingInfo) { direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - colouredBox.Anchor = colouredBox.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Anchor = colouredBox.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; }, true); } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { if (accentColour == value) return; + accentColour = value; colouredBox.Colour = AccentColour.Lighten(0.9f); diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 77562bb4c2..5e9f46d9c7 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -17,9 +17,10 @@ namespace osu.Game.Rulesets.Mania.Objects public double EndTime => StartTime + Duration; private double duration; + public double Duration { - get { return duration; } + get => duration; set { duration = value; @@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Objects public override double StartTime { - get { return base.StartTime; } + get => base.StartTime; set { base.StartTime = value; @@ -40,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects public override int Column { - get { return base.Column; } + get => base.Column; set { base.Column = value; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 05959a31c0..c133ee73b1 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index bb3d060e61..70720a926b 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects public virtual int Column { - get => ColumnBindable; + get => ColumnBindable.Value; set => ColumnBindable.Value = value; } diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs deleted file mode 100644 index 390d2b0218..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Objects.Types; -using System; - -namespace osu.Game.Rulesets.Mania.Objects -{ - internal class ManiaHitObjectDifficulty - { - /// - /// Factor by how much individual / overall strain decays per second. - /// - /// - /// These values are results of tweaking a lot and taking into account general feedback. - /// - internal const double INDIVIDUAL_DECAY_BASE = 0.125; - internal const double OVERALL_DECAY_BASE = 0.30; - - internal ManiaHitObject BaseHitObject; - - private readonly int beatmapColumnCount; - - - private readonly double endTime; - private readonly double[] heldUntil; - - /// - /// Measures jacks or more generally: repeated presses of the same button - /// - private readonly double[] individualStrains; - - internal double IndividualStrain - { - get - { - return individualStrains[BaseHitObject.Column]; - } - - set - { - individualStrains[BaseHitObject.Column] = value; - } - } - - /// - /// Measures note density in a way - /// - internal double OverallStrain = 1; - - public ManiaHitObjectDifficulty(ManiaHitObject baseHitObject, int columnCount) - { - BaseHitObject = baseHitObject; - - endTime = (baseHitObject as IHasEndTime)?.EndTime ?? baseHitObject.StartTime; - - beatmapColumnCount = columnCount; - heldUntil = new double[beatmapColumnCount]; - individualStrains = new double[beatmapColumnCount]; - - for (int i = 0; i < beatmapColumnCount; ++i) - { - individualStrains[i] = 0; - heldUntil[i] = 0; - } - } - - internal void CalculateStrains(ManiaHitObjectDifficulty previousHitObject, double timeRate) - { - // TODO: Factor in holds - double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double individualDecay = Math.Pow(INDIVIDUAL_DECAY_BASE, timeElapsed / 1000); - double overallDecay = Math.Pow(OVERALL_DECAY_BASE, timeElapsed / 1000); - - double holdFactor = 1.0; // Factor to all additional strains in case something else is held - double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly - - // Fill up the heldUntil array - for (int i = 0; i < beatmapColumnCount; ++i) - { - heldUntil[i] = previousHitObject.heldUntil[i]; - - // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... - if (BaseHitObject.StartTime < heldUntil[i] && endTime > heldUntil[i]) - { - holdAddition = 1.0; - } - - // ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1 - if (endTime == heldUntil[i]) - { - holdAddition = 0; - } - - // We give a slight bonus to everything if something is held meanwhile - if (heldUntil[i] > endTime) - { - holdFactor = 1.25; - } - - // Decay individual strains - individualStrains[i] = previousHitObject.individualStrains[i] * individualDecay; - } - - heldUntil[BaseHitObject.Column] = endTime; - - // Increase individual strain in own column - IndividualStrain += 2.0 * holdFactor; - - OverallStrain = previousHitObject.OverallStrain * overallDecay + (1.0 + holdAddition) * holdFactor; - } - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs index ad0c04b4cc..5f2ceab48b 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitWindows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects private static readonly IReadOnlyDictionary base_ranges = new Dictionary { { HitResult.Perfect, (44.8, 38.8, 27.8) }, - { HitResult.Great, (128, 98, 68 ) }, + { HitResult.Great, (128, 98, 68) }, { HitResult.Good, (194, 164, 134) }, { HitResult.Ok, (254, 224, 194) }, { HitResult.Meh, (302, 272, 242) }, diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 42877649d2..0035960c63 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index 9de542bcd3..5a30fd6a12 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; diff --git a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs index 44a79de7db..1ea3138828 100644 --- a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs +++ b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mania.Objects.Types { diff --git a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs index 76ccfe324b..f3ea6c7b71 100644 --- a/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Mania.Tests.iOS")] diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index c58d66c66a..65b7d54cd2 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -1,17 +1,16 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Mania.Replays { - internal class ManiaAutoGenerator : AutoGenerator + internal class ManiaAutoGenerator : AutoGenerator { public const double RELEASE_DELAY = 20; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index 20b0775c57..197b105437 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 04d3bdf5f5..81a76c93e6 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/diffcalc-test.osu b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/diffcalc-test.osu new file mode 100644 index 0000000000..4c877c6193 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Resources/Testing/Beatmaps/diffcalc-test.osu @@ -0,0 +1,180 @@ +osu file format v14 + +[General] +Mode: 3 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +37500,-50,4,2,1,50,0,0 +41500,-25,4,2,1,50,0,0 + +[HitObjects] +// jacks spaced 1/1 beat apart +64,192,0,1,0,0:0:0:0: +64,192,500,1,0,0:0:0:0: +64,192,1000,1,0,0:0:0:0: +64,192,1500,1,0,0:0:0:0: +64,192,2000,1,0,0:0:0:0: +64,192,2500,1,0,0:0:0:0: + +// jacks spaced 1/2 beat apart +64,192,3500,1,0,0:0:0:0: +64,192,3750,1,0,0:0:0:0: +64,192,4000,1,0,0:0:0:0: +64,192,4250,1,0,0:0:0:0: +64,192,4500,1,0,0:0:0:0: +64,192,4750,1,0,0:0:0:0: +64,192,5000,1,0,0:0:0:0: +64,192,6000,1,0,0:0:0:0: + +// doubles jacks spaced 1/2 beat apart +192,192,6000,1,0,0:0:0:0: +64,192,6250,1,0,0:0:0:0: +192,192,6250,1,0,0:0:0:0: +64,192,6500,1,0,0:0:0:0: +192,192,6500,1,0,0:0:0:0: +64,192,6750,1,0,0:0:0:0: +192,192,6750,1,0,0:0:0:0: +64,192,7000,1,0,0:0:0:0: +192,192,7000,1,0,0:0:0:0: +64,192,7250,1,0,0:0:0:0: +192,192,7250,1,0,0:0:0:0: +64,192,7500,1,0,0:0:0:0: +192,192,7500,1,0,0:0:0:0: + +// trill spaced 1/2 beat apart +64,192,8500,1,0,0:0:0:0: +192,192,8750,1,0,0:0:0:0: +64,192,9000,1,0,0:0:0:0: +192,192,9250,1,0,0:0:0:0: +64,192,9500,1,0,0:0:0:0: +192,192,9750,1,0,0:0:0:0: +64,192,10000,1,0,0:0:0:0: +192,192,10250,1,0,0:0:0:0: +64,192,10500,1,0,0:0:0:0: + +// stair spaced 1/4 apart +64,192,11500,1,0,0:0:0:0: +192,192,11625,1,0,0:0:0:0: +320,192,11750,1,0,0:0:0:0: +448,192,11875,1,0,0:0:0:0: +320,192,12000,1,0,0:0:0:0: +192,192,12125,1,0,0:0:0:0: +64,192,12250,1,0,0:0:0:0: +192,192,12375,1,0,0:0:0:0: +320,192,12500,1,0,0:0:0:0: +448,192,12625,1,0,0:0:0:0: + +// jumpstreams? +64,192,13500,1,0,0:0:0:0: +192,192,13625,1,0,0:0:0:0: +320,192,13750,1,0,0:0:0:0: +448,192,13875,1,0,0:0:0:0: +320,192,14000,1,0,0:0:0:0: +192,192,14000,1,0,0:0:0:0: +64,192,14125,1,0,0:0:0:0: +192,192,14250,1,0,0:0:0:0: +320,192,14250,1,0,0:0:0:0: +448,192,14250,1,0,0:0:0:0: +64,192,14375,1,0,0:0:0:0: +64,192,14500,1,0,0:0:0:0: +320,192,14625,1,0,0:0:0:0: +448,192,14625,1,0,0:0:0:0: +192,192,14625,1,0,0:0:0:0: +192,192,14750,1,0,0:0:0:0: +64,192,14875,1,0,0:0:0:0: +192,192,15000,1,0,0:0:0:0: +320,192,15125,1,0,0:0:0:0: +448,192,15125,1,0,0:0:0:0: + +// double... jumps? +64,192,16000,1,0,0:0:0:0: +64,192,16250,1,0,0:0:0:0: +192,192,16250,1,0,0:0:0:0: +192,192,16500,1,0,0:0:0:0: +320,192,16500,1,0,0:0:0:0: +320,192,16750,1,0,0:0:0:0: +448,192,16750,1,0,0:0:0:0: +448,192,17000,1,0,0:0:0:0: + +// notes alongside hold +64,192,18000,128,0,18500:0:0:0:0: +192,192,18000,1,0,0:0:0:0: +192,192,18250,1,0,0:0:0:0: +192,192,18500,1,0,0:0:0:0: + +// notes overlapping hold +64,192,19500,1,0,0:0:0:0: +192,192,19625,128,0,20875:0:0:0:0: +64,192,19750,1,0,0:0:0:0: +64,192,20000,1,0,0:0:0:0: +64,192,20250,1,0,0:0:0:0: +64,192,20500,1,0,0:0:0:0: +64,192,20750,1,0,0:0:0:0: +64,192,21000,1,0,0:0:0:0: + +// simultaneous holds +64,192,22000,128,0,23000:0:0:0:0: +192,192,22000,128,0,23000:0:0:0:0: +320,192,22000,128,0,23000:0:0:0:0: +448,192,22000,128,0,23000:0:0:0:0: + +// hold stairs +64,192,24500,128,0,25500:0:0:0:0: +192,192,24625,128,0,25375:0:0:0:0: +320,192,24750,128,0,25250:0:0:0:0: +448,192,24875,128,0,25125:0:0:0:0: +448,192,25375,128,0,26375:0:0:0:0: +320,192,25500,128,0,26250:0:0:0:0: +192,192,25625,128,0,26125:0:0:0:0: +64,192,25750,128,0,26000:0:0:0:0: + +// quads +64,192,26500,1,0,0:0:0:0: +64,192,27500,1,0,0:0:0:0: +192,192,27500,1,0,0:0:0:0: +320,192,27500,1,0,0:0:0:0: +448,192,27500,1,0,0:0:0:0: +64,192,27750,1,0,0:0:0:0: +192,192,27750,1,0,0:0:0:0: +320,192,27750,1,0,0:0:0:0: +448,192,27750,1,0,0:0:0:0: +64,192,28000,1,0,0:0:0:0: +192,192,28000,1,0,0:0:0:0: +320,192,28000,1,0,0:0:0:0: +448,192,28000,1,0,0:0:0:0: +64,192,28250,1,0,0:0:0:0: +192,192,28250,1,0,0:0:0:0: +320,192,28250,1,0,0:0:0:0: +448,192,28250,1,0,0:0:0:0: +64,192,28500,1,0,0:0:0:0: +192,192,28500,1,0,0:0:0:0: +320,192,28500,1,0,0:0:0:0: +448,192,28500,1,0,0:0:0:0: + +// double-trills +64,192,29500,1,0,0:0:0:0: +192,192,29500,1,0,0:0:0:0: +320,192,29625,1,0,0:0:0:0: +448,192,29625,1,0,0:0:0:0: +64,192,29750,1,0,0:0:0:0: +192,192,29750,1,0,0:0:0:0: +320,192,29875,1,0,0:0:0:0: +448,192,29875,1,0,0:0:0:0: +64,192,30000,1,0,0:0:0:0: +192,192,30000,1,0,0:0:0:0: +320,192,30125,1,0,0:0:0:0: +448,192,30125,1,0,0:0:0:0: +64,192,30250,1,0,0:0:0:0: +192,192,30250,1,0,0:0:0:0: +320,192,30375,1,0,0:0:0:0: +448,192,30375,1,0,0:0:0:0: +64,192,30500,1,0,0:0:0:0: +192,192,30500,1,0,0:0:0:0: diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 20a665c314..5c914d8eac 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -92,8 +92,8 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - public ManiaScoreProcessor(RulesetContainer rulesetContainer) - : base(rulesetContainer) + public ManiaScoreProcessor(DrawableRuleset drawableRuleset) + : base(drawableRuleset) { } @@ -159,6 +159,6 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); + public override HitWindows CreateHitWindows() => new ManiaHitWindows(); } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index efa4a671a3..c59bed4ea7 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osuTK.Graphics; @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.UI.Components; @@ -82,28 +82,30 @@ namespace osu.Game.Rulesets.Mania.UI TopLevelContainer.Add(explosionContainer.CreateProxy()); - Direction.BindValueChanged(d => + Direction.BindValueChanged(dir => { hitTargetContainer.Padding = new MarginPadding { - Top = d == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, - Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + Top = dir.NewValue == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - keyArea.Anchor = keyArea.Origin= d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } public override Axes RelativeSizeAxes => Axes.Y; private bool isSpecial; + public bool IsSpecial { - get { return isSpecial; } + get => isSpecial; set { if (isSpecial == value) return; + isSpecial = value; Width = isSpecial ? special_column_width : column_width; @@ -111,13 +113,15 @@ namespace osu.Game.Rulesets.Mania.UI } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { if (accentColour == value) return; + accentColour = value; background.AccentColour = value; @@ -156,7 +160,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements) + if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value) return; explosionContainer.Add(new HitExplosion(judgedObject) @@ -167,7 +171,7 @@ namespace osu.Game.Rulesets.Mania.UI public bool OnPressed(ManiaAction action) { - if (action != Action) + if (action != Action.Value) return false; var nextObject = diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 6aef158205..b4e29ae9f9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -48,9 +48,9 @@ namespace osu.Game.Rulesets.Mania.UI.Components }; direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - backgroundOverlay.Anchor = backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Anchor = backgroundOverlay.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; updateColours(); }, true); } @@ -70,6 +70,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components { if (accentColour == value) return; + accentColour = value; updateColours(); diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index f158d5be07..89e8cd9b5a 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -49,9 +49,9 @@ namespace osu.Game.Rulesets.Mania.UI.Components private void load(IScrollingInfo scrollingInfo) { direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - Anchor anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; hitTargetBar.Anchor = hitTargetBar.Origin = anchor; hitTargetLine.Anchor = hitTargetLine.Origin = anchor; @@ -73,6 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components { if (accentColour == value) return; + accentColour = value; updateColours(); diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index 228e81fef3..03b55cbead 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -64,11 +64,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components }; direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { gradient.Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); + dir.NewValue == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + dir.NewValue == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); }, true); } @@ -87,6 +87,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components { if (accentColour == value) return; + accentColour = value; updateColours(); diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index f78cfefab8..8797f014df 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -19,25 +19,18 @@ namespace osu.Game.Rulesets.Mania.UI private void load() { if (JudgementText != null) - JudgementText.TextSize = 25; + JudgementText.Font = JudgementText.Font.With(size: 25); } - protected override void LoadComplete() + protected override double FadeInDuration => 50; + + protected override void ApplyHitAnimations() { - base.LoadComplete(); + JudgementBody.ScaleTo(0.8f); + JudgementBody.ScaleTo(1, 250, Easing.OutElastic); - this.FadeInFromZero(50, Easing.OutQuint); - - if (Result.IsHit) - { - JudgementBody.ScaleTo(0.8f); - JudgementBody.ScaleTo(1, 250, Easing.OutElastic); - - JudgementBody.Delay(50).ScaleTo(0.75f, 250); - this.Delay(50).FadeOut(200); - } - - Expire(); + JudgementBody.Delay(FadeInDuration).ScaleTo(0.75f, 250); + this.Delay(FadeInDuration).FadeOut(200); } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs similarity index 77% rename from osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs rename to osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index db65dfae41..a019401d5b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -15,7 +15,6 @@ using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; @@ -29,17 +28,19 @@ using osuTK; namespace osu.Game.Rulesets.Mania.UI { - public class ManiaRulesetContainer : ScrollingRulesetContainer + public class DrawableManiaRuleset : DrawableScrollingRuleset { + protected new ManiaPlayfield Playfield => (ManiaPlayfield)base.Playfield; + public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; public IEnumerable BarLines; - protected new ManiaConfigManager Config => (ManiaConfigManager)base.Config; + protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; private readonly Bindable configDirection = new Bindable(); - public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { // Generate the bar lines @@ -75,10 +76,10 @@ namespace osu.Game.Rulesets.Mania.UI { BarLines.ForEach(Playfield.Add); - Config.BindWith(ManiaSetting.ScrollDirection, configDirection); - configDirection.BindValueChanged(v => Direction.Value = (ScrollingDirection)v, true); + Config.BindWith(ManiaRulesetSetting.ScrollDirection, configDirection); + configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true); - Config.BindWith(ManiaSetting.ScrollTime, TimeRange); + Config.BindWith(ManiaRulesetSetting.ScrollTime, TimeRange); } /// @@ -96,9 +97,9 @@ namespace osu.Game.Rulesets.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); - public override int Variant => (int)(Mods.OfType().FirstOrDefault()?.PlayfieldType ?? PlayfieldType.Single) + Beatmap.TotalColumns; + public override int Variant => (int)(Beatmap.Stages.Count == 1 ? PlayfieldType.Single : PlayfieldType.Dual) + Beatmap.TotalColumns; - public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); + protected override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); public override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 817b60d14a..f5a9978f77 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 0caac39f21..81888d2773 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs index 0fc9c1920a..98165fedeb 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingDirection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index f71b866912..a28de7ea58 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -136,12 +136,12 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } - Direction.BindValueChanged(d => + Direction.BindValueChanged(dir => { barLineContainer.Padding = new MarginPadding { - Top = d == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, - Bottom = d == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, + Top = dir.NewValue == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, }; }, true); } @@ -185,7 +185,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayResult || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements.Value) return; judgements.Clear(); diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs new file mode 100644 index 0000000000..01e635f09c --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.iOS/AppDelegate.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; +using osu.Game.Tests; + +namespace osu.Game.Rulesets.Osu.Tests.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs new file mode 100644 index 0000000000..7a0797a909 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.Game.Rulesets.Osu.Tests.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Entitlements.plist b/osu.Game.Rulesets.Osu.Tests.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist new file mode 100644 index 0000000000..f79215cf54 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleName + osu.Game.Rulesets.Osu.Tests.iOS + CFBundleIdentifier + ppy.osu-Game-Rulesets-Osu-Tests-iOS + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj new file mode 100644 index 0000000000..9930a166e3 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -0,0 +1,45 @@ + + + + + Debug + iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96} + Exe + osu.Game.Rulesets.Osu.Tests + osu.Game.Rulesets.Osu.Tests.iOS + + + + + + + libbass.a + PreserveNewest + + + libbass_fx.a + PreserveNewest + + + Linker.xml + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {C92A607B-1FDD-4954-9F92-03FF547D9080} + osu.Game.Rulesets.Osu + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs index 3a551bbbcf..f7d1ff4db1 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuBeatmapConversionTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -33,9 +33,11 @@ namespace osu.Game.Rulesets.Osu.Tests case Slider slider: foreach (var nested in slider.NestedHitObjects) yield return createConvertValue(nested); + break; default: yield return createConvertValue(hitObject); + break; } diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs new file mode 100644 index 0000000000..e55dc1f902 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Osu.Difficulty; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class OsuDifficultyCalculatorTest : DifficultyCalculatorTest + { + protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; + + [TestCase(6.931145117263422, "diffcalc-test")] + public void Test(double expected, string name) + => base.Test(expected, name); + + protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(new OsuRuleset(), beatmap); + + protected override Ruleset CreateRuleset() => new OsuRuleset(); + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs index 579cb77084..e2f6b2164c 100644 --- a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using System.Linq; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs index f2525ad555..83626e7043 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseEditor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs index 472da88e1f..5c1e775c01 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseGameplayCursor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -16,18 +16,18 @@ namespace osu.Game.Rulesets.Osu.Tests [TestFixture] public class TestCaseGameplayCursor : OsuTestCase, IProvideCursor { - private GameplayCursor cursor; + private GameplayCursorContainer cursorContainer; - public override IReadOnlyList RequiredTypes => new [] { typeof(CursorTrail) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(CursorTrail) }; - public CursorContainer Cursor => cursor; + public CursorContainer Cursor => cursorContainer; public bool ProvidingUserCursor => true; [BackgroundDependencyLoader] private void load() { - Add(cursor = new GameplayCursor { RelativeSizeAxes = Axes.Both }); + Add(cursorContainer = new GameplayCursorContainer { RelativeSizeAxes = Axes.Both }); } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index 1c1a027411..e1e854e8dc 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -89,7 +89,8 @@ namespace osu.Game.Rulesets.Osu.Tests { private readonly bool auto; - public TestDrawableHitCircle(HitCircle h, bool auto) : base(h) + public TestDrawableHitCircle(HitCircle h, bool auto) + : base(h) { this.auto = auto; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs index 68c35faca4..26d9b5ae91 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs new file mode 100644 index 0000000000..8d097ff1c1 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleLongCombo.cs @@ -0,0 +1,37 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class TestCaseHitCircleLongCombo : PlayerTestCase + { + public TestCaseHitCircleLongCombo() + : base(new OsuRuleset()) + { + } + + protected override IBeatmap CreateBeatmap(Ruleset ruleset) + { + var beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 }, + Ruleset = ruleset.RulesetInfo + } + }; + + for (int i = 0; i < 512; i++) + beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); + + return beatmap; + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs index 313438a337..d536e39eef 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCirclePlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs index fed62188ab..e9284e453e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircleSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs new file mode 100644 index 0000000000..720c3c66fe --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseOsuPlayer.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class TestCaseOsuPlayer : PlayerTestCase + { + public TestCaseOsuPlayer() + : base(new OsuRuleset()) + { + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs index 97978cff1e..5dc0dc1024 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.MathUtils; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index 1895913917..35e8f3e17e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -16,6 +16,7 @@ using osuTK.Graphics; using osu.Game.Rulesets.Mods; using System.Linq; using NUnit.Framework; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -300,6 +301,7 @@ namespace osu.Game.Rulesets.Osu.Tests } private float judgementOffsetDirection = 1; + private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { var osuObject = judgedObject as DrawableOsuHitObject; @@ -313,7 +315,7 @@ namespace osu.Game.Rulesets.Osu.Tests Origin = Anchor.Centre, Text = result.IsHit ? "Hit!" : "Miss!", Colour = result.IsHit ? Color4.Green : Color4.Red, - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs index 1c207d1fca..ba5bd48c51 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs new file mode 100644 index 0000000000..2f33982d41 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -0,0 +1,372 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Replays; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseSliderInput : RateAdjustedBeatmapTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SliderBall), + typeof(DrawableSlider), + typeof(DrawableSliderTick), + typeof(DrawableRepeatPoint), + typeof(DrawableOsuHitObject), + typeof(DrawableSliderHead), + typeof(DrawableSliderTail), + }; + + private const double time_before_slider = 250; + private const double time_slider_start = 1500; + private const double time_during_slide_1 = 2500; + private const double time_during_slide_2 = 3000; + private const double time_during_slide_3 = 3500; + private const double time_during_slide_4 = 3800; + + private List judgementResults; + private bool allJudgedFired; + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the latter pressed key + /// Expected Result: + /// A passing test case will have the cursor lose tracking on replay frame 3. + /// + [Test] + public void TestInvalidKeyTransfer() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the original key used to hit the slider + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the new key that was pressed second + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestTrackingRetentionLeftRightLeft() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key that was held down before the slider started. + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3 + /// + [Test] + public void TestTrackingLeftBeforeSliderToRight() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down throughout the slider without pressing any other buttons. + /// Expected Result: + /// A passing test case will have the cursor track the slider, but miss the slider head. + /// + [Test] + public void TestTrackingPreclicked() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + }); + + AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailTracked); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down after the slider starts + /// - Move the cursor away from the slider body + /// - Move the cursor back onto the body + /// Expected Result: + /// A passing test case will have the cursor track the slider, miss the head, miss the ticks where its outside of the body, and resume tracking when the cursor returns. + /// + [Test] + public void TestTrackingReturnMidSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking re-acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key used to hit the slider head + /// - While holding the first key, move the cursor away from the slider body + /// - Still holding the first key, move the cursor back to the slider body + /// Expected Result: + /// A passing test case will have the slider not track despite having the cursor return to the slider body. + /// + [Test] + public void TestTrackingReturnMidSliderKeyDownBefore() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Scenario: + /// - Wait for the slider to reach a mid-point + /// - Press a key away from the slider body + /// - While holding down the key, move into the slider body + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestTrackingMidSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key before the slider starts + /// - Press another key on the slider head while holding the original key + /// - Move out of the slider body while releasing the two pressed keys + /// - Move back into the slider body while pressing any key. + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestMidSliderTrackingAcquired() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + [Test] + public void TestMidSliderTrackingAcquiredWithMouseDownOutsideSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key on the slider head + /// - While holding the key, move outside of the slider body with the cursor + /// - Release the key while outside of the slider body + /// - Press the key again while outside of the slider body + /// - Move back into the slider body while holding the pressed key + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestTrackingReleasedValidKey() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great; + + private bool assertHeadMissTailTracked() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; + + private bool assertMidSliderJudgements() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great; + + private bool assertMidSliderJudgementFail() => judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; + + private ScoreAccessibleReplayPlayer currentPlayer; + + private void performTest(List frames) + { + // Empty frame to be added as a workaround for first frame behavior. + // If an input exists on the first frame, the input would apply to the entire intro lead-in + // Likely requires some discussion regarding how first frame inputs should be handled. + frames.Insert(0, new OsuReplayFrame()); + + AddStep("load player", () => + { + Beatmap.Value = new TestWorkingBeatmap(new Beatmap + { + HitObjects = + { + new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + } + }, + ControlPointInfo = + { + DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }, Clock); + + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false + }; + + p.OnLoadComplete += _ => + { + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults.Add(result); + }; + p.ScoreProcessor.AllJudged += () => + { + if (currentPlayer == p) allJudgedFired = true; + }; + }; + + LoadScreen(currentPlayer = p); + allJudgedFired = false; + judgementResults = new List(); + }); + + AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); + AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); + AddUntilStep("Wait for all judged", () => allJudgedFired); + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs index 1f693ad9f4..f11d98613a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderPlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs index cd07369ccf..a7386ba48b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs index 3b91ea93b8..e8b534bba9 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Tests public class TestCaseSpinner : OsuTestCase { public override IReadOnlyList RequiredTypes => new[] -{ + { typeof(SpinnerDisc), typeof(DrawableSpinner), typeof(DrawableOsuHitObject) @@ -67,7 +67,8 @@ namespace osu.Game.Rulesets.Osu.Tests { private bool auto; - public TestDrawableSpinner(Spinner s, bool auto) : base(s) + public TestDrawableSpinner(Spinner s, bool auto) + : base(s) { this.auto = auto; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs index b93a6ed0f1..6136ce1639 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs index 9a90be2582..9001ad3596 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerPlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs index d7ba5d8105..11f5ddf8b5 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinnerSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 35f137572d..8c31db9a7d 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,9 +2,9 @@ - + - + diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs index 6d90c2a875..1a352aa2a1 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 510c32fd9f..6a41e93c35 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 483ff2d409..59a5f90fd0 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs new file mode 100644 index 0000000000..f6edd062e9 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Configuration/OsuRulesetConfigManager.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; + +namespace osu.Game.Rulesets.Osu.Configuration +{ + public class OsuRulesetConfigManager : RulesetConfigManager + { + public OsuRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) + { + } + + protected override void InitialiseDefaults() + { + base.InitialiseDefaults(); + + Set(OsuRulesetSetting.SnakingInSliders, true); + Set(OsuRulesetSetting.SnakingOutSliders, true); + } + } + + public enum OsuRulesetSetting + { + SnakingInSliders, + SnakingOutSliders + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index 2b42eed0c5..6e991a1d08 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Difficulty { @@ -13,10 +12,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty public double ApproachRate; public double OverallDifficulty; public int MaxCombo; - - public OsuDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 8fc2b69267..e2a1542574 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -1,10 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; @@ -15,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuDifficultyCalculator : DifficultyCalculator { - private const int section_length = 400; private const double difficulty_multiplier = 0.0675; public OsuDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) @@ -23,54 +25,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty { } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new OsuDifficultyAttributes(mods, 0); - - OsuDifficultyBeatmap difficultyBeatmap = new OsuDifficultyBeatmap(beatmap.HitObjects.Cast().ToList(), timeRate); - Skill[] skills = - { - new Aim(), - new Speed() - }; - - double sectionLength = section_length * timeRate; - - // The first object doesn't generate a strain, so we begin with an incremented section end - double currentSectionEnd = Math.Ceiling(beatmap.HitObjects.First().StartTime / sectionLength) * sectionLength; - - foreach (OsuDifficultyHitObject h in difficultyBeatmap) - { - while (h.BaseObject.StartTime > currentSectionEnd) - { - foreach (Skill s in skills) - { - s.SaveCurrentPeak(); - s.StartNewSectionFrom(currentSectionEnd); - } - - currentSectionEnd += sectionLength; - } - - foreach (Skill s in skills) - s.Process(h); - } + if (beatmap.HitObjects.Count == 0) + return new OsuDifficultyAttributes { Mods = mods }; double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future - double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate; - double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; + double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate; + double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; int maxCombo = beatmap.HitObjects.Count; // Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above) maxCombo += beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); - return new OsuDifficultyAttributes(mods, starRating) + return new OsuDifficultyAttributes { + StarRating = starRating, + Mods = mods, AimStrain = aimRating, SpeedStrain = speedRating, ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5, @@ -79,6 +54,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty }; } + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + // The first jump is formed by the first two hitobjects of the map. + // If the map has less than two OsuHitObjects, the enumerator will not return anything. + for (int i = 1; i < beatmap.HitObjects.Count; i++) + { + var lastLast = i > 1 ? beatmap.HitObjects[i - 2] : null; + var last = beatmap.HitObjects[i - 1]; + var current = beatmap.HitObjects[i]; + + yield return new OsuDifficultyHitObject(current, lastLast, last, clockRate); + } + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] + { + new Aim(), + new Speed() + }; + protected override Mod[] DifficultyAdjustmentMods => new Mod[] { new OsuModDoubleTime(), diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 16f0af9875..0dce5208dd 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -88,11 +88,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty private double computeAimValue() { - double aimValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.AimStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f; + double rawAim = Attributes.AimStrain; + + if (mods.Any(m => m is OsuModTouchDevice)) + rawAim = Math.Pow(rawAim, 0.8); + + double aimValue = Math.Pow(5.0f * Math.Max(1.0f, rawAim / 0.0675f) - 4.0f, 3.0f) / 100000.0f; // Longer maps are worth more double lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); aimValue *= lengthBonus; @@ -105,28 +110,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty double approachRateFactor = 1.0f; if (Attributes.ApproachRate > 10.33f) - approachRateFactor += 0.45f * (Attributes.ApproachRate - 10.33f); + approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); else if (Attributes.ApproachRate < 8.0f) { - // HD is worth more with lower ar! - if (mods.Any(h => h is OsuModHidden)) - approachRateFactor += 0.02f * (8.0f - Attributes.ApproachRate); - else - approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); + approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate); } aimValue *= approachRateFactor; // We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR. if (mods.Any(h => h is OsuModHidden)) - aimValue *= 1.02 + (11.0f - Attributes.ApproachRate) / 50.0; // Gives a 1.04 bonus for AR10, a 1.06 bonus for AR9, a 1.02 bonus for AR11. + aimValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); if (mods.Any(h => h is OsuModFlashlight)) { // Apply object-based bonus for flashlight. aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) + - (totalHits > 200 ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + - (totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) : 0.0f); + (totalHits > 200 + ? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) + + (totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f) + : 0.0f); } // Scale the aim value with accuracy _slightly_ @@ -143,7 +146,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty // Longer maps are worth more speedValue *= 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) + - (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); + (totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f); // Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available speedValue *= Math.Pow(0.97f, countMiss); @@ -152,13 +155,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (beatmapMaxCombo > 0) speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f); + double approachRateFactor = 1.0f; + if (Attributes.ApproachRate > 10.33f) + approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f); + + speedValue *= approachRateFactor; + if (mods.Any(m => m is OsuModHidden)) - speedValue *= 1.18f; + speedValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate); // Scale the speed value with accuracy _slightly_ - speedValue *= 0.5f + accuracy / 2.0f; + speedValue *= 0.02f + accuracy; // It is important to also consider accuracy difficulty when doing that - speedValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500; + speedValue *= 0.96f + Math.Pow(Attributes.OverallDifficulty, 2) / 1600; return speedValue; } @@ -186,7 +195,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f)); if (mods.Any(m => m is OsuModHidden)) - accuracyValue *= 1.02f; + accuracyValue *= 1.08f; if (mods.Any(m => m is OsuModFlashlight)) accuracyValue *= 1.02f; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs deleted file mode 100644 index 24d4677981..0000000000 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Osu.Objects; - -namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing -{ - /// - /// An enumerable container wrapping input as - /// which contains extra data required for difficulty calculation. - /// - public class OsuDifficultyBeatmap : IEnumerable - { - private readonly IEnumerator difficultyObjects; - - /// - /// Creates an enumerator, which preprocesses a list of s recieved as input, wrapping them as - /// which contains extra data required for difficulty calculation. - /// - public OsuDifficultyBeatmap(List objects, double timeRate) - { - // Sort OsuHitObjects by StartTime - they are not correctly ordered in some cases. - // This should probably happen before the objects reach the difficulty calculator. - difficultyObjects = createDifficultyObjectEnumerator(objects.OrderBy(h => h.StartTime).ToList(), timeRate); - } - - /// - /// Returns an enumerator that enumerates all s in the . - /// - public IEnumerator GetEnumerator() => difficultyObjects; - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - private IEnumerator createDifficultyObjectEnumerator(List objects, double timeRate) - { - // The first jump is formed by the first two hitobjects of the map. - // If the map has less than two OsuHitObjects, the enumerator will not return anything. - for (int i = 1; i < objects.Count; i++) - yield return new OsuDifficultyHitObject(objects[i], objects[i - 1], timeRate); - } - } -} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index d8e3b340c9..37276a3432 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -1,24 +1,20 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osuTK; namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing { - /// - /// A wrapper around extending it with additional data required for difficulty calculation. - /// - public class OsuDifficultyHitObject + public class OsuDifficultyHitObject : DifficultyHitObject { private const int normalized_radius = 52; - /// - /// The this refers to. - /// - public OsuHitObject BaseObject { get; } + protected new OsuHitObject BaseObject => (OsuHitObject)base.BaseObject; /// /// Normalized distance from the end position of the previous to the start position of this . @@ -31,31 +27,29 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing public double TravelDistance { get; private set; } /// - /// Milliseconds elapsed since the StartTime of the previous . + /// Angle the player has to take to hit this . + /// Calculated as the angle between the circles (current-2, current-1, current). /// - public double DeltaTime { get; private set; } + public double? Angle { get; private set; } /// /// Milliseconds elapsed since the start time of the previous , with a minimum of 50ms. /// - public double StrainTime { get; private set; } + public readonly double StrainTime; + private readonly OsuHitObject lastLastObject; private readonly OsuHitObject lastObject; - private readonly double timeRate; - /// - /// Initializes the object calculating extra data required for difficulty calculation. - /// - public OsuDifficultyHitObject(OsuHitObject currentObject, OsuHitObject lastObject, double timeRate) + public OsuDifficultyHitObject(HitObject hitObject, HitObject lastLastObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) { - this.lastObject = lastObject; - this.timeRate = timeRate; - - BaseObject = currentObject; + this.lastLastObject = (OsuHitObject)lastLastObject; + this.lastObject = (OsuHitObject)lastObject; setDistances(); - setTimingValues(); - // Calculate angle here + + // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure + StrainTime = Math.Max(50, DeltaTime); } private void setDistances() @@ -68,41 +62,44 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing scalingFactor *= 1 + smallCircleBonus; } - Vector2 lastCursorPosition = lastObject.StackedPosition; - - var lastSlider = lastObject as Slider; - if (lastSlider != null) + if (lastObject is Slider lastSlider) { computeSliderCursorPosition(lastSlider); - lastCursorPosition = lastSlider.LazyEndPosition ?? lastCursorPosition; - TravelDistance = lastSlider.LazyTravelDistance * scalingFactor; } + Vector2 lastCursorPosition = getEndCursorPosition(lastObject); + // Don't need to jump to reach spinners if (!(BaseObject is Spinner)) JumpDistance = (BaseObject.StackedPosition * scalingFactor - lastCursorPosition * scalingFactor).Length; - } - private void setTimingValues() - { - DeltaTime = (BaseObject.StartTime - lastObject.StartTime) / timeRate; + if (lastLastObject != null) + { + Vector2 lastLastCursorPosition = getEndCursorPosition(lastLastObject); - // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure - StrainTime = Math.Max(50, DeltaTime); + Vector2 v1 = lastLastCursorPosition - lastObject.StackedPosition; + Vector2 v2 = BaseObject.StackedPosition - lastCursorPosition; + + float dot = Vector2.Dot(v1, v2); + float det = v1.X * v2.Y - v1.Y * v2.X; + + Angle = Math.Abs(Math.Atan2(det, dot)); + } } private void computeSliderCursorPosition(Slider slider) { if (slider.LazyEndPosition != null) return; + slider.LazyEndPosition = slider.StackedPosition; float approxFollowCircleRadius = (float)(slider.Radius * 3); var computeVertex = new Action(t => { - double progress = ((int)t - (int)slider.StartTime) / (float)(int)slider.SpanDuration; - if (progress % 2 > 1) + double progress = (t - slider.StartTime) / slider.SpanDuration; + if (progress % 2 >= 1) progress = 1 - progress % 1; else progress = progress % 1; @@ -125,7 +122,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing var scoringTimes = slider.NestedHitObjects.Skip(1).Select(t => t.StartTime); foreach (var time in scoringTimes) computeVertex(time); - computeVertex(slider.EndTime); + } + + private Vector2 getEndCursorPosition(OsuHitObject hitObject) + { + Vector2 pos = hitObject.StackedPosition; + + if (hitObject is Slider slider) + { + computeSliderCursorPosition(slider); + pos = slider.LazyEndPosition ?? pos; + } + + return pos; } } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index f11b6d66f6..e74f4933b2 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -1,8 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -11,10 +14,46 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// public class Aim : Skill { + private const double angle_bonus_begin = Math.PI / 3; + private const double timing_threshold = 107; + protected override double SkillMultiplier => 26.25; protected override double StrainDecayBase => 0.15; - protected override double StrainValueOf(OsuDifficultyHitObject current) - => (Math.Pow(current.TravelDistance, 0.99) + Math.Pow(current.JumpDistance, 0.99)) / current.StrainTime; + protected override double StrainValueOf(DifficultyHitObject current) + { + if (current.BaseObject is Spinner) + return 0; + + var osuCurrent = (OsuDifficultyHitObject)current; + + double result = 0; + + if (Previous.Count > 0) + { + var osuPrevious = (OsuDifficultyHitObject)Previous[0]; + + if (osuCurrent.Angle != null && osuCurrent.Angle.Value > angle_bonus_begin) + { + const double scale = 90; + + var angleBonus = Math.Sqrt( + Math.Max(osuPrevious.JumpDistance - scale, 0) + * Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2) + * Math.Max(osuCurrent.JumpDistance - scale, 0)); + result = 1.5 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.StrainTime); + } + } + + double jumpDistanceExp = applyDiminishingExp(osuCurrent.JumpDistance); + double travelDistanceExp = applyDiminishingExp(osuCurrent.TravelDistance); + + return Math.Max( + result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.StrainTime, timing_threshold), + (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.StrainTime + ); + } + + private double applyDiminishingExp(double val) => Math.Pow(val, 0.99); } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 1cde03624b..46a81a9480 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -1,7 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -10,30 +14,48 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// public class Speed : Skill { + private const double single_spacing_threshold = 125; + + private const double angle_bonus_begin = 5 * Math.PI / 6; + private const double pi_over_4 = Math.PI / 4; + private const double pi_over_2 = Math.PI / 2; + protected override double SkillMultiplier => 1400; protected override double StrainDecayBase => 0.3; - private const double single_spacing_threshold = 125; - private const double stream_spacing_threshold = 110; - private const double almost_diameter = 90; + private const double min_speed_bonus = 75; // ~200BPM + private const double max_speed_bonus = 45; // ~330BPM + private const double speed_balancing_factor = 40; - protected override double StrainValueOf(OsuDifficultyHitObject current) + protected override double StrainValueOf(DifficultyHitObject current) { - double distance = current.TravelDistance + current.JumpDistance; + if (current.BaseObject is Spinner) + return 0; - double speedValue; - if (distance > single_spacing_threshold) - speedValue = 2.5; - else if (distance > stream_spacing_threshold) - speedValue = 1.6 + 0.9 * (distance - stream_spacing_threshold) / (single_spacing_threshold - stream_spacing_threshold); - else if (distance > almost_diameter) - speedValue = 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter); - else if (distance > almost_diameter / 2) - speedValue = 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2); - else - speedValue = 0.95; + var osuCurrent = (OsuDifficultyHitObject)current; - return speedValue / current.StrainTime; + double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance); + double deltaTime = Math.Max(max_speed_bonus, current.DeltaTime); + + double speedBonus = 1.0; + if (deltaTime < min_speed_bonus) + speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2); + + double angleBonus = 1.0; + if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin) + { + angleBonus = 1 + Math.Pow(Math.Sin(1.5 * (angle_bonus_begin - osuCurrent.Angle.Value)), 2) / 3.57; + if (osuCurrent.Angle.Value < pi_over_2) + { + angleBonus = 1.28; + if (distance < 90 && osuCurrent.Angle.Value < pi_over_4) + angleBonus += (1 - angleBonus) * Math.Min((90 - distance) / 10, 1); + else if (distance < 90) + angleBonus += (1 - angleBonus) * Math.Min((90 - distance) / 10, 1) * Math.Sin((pi_over_2 - osuCurrent.Angle.Value) / pi_over_4); + } + } + + return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index de219ed5a5..7f6a60c400 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components PositionBindable.BindValueChanged(_ => UpdatePosition(), true); StackHeightBindable.BindValueChanged(_ => UpdatePosition()); - ScaleBindable.BindValueChanged(v => Scale = new Vector2(v), true); + ScaleBindable.BindValueChanged(scale => Scale = new Vector2(scale.NewValue), true); } protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index eddd399a4a..a4050f0c31 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; +using osuTK; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { @@ -22,8 +23,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles { base.LoadComplete(); - // Fixes a 1-frame position discrpancy due to the first mouse move event happening in the next frame - HitObject.Position = GetContainingInputManager().CurrentState.Mouse.Position; + // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame + HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero; } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index a59dac1834..83787e2219 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs index 882a9a3d81..315a5a2b9d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index fab9c27c6d..dd524252f3 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs index ef7254d9c9..8fd1d6d6f9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs index 18efe21404..e257369ad9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components path = new SmoothPath { Anchor = Anchor.Centre, - PathWidth = 1 + PathRadius = 1 }, marker = new CircularContainer { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs index 0089c2dddd..df846b5d5b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/PathControlPointVisualiser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index 5ea85676b5..957550a051 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components InternalChild = body = new ManualSliderBody { AccentColour = Color4.Transparent, - PathWidth = slider.Scale * 64 + PathRadius = slider.Scale * 64 }; } @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components body.BorderColour = colours.Yellow; PositionBindable.BindValueChanged(_ => updatePosition(), true); - ScaleBindable.BindValueChanged(v => body.PathWidth = v * 64, true); + ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * 64, true); } private void updatePosition() => Position = slider.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs index 205ac6bea3..9d164ebe0b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index 32258572bf..c9f005495c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index ba3501cb2b..989a53db1f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -47,6 +47,14 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders setState(PlacementState.Initial); } + protected override void LoadComplete() + { + base.LoadComplete(); + + // Fixes a 1-frame position discrepancy due to the first mouse move event happening in the next frame + HitObject.Position = Parent?.ToLocalSpace(GetContainingInputManager().CurrentState.Mouse.Position) ?? Vector2.Zero; + } + protected override bool OnMouseMove(MouseMoveEvent e) { switch (state) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs index a117a7056e..616bb17e05 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPosition.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs index 2206a36738..fb8c081ff7 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index af648cfa1b..ae94848c81 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components PositionBindable.BindValueChanged(_ => updatePosition(), true); StackHeightBindable.BindValueChanged(_ => updatePosition()); - ScaleBindable.BindValueChanged(v => ring.Scale = new Vector2(v), true); + ScaleBindable.BindValueChanged(scale => ring.Scale = new Vector2(scale.NewValue), true); } private void updatePosition() => Position = spinner.Position; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 804a4fcba0..03d761c67f 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index e4bcc20f6a..25cef3b251 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs new file mode 100644 index 0000000000..1a6e78d918 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Cursor; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class DrawableOsuEditRuleset : DrawableOsuRuleset + { + public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap) + : base(ruleset, beatmap) + { + } + + protected override Playfield CreatePlayfield() => new OsuPlayfieldNoCursor { Size = Vector2.One }; + + private class OsuPlayfieldNoCursor : OsuPlayfield + { + protected override CursorContainer CreateCursor() => null; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs index ddab70d53a..9c94fe0e3d 100644 --- a/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/HitCircleCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs deleted file mode 100644 index 05bc7dada0..0000000000 --- a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics.Cursor; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.UI; -using osuTK; - -namespace osu.Game.Rulesets.Osu.Edit -{ - public class OsuEditRulesetContainer : OsuRulesetContainer - { - public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) - { - } - - protected override CursorContainer CreateCursor() => null; - - protected override Playfield CreatePlayfield() => new OsuPlayfield { Size = Vector2.One }; - } -} diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 117af9e853..dd3925e04f 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Graphics; @@ -26,8 +26,8 @@ namespace osu.Game.Rulesets.Osu.Edit { } - protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) - => new OsuEditRulesetContainer(ruleset, beatmap); + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap) + => new DrawableOsuEditRuleset(ruleset, beatmap); protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 0c7e571ef5..1ab1219ab0 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Input.Events; diff --git a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs index 6d4f67c597..a377deb35f 100644 --- a/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SliderCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs index 5c19a1bac0..0de0af8f8c 100644 --- a/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs +++ b/osu.Game.Rulesets.Osu/Edit/SpinnerCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; diff --git a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs index 3000031c78..ad292b0439 100644 --- a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,8 +9,10 @@ namespace osu.Game.Rulesets.Osu.Judgements { [Description(@"")] None, + [Description(@"Good")] Good, + [Description(@"Amazing")] Perfect } diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index b1c9760866..81fedf9f4a 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs index 17b8b4399f..c7661bddb1 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs index d52de9f971..5104d9494b 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index 4d371c2e16..21b4dbfeda 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index 7ef01e075c..bea2bbcb32 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray(); - protected override Score CreateReplayScore(Beatmap beatmap) => new Score + public override Score CreateReplayScore(IBeatmap beatmap) => new Score { ScoreInfo = new ScoreInfo { User = new User { Username = "Autoplay" } }, Replay = new OsuAutoGenerator(beatmap).Generate() diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index cc2102f0e9..a1f4dfe1da 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -18,7 +18,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBlinds : Mod, IApplicableToRulesetContainer, IApplicableToScoreProcessor + public class OsuModBlinds : Mod, IApplicableToDrawableRuleset, IApplicableToScoreProcessor { public override string Name => "Blinds"; public override string Description => "Play with blinds on your screen."; @@ -32,14 +32,14 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1.12; private DrawableOsuBlinds blinds; - public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - rulesetContainer.Overlays.Add(blinds = new DrawableOsuBlinds(rulesetContainer.Playfield.HitObjectContainer, rulesetContainer.Beatmap)); + drawableRuleset.Overlays.Add(blinds = new DrawableOsuBlinds(drawableRuleset.Playfield.HitObjectContainer, drawableRuleset.Beatmap)); } public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += val => { blinds.AnimateClosedness((float)val); }; + scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } /// diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs index ff3f6ea7cf..371dfe6a1a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs index 45b538d506..933c6cde1c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs index 465775b175..f13c7d2ff6 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 84a35b04fe..2c40d18f1b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; @@ -41,9 +42,9 @@ namespace osu.Game.Rulesets.Osu.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs new file mode 100644 index 0000000000..65e9eb7a1d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModGrow : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Grow"; + + public override string Acronym => "GR"; + + public override FontAwesome Icon => FontAwesome.fa_arrows_v; + + public override ModType Type => ModType.Fun; + + public override string Description => "Hit them at the right size!"; + + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + { + switch (drawable) + { + case DrawableSpinner _: + continue; + default: + drawable.ApplyCustomUpdateState += ApplyCustomState; + break; + } + } + } + + protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) + { + var h = (OsuHitObject)drawable.HitObject; + + // apply grow effect + switch (drawable) + { + case DrawableSliderHead _: + case DrawableSliderTail _: + // special cases we should *not* be scaling. + break; + case DrawableSlider _: + case DrawableHitCircle _: + { + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + drawable.ScaleTo(0.5f).Then().ScaleTo(1, h.TimePreempt, Easing.OutSine); + break; + } + } + + // remove approach circles + switch (drawable) + { + case DrawableHitCircle circle: + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.ApproachCircle.Hide(); + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs index dc3ba592fb..4769e7660b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs index 1569e868b2..80686b7983 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 4eff2a55c8..1a30b2c944 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs index 9c1b2d8a35..5668c17792 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs index a51cb9d888..9f707a5aa6 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs index 5169c8186b..da462eb6e8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 8d27502b3c..ec23570f54 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -13,7 +13,7 @@ using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToRulesetContainer + public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToDrawableRuleset { 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.Append(typeof(OsuModAutopilot)).ToArray(); @@ -79,10 +79,10 @@ namespace osu.Game.Rulesets.Osu.Mods state.Apply(osuInputManager.CurrentState, osuInputManager); } - public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { // grab the input manager for future use. - osuInputManager = (OsuInputManager)rulesetContainer.KeyBindingInputManager; + osuInputManager = (OsuInputManager)drawableRuleset.KeyBindingInputManager; osuInputManager.AllowUserPresses = false; } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index cf0d629367..0c8436d096 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs index fdd5099ad6..0403e81229 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs index 968854d8b2..36fa5f3098 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs new file mode 100644 index 0000000000..571756d056 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModTouchDevice : Mod + { + public override string Name => "Touch Device"; + public override string Acronym => "TD"; + public override double ScoreMultiplier => 1; + + public override bool Ranked => true; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs index 6949f44bd1..9a769ec39c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Mods { foreach (var drawable in drawables) { - var hitObject = (OsuHitObject) drawable.HitObject; + var hitObject = (OsuHitObject)drawable.HitObject; float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2; @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Mods .MoveTo(originalPosition, moveDuration, Easing.InOutSine); } - theta += (float) hitObject.TimeFadeIn / 1000; + theta += (float)hitObject.TimeFadeIn / 1000; } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs index 3f7d43e31f..af9f0ec8f3 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index f15be94b8a..9106f4c7bd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects; @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Connects hit objects visually, for example with follow points. /// - public abstract class ConnectionRenderer : Container + public abstract class ConnectionRenderer : LifetimeManagementContainer where T : HitObject { /// diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index bd329266aa..3c64fe57d4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 61219d9bb9..8f9d487d49 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -12,39 +12,44 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections public class FollowPointRenderer : ConnectionRenderer { private int pointDistance = 32; + /// /// Determines how much space there is between points. /// public int PointDistance { - get { return pointDistance; } + get => pointDistance; set { if (pointDistance == value) return; + pointDistance = value; update(); } } private int preEmpt = 800; + /// /// Follow points to the next hitobject start appearing for this many milliseconds before an hitobject's end time. /// public int PreEmpt { - get { return preEmpt; } + get => preEmpt; set { if (preEmpt == value) return; + preEmpt = value; update(); } } private IEnumerable hitObjects; + public override IEnumerable HitObjects { - get { return hitObjects; } + get => hitObjects; set { hitObjects = value; @@ -56,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private void update() { - Clear(); + ClearInternal(); if (hitObjects == null) return; @@ -86,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections FollowPoint fp; - Add(fp = new FollowPoint + AddInternal(fp = new FollowPoint { Position = pointStartPosition, Rotation = rotation, @@ -107,6 +112,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections fp.Expire(true); } } + prevHitObject = currHitObject; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 9b562745fa..decd0ce073 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK; @@ -27,40 +28,60 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); + public OsuAction? HitAction => circle.HitAction; + + private readonly Container explodeContainer; + + private readonly Container scaleContainer; + public DrawableHitCircle(HitCircle h) : base(h) { Origin = Anchor.Centre; Position = HitObject.StackedPosition; - Scale = new Vector2(h.Scale); InternalChildren = new Drawable[] { - glow = new GlowPiece(), - circle = new CirclePiece + scaleContainer = new Container { - Hit = () => + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Child = explodeContainer = new Container { - if (AllJudged) - return false; + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Children = new Drawable[] + { + glow = new GlowPiece(), + circle = new CirclePiece + { + Hit = () => + { + if (AllJudged) + return false; - UpdateResult(true); - return true; - }, + UpdateResult(true); + return true; + }, + }, + number = new NumberPiece + { + Text = (HitObject.IndexInCurrentCombo + 1).ToString(), + }, + ring = new RingPiece(), + flash = new FlashPiece(), + explode = new ExplodePiece(), + ApproachCircle = new ApproachCircle + { + Alpha = 0, + Scale = new Vector2(4), + } + } + } }, - number = new NumberPiece - { - Text = (HitObject.IndexInCurrentCombo + 1).ToString(), - }, - ring = new RingPiece(), - flash = new FlashPiece(), - explode = new ExplodePiece(), - ApproachCircle = new ApproachCircle - { - Alpha = 0, - Scale = new Vector2(4), - } }; //may not be so correct @@ -72,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(v => Scale = new Vector2(v)); + scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); positionBindable.BindTo(HitObject.PositionBindable); stackHeightBindable.BindTo(HitObject.StackHeightBindable); @@ -81,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; @@ -118,6 +139,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); + ApproachCircle.Expire(true); } protected override void UpdateCurrentState(ArmedState state) @@ -131,6 +153,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); + circle.HitAction = null; + // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; @@ -156,8 +180,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.FadeOut(); number.FadeOut(); - this.FadeOut(800) - .ScaleTo(Scale * 1.5f, 400, Easing.OutQuad); + this.FadeOut(800); + explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); } Expire(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 56c4ea639b..10b37af957 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Rulesets.Objects.Drawables; @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.SkinChanged(skin, allowFallback); if (HitObject is IHasComboInformation combo) - AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; + AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White; } protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 17f6ddd211..938a2293ba 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osuTK; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -16,12 +15,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } - protected override void LoadComplete() + protected override void ApplyHitAnimations() { - if (Result.Type != HitResult.Miss) - JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); - - base.LoadComplete(); + JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); + base.ApplyHitAnimations(); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 8c9252a2da..22d2034fe0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -101,7 +101,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - float aimRotation = MathHelper.RadiansToDegrees((float)Math.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X)); while (Math.Abs(aimRotation - Rotation) > 180) aimRotation += aimRotation < Rotation ? 360 : -360; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index eed9a53ad7..57ea0abdd8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -8,12 +8,13 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; -using osu.Game.Configuration; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Scoring; using osuTK.Graphics; +using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -32,6 +33,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable scaleBindable = new Bindable(); private readonly IBindable pathBindable = new Bindable(); + [Resolved(CanBeNull = true)] + private OsuRulesetConfigManager config { get; set; } + public DrawableSlider(Slider s) : base(s) { @@ -46,12 +50,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Body = new SnakingSliderBody(s) { - PathWidth = s.Scale * 64, + PathRadius = s.Scale * 64, }, ticks = new Container { RelativeSizeAxes = Axes.Both }, repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { + GetInitialHitAction = () => HeadCircle.HitAction, BypassAutoSizeAxes = Axes.Both, Scale = new Vector2(s.Scale), AlwaysPresent = true, @@ -92,16 +97,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load() { - config.BindWith(OsuSetting.SnakingInSliders, Body.SnakingIn); - config.BindWith(OsuSetting.SnakingOutSliders, Body.SnakingOut); + config?.BindWith(OsuRulesetSetting.SnakingInSliders, Body.SnakingIn); + config?.BindWith(OsuRulesetSetting.SnakingOutSliders, Body.SnakingOut); positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(v => + scaleBindable.BindValueChanged(scale => { - Body.PathWidth = HitObject.Scale * 64; - Ball.Scale = new Vector2(HitObject.Scale); + Body.PathRadius = scale.NewValue * 64; + Ball.Scale = new Vector2(scale.NewValue); }); positionBindable.BindTo(HitObject.PositionBindable); @@ -113,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; @@ -151,6 +156,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + + Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? Body.AccentColour; + Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Body.BorderColour; + Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? Ball.AccentColour; + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index f4962f6113..66b6f0f9ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 4ff05d8995..23c5494cf5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 531e6a37af..b5ce36f889 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -20,7 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public override bool DisplayResult => false; - public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) + public DrawableSliderTick(SliderTick sliderTick) + : base(sliderTick) { Size = new Vector2(16) * sliderTick.Scale; Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 8e809306a4..789af4f49b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Graphics; @@ -11,7 +11,7 @@ using osuTK.Graphics; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Screens.Ranking; using osu.Game.Rulesets.Scoring; @@ -42,7 +42,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private Color4 normalColour; private Color4 completeColour; - public DrawableSpinner(Spinner s) : base(s) + public DrawableSpinner(Spinner s) + : base(s) { Origin = Anchor.Centre; Position = s.Position; @@ -130,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Colour = colours.BlueDark; glow.Colour = colours.BlueDark; - positionBindable.BindValueChanged(v => Position = v); + positionBindable.BindValueChanged(pos => Position = pos.NewValue); positionBindable.BindTo(HitObject.PositionBindable); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs index e89ec1775b..b1815b23c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Osu.Objects.Drawables { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs index 23903e1b5e..cae2a7c36d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 07d99bda42..8ee065aaea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,6 +12,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class ApproachCircle : Container { + public override bool RemoveWhenNotAlive => false; + public ApproachCircle() { Anchor = Anchor.Centre; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 1a9acf708a..786cac7198 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Func Hit; + public OsuAction? HitAction; + public CirclePiece() { Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); @@ -35,7 +37,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { case OsuAction.LeftButton: case OsuAction.RightButton: - return IsHovered && (Hit?.Invoke() ?? false); + if (IsHovered && (Hit?.Invoke() ?? false)) + { + HitAction = action; + return true; + } + + break; } return false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs index 86b60c3443..047ff943ff 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 2a2c845143..b960f40578 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index 8880c96e3c..8e5eb886aa 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index 48b78bac40..917695c790 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs index 6f4ccd60a9..d69df1d5c2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ManualSliderBody.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 87ca2f05e1..93ac8748dd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -17,8 +18,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public string Text { - get { return number.Text; } - set { number.Text = value; } + get => number.Text; + set => number.Text = value; } public NumberPiece() @@ -42,9 +43,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }, s => s.GetTexture("Play/osu/hitcircle") == null), number = new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText { - Font = @"Venera", + Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, - TextSize = 40, }, restrictSize: false) { Text = @"1" diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index 75b34959bd..28180a7f71 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 5144ce4e7a..e41c568403 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,12 +20,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private Color4 accentColour = Color4.Black; + public Func GetInitialHitAction; + /// /// The colour that is used for the slider ball. /// public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; @@ -129,15 +132,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces base.ClearTransformsAfter(time, false, targetMember); } + public override void ApplyTransformsAt(double time, bool propagateChildren = false) + { + // For the same reasons as above w.r.t rewinding, we shouldn't propagate to children here either. + base.ApplyTransformsAt(time, false); + } + private bool tracking; public bool Tracking { - get { return tracking; } + get => tracking; private set { if (value == tracking) return; + tracking = value; FollowCircle.ScaleTo(tracking ? 2f : 1, 300, Easing.OutQuint); @@ -145,20 +155,72 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime; + /// + /// If the cursor moves out of the ball's radius we still need to be able to receive positional updates to stop tracking. + /// + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + /// + /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. + /// + /// This is a requirement to stop the case where a player holds down one key (from before the slider) and taps the second key while maintaining full scoring (tracking) of sliders. + /// Visually, this special case can be seen below (time increasing from left to right): + /// + /// Z Z+X Z + /// o========o + /// + /// Without this logic, tracking would continue through the entire slider even though no key hold action is directly attributing to it. + /// + /// In all other cases, no special handling is required (either key being pressed is allowable as valid tracking). + /// + /// The reason for storing this as a time value (rather than a bool) is to correctly handle rewind scenarios. + /// + private double? timeToAcceptAnyKeyAfter; protected override void Update() { base.Update(); - if (Time.Current < slider.EndTime) + // from the point at which the head circle is hit, this will be non-null. + // it may be null if the head circle was missed. + var headCircleHitAction = GetInitialHitAction(); + + if (headCircleHitAction == null) + timeToAcceptAnyKeyAfter = null; + + var actions = drawableSlider?.OsuActionInputManager?.PressedActions; + + // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. + if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) { - // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = canCurrentlyTrack - && lastScreenSpaceMousePosition.HasValue - && ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) - && (drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + var otherKey = headCircleHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton; + + // we can return to accepting all keys if the initial head circle key is the *only* key pressed, or all keys have been released. + if (actions?.Contains(otherKey) != true) + timeToAcceptAnyKeyAfter = Time.Current; } + + Tracking = + // in valid time range + Time.Current >= slider.StartTime && Time.Current < slider.EndTime && + // in valid position range + lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && + // valid action + (actions?.Any(isValidTrackingAction) ?? false); + } + + /// + /// Check whether a given user input is a valid tracking action. + /// + private bool isValidTrackingAction(OsuAction action) + { + bool headCircleHit = GetInitialHitAction().HasValue; + + // if the head circle was hit, we may not yet be allowed to accept any key, so we must use the initial hit action. + if (headCircleHit && (!timeToAcceptAnyKeyAfter.HasValue || Time.Current <= timeToAcceptAnyKeyAfter.Value)) + return action == GetInitialHitAction(); + + return action == OsuAction.LeftButton || action == OsuAction.RightButton; } public void UpdateProgress(double completionProgress) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 4604a00fdd..2f5c326bda 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Graphics; @@ -19,10 +19,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private readonly BufferedContainer container; - public float PathWidth + public float PathRadius { - get => path.PathWidth; - set => path.PathWidth = value; + get => path.PathRadius; + set => path.PathRadius = value; } /// @@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { if (path.AccentColour == value) return; + path.AccentColour = value; container.ForceRedraw(); @@ -56,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { if (path.BorderColour == value) return; + path.BorderColour = value; container.ForceRedraw(); @@ -105,6 +107,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { if (borderColour == value) return; + borderColour = value; InvalidateTexture(); @@ -120,6 +123,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { if (accentColour == value) return; + accentColour = value; InvalidateTexture(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 49c66c4063..73b184bffe 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -54,18 +54,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadeIn, 0, 1) : 1; + double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadeIn, 0, 1) : 1; if (span >= slider.SpanCount() - 1) { if (Math.Min(span, slider.SpanCount() - 1) % 2 == 1) { start = 0; - end = SnakingOut ? spanProgress : 1; + end = SnakingOut.Value ? spanProgress : 1; } else { - start = SnakingOut ? spanProgress : 0; + start = SnakingOut.Value ? spanProgress : 0; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index e2d67f16a9..c982f53c2b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics; @@ -15,10 +15,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Color4 AccentColour { - get - { - return Disc.Colour; - } + get => Disc.Colour; set { Disc.Colour = value; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 59400a71ea..448a2eada7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -17,8 +17,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Color4 AccentColour { - get { return background.AccentColour; } - set { background.AccentColour = value; } + get => background.AccentColour; + set => background.AccentColour = value; } private readonly SpinnerBackground background; @@ -43,12 +43,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; private bool tracking; + public bool Tracking { - get { return tracking; } + get => tracking; set { if (value == tracking) return; + tracking = value; background.FadeTo(tracking ? tracking_alpha : idle_alpha, 100); @@ -56,12 +58,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } private bool complete; + public bool Complete { - get { return complete; } + get => complete; set { if (value == complete) return; + complete = value; updateCompleteTick(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs index 0bdd4296fb..b1d90c49f6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -23,16 +24,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"0", - Font = @"Venera", - TextSize = 24 + Font = OsuFont.Numeric.With(size: 24) }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"SPINS PER MINUTE", - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Y = 30 } }; @@ -42,10 +41,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public double SpinsPerMinute { - get { return spm; } + get => spm; private set { if (value == spm) return; + spm = value; spmText.Text = Math.Truncate(value).ToString(@"#0"); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index cc9bb1975d..f47617bcf6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs index 59b204bdaf..0e29a1dcd8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics.Backgrounds; diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index d1656a9672..d652db0fd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs index 43ec7ae006..7594f7c2e0 100644 --- a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs +++ b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 462df43b65..364c182dd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osuTK; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual Vector2 Position { - get => PositionBindable; + get => PositionBindable.Value; set => PositionBindable.Value = value; } @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Objects public int StackHeight { - get => StackHeightBindable; + get => StackHeightBindable.Value; set => StackHeightBindable.Value = value; } @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects public float Scale { - get => ScaleBindable; + get => ScaleBindable.Value; set => ScaleBindable.Value = value; } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs index 8405498554..add8fd53c7 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitWindows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index c8621cdbcf..63713541b4 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 44185fb83a..1afbacc01e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -1,14 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Caching; -using osu.Framework.Configuration; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -155,115 +154,76 @@ namespace osu.Game.Rulesets.Osu.Objects { base.CreateNestedHitObjects(); - createSliderEnds(); - createTicks(); - createRepeatPoints(); - - if (LegacyLastTickOffset != null) - TailCircle.StartTime = Math.Max(StartTime + Duration / 2, TailCircle.StartTime - LegacyLastTickOffset.Value); - } - - private void createSliderEnds() - { - HeadCircle = new SliderCircle + foreach (var e in + SliderEventGenerator.Generate(StartTime, SpanDuration, Velocity, TickDistance, Path.Distance, this.SpanCount(), LegacyLastTickOffset)) { - StartTime = StartTime, - Position = Position, - Samples = getNodeSamples(0), - SampleControlPoint = SampleControlPoint, - IndexInCurrentCombo = IndexInCurrentCombo, - ComboIndex = ComboIndex, - }; + var firstSample = Samples.Find(s => s.Name == SampleInfo.HIT_NORMAL) + ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + var sampleList = new List(); - TailCircle = new SliderTailCircle(this) - { - StartTime = EndTime, - Position = EndPosition, - IndexInCurrentCombo = IndexInCurrentCombo, - ComboIndex = ComboIndex, - }; - - AddNested(HeadCircle); - AddNested(TailCircle); - } - - private void createTicks() - { - // A very lenient maximum length of a slider for ticks to be generated. - // This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. - const double max_length = 100000; - - var length = Math.Min(max_length, Path.Distance); - var tickDistance = MathHelper.Clamp(TickDistance, 0, length); - - if (tickDistance == 0) return; - - var minDistanceFromEnd = Velocity * 0.01; - - var spanCount = this.SpanCount(); - - for (var span = 0; span < spanCount; span++) - { - var spanStartTime = StartTime + span * SpanDuration; - var reversed = span % 2 == 1; - - for (var d = tickDistance; d <= length; d += tickDistance) - { - if (d > length - minDistanceFromEnd) - break; - - var distanceProgress = d / length; - var timeProgress = reversed ? 1 - distanceProgress : distanceProgress; - - var firstSample = Samples.Find(s => s.Name == SampleInfo.HIT_NORMAL) - ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) - var sampleList = new List(); - - if (firstSample != null) - sampleList.Add(new SampleInfo - { - Bank = firstSample.Bank, - Volume = firstSample.Volume, - Name = @"slidertick", - }); - - AddNested(new SliderTick + if (firstSample != null) + sampleList.Add(new SampleInfo { - SpanIndex = span, - SpanStartTime = spanStartTime, - StartTime = spanStartTime + timeProgress * SpanDuration, - Position = Position + Path.PositionAt(distanceProgress), - StackHeight = StackHeight, - Scale = Scale, - Samples = sampleList + Bank = firstSample.Bank, + Volume = firstSample.Volume, + Name = @"slidertick", }); + + switch (e.Type) + { + case SliderEventType.Tick: + AddNested(new SliderTick + { + SpanIndex = e.SpanIndex, + SpanStartTime = e.SpanStartTime, + StartTime = e.Time, + Position = Position + Path.PositionAt(e.PathProgress), + StackHeight = StackHeight, + Scale = Scale, + Samples = sampleList + }); + break; + case SliderEventType.Head: + AddNested(HeadCircle = new SliderCircle + { + StartTime = e.Time, + Position = Position, + Samples = getNodeSamples(0), + SampleControlPoint = SampleControlPoint, + IndexInCurrentCombo = IndexInCurrentCombo, + ComboIndex = ComboIndex, + }); + break; + case SliderEventType.LegacyLastTick: + // we need to use the LegacyLastTick here for compatibility reasons (difficulty). + // it is *okay* to use this because the TailCircle is not used for any meaningful purpose in gameplay. + // if this is to change, we should revisit this. + AddNested(TailCircle = new SliderTailCircle(this) + { + StartTime = e.Time, + Position = EndPosition, + IndexInCurrentCombo = IndexInCurrentCombo, + ComboIndex = ComboIndex, + }); + break; + case SliderEventType.Repeat: + AddNested(new RepeatPoint + { + RepeatIndex = e.SpanIndex, + SpanDuration = SpanDuration, + StartTime = StartTime + (e.SpanIndex + 1) * SpanDuration, + Position = Position + Path.PositionAt(e.PathProgress), + StackHeight = StackHeight, + Scale = Scale, + Samples = getNodeSamples(e.SpanIndex + 1) + }); + break; } } } - private void createRepeatPoints() - { - for (int repeatIndex = 0, repeat = 1; repeatIndex < RepeatCount; repeatIndex++, repeat++) - { - AddNested(new RepeatPoint - { - RepeatIndex = repeatIndex, - SpanDuration = SpanDuration, - StartTime = StartTime + repeat * SpanDuration, - Position = Position + Path.PositionAt(repeat % 2), - StackHeight = StackHeight, - Scale = Scale, - Samples = getNodeSamples(1 + repeatIndex) - }); - } - } - - private List getNodeSamples(int nodeIndex) - { - if (nodeIndex < NodeSamples.Count) - return NodeSamples[nodeIndex]; - return Samples; - } + private List getNodeSamples(int nodeIndex) => + nodeIndex < NodeSamples.Count ? NodeSamples[nodeIndex] : Samples; public override Judgement CreateJudgement() => new OsuJudgement(); } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs index deda951378..151902a752 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderCircle.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Osu.Objects { diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 74a7a8d446..4f2af64161 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,13 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { + /// + /// Note that this should not be used for timing correctness. + /// See usage in for more information. + /// public class SliderTailCircle : SliderCircle { private readonly IBindable pathBindable = new Bindable(); diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 906f0a0182..85439699dd 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 1c60fd4831..8a2fd3b7aa 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index e2f4c43a23..b9e083d35b 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.ComponentModel; @@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Osu protected override bool Handle(UIEvent e) { if (!AllowUserPresses) return false; + return base.Handle(e); } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 5cfc24bdde..7d3aff7801 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -13,11 +13,15 @@ using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Difficulty; using osu.Game.Scoring; @@ -25,7 +29,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new OsuRulesetContainer(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableOsuRuleset(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap); @@ -82,6 +86,9 @@ namespace osu.Game.Rulesets.Osu if (mods.HasFlag(LegacyMods.Target)) yield return new OsuModTarget(); + + if (mods.HasFlag(LegacyMods.TouchDevice)) + yield return new OsuModTouchDevice(); } public override IEnumerable GetModsFor(ModType type) @@ -118,9 +125,12 @@ namespace osu.Game.Rulesets.Osu new OsuModAutopilot(), }; case ModType.Fun: - return new Mod[] { + return new Mod[] + { new OsuModTransform(), new OsuModWiggle(), + new OsuModGrow(), + new MultiMod(new ModWindUp(), new ModWindDown()), }; default: return new Mod[] { }; @@ -139,12 +149,14 @@ namespace osu.Game.Rulesets.Osu public override string ShortName => "osu"; - public override RulesetSettingsSubsection CreateSettings() => new OsuSettings(this); + public override RulesetSettingsSubsection CreateSettings() => new OsuSettingsSubsection(this); public override int? LegacyID => 0; public override IConvertibleReplayFrame CreateConvertibleReplayFrame() => new OsuReplayFrame(); + public override IRulesetConfigManager CreateConfig(SettingsStore settings) => new OsuRulesetConfigManager(settings, RulesetInfo); + public OsuRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { diff --git a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs index b61c53be6a..b9a7096330 100644 --- a/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Osu.Tests.iOS")] diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index eda5be1f0f..c1aaa7767e 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.MathUtils; @@ -10,12 +10,15 @@ using System.Linq; using osu.Framework.Graphics; using osu.Game.Replays; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Replays { public class OsuAutoGenerator : OsuAutoGeneratorBase { + public new OsuBeatmap Beatmap => (OsuBeatmap)base.Beatmap; + #region Parameters /// @@ -42,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Replays #region Construction / Initialisation - public OsuAutoGenerator(Beatmap beatmap) + public OsuAutoGenerator(IBeatmap beatmap) : base(beatmap) { // Already superhuman, but still somewhat realistic @@ -209,7 +212,7 @@ namespace osu.Game.Rulesets.Osu.Replays // Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up. if (timeDifference > 0 && // Sanity checks ((lastPosition - targetPos).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough - timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. + timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. { // Perform eased movement for (double time = lastFrame.Time + FrameDelay; time < h.StartTime; time += FrameDelay) diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 6dc5e42258..9ab358ee12 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -1,9 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Osu.Objects; using System; using System.Collections.Generic; using osu.Game.Replays; @@ -12,7 +11,7 @@ using osu.Game.Rulesets.Replays; namespace osu.Game.Rulesets.Osu.Replays { - public abstract class OsuAutoGeneratorBase : AutoGenerator + public abstract class OsuAutoGeneratorBase : AutoGenerator { #region Constants @@ -20,6 +19,7 @@ namespace osu.Game.Rulesets.Osu.Replays /// Constants (for spinners). /// protected static readonly Vector2 SPINNER_CENTRE = OsuPlayfield.BASE_SIZE / 2; + protected const float SPIN_RADIUS = 50; /// @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Replays protected Replay Replay; protected List Frames => Replay.Frames; - protected OsuAutoGeneratorBase(Beatmap beatmap) + protected OsuAutoGeneratorBase(IBeatmap beatmap) : base(beatmap) { Replay = new Replay(); @@ -46,6 +46,7 @@ namespace osu.Game.Rulesets.Osu.Replays #endregion #region Utilities + protected double ApplyModsToTime(double v) => v; protected double ApplyModsToRate(double v) => v; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs similarity index 79% rename from osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs rename to osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index 7806e88b5c..d1ac77857d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -11,9 +11,9 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Replays { - public class OsuReplayInputHandler : FramedReplayInputHandler + public class OsuFramedReplayInputHandler : FramedReplayInputHandler { - public OsuReplayInputHandler(Replay replay) + public OsuFramedReplayInputHandler(Replay replay) : base(replay) { } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 74250fb92d..4d90fcadd5 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/diffcalc-test.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/diffcalc-test.osu new file mode 100644 index 0000000000..bf345811a2 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/diffcalc-test.osu @@ -0,0 +1,179 @@ +osu file format v14 + +[General] +StackLeniency: 0.3 +Mode: 0 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +62500,-500,4,2,1,50,0,0 +71000,-100,4,2,1,50,0,0 + +[HitObjects] +// Circles spaced 1 beat apart, with increasing jump distance +126,112,500,5,0,0:0:0:0: +130,155,1000,1,0,0:0:0:0: +131,269,1500,1,0,0:0:0:0: +341,269,2000,1,0,0:0:0:0: +113,95,2500,1,0,0:0:0:0: + +// Circles spaced 1/2 beat apart, with increasing jump distance +108,104,3500,5,0,0:0:0:0: +110,145,3750,1,0,0:0:0:0: +115,262,4000,1,0,0:0:0:0: +285,265,4250,1,0,0:0:0:0: +458,48,4500,1,0,0:0:0:0: +35,199,4750,1,0,0:0:0:0: +251,340,5000,1,0,0:0:0:0: +20,352,5250,1,0,0:0:0:0: +426,62,5500,1,0,0:0:0:0: + +// Circles spaced 1/4 beat apart, with increasing jump distances +211,138,6500,5,0,0:0:0:0: +99,256,6625,1,0,0:0:0:0: +68,129,6750,1,0,0:0:0:0: +371,340,6875,1,0,0:0:0:0: +241,219,7000,1,0,0:0:0:0: +252,148,7125,1,0,0:0:0:0: +434,97,7250,1,0,0:0:0:0: +40,38,7375,1,0,0:0:0:0: +114,334,7500,1,0,0:0:0:0: +301,19,7625,1,0,0:0:0:0: +441,241,7750,1,0,0:0:0:0: +121,91,7875,1,0,0:0:0:0: +270,384,8000,1,0,0:0:0:0: +488,92,8125,1,0,0:0:0:0: +332,82,8250,1,0,0:0:0:0: +108,240,8375,1,0,0:0:0:0: +281,268,8500,1,0,0:0:0:0: + +// Constant spaced circles spaced 1/2 beat apart, small jump distances, changing angles +252,191,9500,5,0,0:0:0:0: +356,191,9750,1,0,0:0:0:0: +311,268,10000,1,0,0:0:0:0: +190,270,10250,1,0,0:0:0:0: +107,199,10500,1,0,0:0:0:0: +172,105,10750,1,0,0:0:0:0: +297,102,11000,1,0,0:0:0:0: +373,178,11250,1,0,0:0:0:0: +252,195,11500,1,0,0:0:0:0: + +// Constant spaced circles spaced 1/2 beat apart, large jump distances, changing angles +140,187,12500,5,0,0:0:0:0: +451,331,12750,1,0,0:0:0:0: +46,338,13000,1,0,0:0:0:0: +204,50,13250,1,0,0:0:0:0: +464,162,13500,1,0,0:0:0:0: +252,346,13750,1,0,0:0:0:0: +13,175,14000,1,0,0:0:0:0: +488,181,14250,1,0,0:0:0:0: +251,187,14500,1,0,0:0:0:0: + +// Constant spaced circles spaced 1/4 beat apart, small jump distances, changing angles +188,192,15500,5,0,0:0:0:0: +298,194,15625,1,0,0:0:0:0: +317,84,15750,1,0,0:0:0:0: +185,85,15875,1,0,0:0:0:0: +77,200,16000,1,0,0:0:0:0: +184,303,16125,1,0,0:0:0:0: +295,225,16250,1,0,0:0:0:0: +300,84,16375,1,0,0:0:0:0: +144,82,16500,1,0,0:0:0:0: +141,215,16625,1,0,0:0:0:0: +314,184,16750,1,0,0:0:0:0: +188,192,16875,1,0,0:0:0:0: +188,192,17000,1,0,0:0:0:0: + +// Constant spaced circles spaced 1/4 beat apart, large jump distances, changing angles +97,192,18000,5,0,0:0:0:0: +336,38,18125,1,0,0:0:0:0: +440,322,18250,1,0,0:0:0:0: +39,331,18375,1,0,0:0:0:0: +98,39,18500,1,0,0:0:0:0: +460,179,18625,1,0,0:0:0:0: +245,338,18750,1,0,0:0:0:0: +12,184,18875,1,0,0:0:0:0: +250,41,19000,1,0,0:0:0:0: +265,193,19125,1,0,0:0:0:0: +486,22,19250,1,0,0:0:0:0: +411,205,19375,1,0,0:0:0:0: +107,198,19500,1,0,0:0:0:0: + +// Short sliders spaced 1 beat apart +28,108,20500,2,0,L|196:107,1,160 +25,177,21500,2,0,L|193:176,1,160 +26,308,22500,2,0,L|194:307,1,160 +320,89,23500,2,0,L|488:88,1,160 + +// Short sliders spaced 1/2 beat apart +28,108,25000,6,0,L|196:107,1,160 +27,173,25750,2,0,L|195:172,1,160 +25,292,26500,2,0,L|193:291,1,160 +340,213,27250,2,0,L|508:212,1,160 +21,44,28000,2,0,L|189:43,1,160 + +// Short sliders spaced 1/4 beat apart +28,108,29500,6,0,L|196:107,1,160 +30,169,30125,2,0,L|198:168,1,160 +35,282,30750,2,0,L|203:281,1,160 +327,286,31375,2,0,L|495:285,1,160 +51,61,32000,2,0,L|219:60,1,160 + +// Large, medium-paced slider shapes +// PerfectCurve +66,86,33500,6,0,P|246:348|427:44,1,800 +66,86,36500,2,0,P|246:348|427:44,1,800 +66,86,39500,2,0,P|246:348|427:44,1,800 +// Linear +66,72,42500,2,0,B|419:65|419:65|66:316|66:316|426:318,1,1120 +66,72,46500,2,0,B|419:65|419:65|66:316|66:316|426:318,1,1120 +66,72,50500,2,0,B|419:65|419:65|66:316|66:316|426:318,1,1120 +// Bezier +76,287,54500,2,0,B|440:325|138:128|470:302|500:30|130:85|66:82,1,640 +76,287,57000,2,0,B|440:325|138:128|470:302|500:30|130:85|66:82,1,640 +76,287,59500,2,0,B|440:325|138:128|470:302|500:30|130:85|66:82,1,640 + +// Large slow slider with many ticks +81,170,62500,6,0,P|263:78|168:268,1,480 + +// Fast slider with many repeats +102,152,71000,6,0,L|175:153,18,64 + +// Slider-circle combos, spaced 1/2 beat apart +106,204,75500,6,0,P|275:33|171:304,1,800 +255,179,78250,1,0,0:0:0:0: +106,204,78500,2,0,P|275:33|171:304,1,800 +255,179,81250,1,0,0:0:0:0: +106,204,81500,2,0,P|275:33|171:304,1,800 + +// Circle-spinner combos, spaced 1/2 beat apart +82,69,85000,5,0,0:0:0:0: +256,192,85250,8,0,86000,0:0:0:0: +384,189,86250,5,0,0:0:0:0: +256,192,86500,12,0,87000,0:0:0:0: + +// Spinner-spinner combos, spaced 1/2 beat apart +256,192,88000,12,0,89000,0:0:0:0: +256,192,89250,12,0,90250,0:0:0:0: +256,192,90500,12,0,91500,0:0:0:0: +256,192,91750,12,0,92750,0:0:0:0: +256,192,93000,12,0,94000,0:0:0:0: + +// Slider-spinner combos, spaced 1/2 beat apart +49,89,95000,6,0,L|214:87,1,160 +256,192,95625,12,0,96500,0:0:0:0: +12,299,96625,6,0,L|177:297,1,160 +256,192,97250,12,0,98125,0:0:0:0: +295,107,98250,6,0,L|460:105,1,160 +256,192,98875,12,0,99750,0:0:0:0: +279,325,99875,6,0,L|444:323,1,160 +256,192,100500,12,0,101375,0:0:0:0: +197,197,101500,6,0,L|362:195,1,160 +256,192,102125,12,0,103000,0:0:0:0: diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index a24efe4a1e..2c8bf11016 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Extensions; @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { - public OsuScoreProcessor(RulesetContainer rulesetContainer) - : base(rulesetContainer) + public OsuScoreProcessor(DrawableRuleset drawableRuleset) + : base(drawableRuleset) { } @@ -74,6 +74,6 @@ namespace osu.Game.Rulesets.Osu.Scoring protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); - protected override HitWindows CreateHitWindows() => new OsuHitWindows(); + public override HitWindows CreateHitWindows() => new OsuHitWindows(); } } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index b25b3e5cb8..03dbf7ac63 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Diagnostics; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { private int currentIndex; - private Shader shader; + private IShader shader; private Texture texture; private Vector2 size => texture.Size * Scale; @@ -35,7 +35,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public override bool IsPresent => true; - private readonly TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); private const int max_sprites = 2048; private readonly TrailPart[] parts = new TrailPart[max_sprites]; @@ -55,7 +54,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor tNode.Texture = texture; tNode.Size = size; tNode.Time = time; - tNode.Shared = trailDrawNodeSharedData; for (int i = 0; i < parts.Length; ++i) if (parts[i].InvalidationID > tNode.Parts[i].InvalidationID) @@ -81,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor [BackgroundDependencyLoader] private void load(ShaderManager shaders, TextureStore textures) { - shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); + shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); texture = textures.Get(@"Cursor/cursortrail"); Scale = new Vector2(1 / texture.ScaleAdjust); } @@ -167,22 +165,18 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public bool WasUpdated; } - private class TrailDrawNodeSharedData - { - public VertexBuffer VertexBuffer; - } - private class TrailDrawNode : DrawNode { - public Shader Shader; + public IShader Shader; public Texture Texture; public float Time; - public TrailDrawNodeSharedData Shared; public readonly TrailPart[] Parts = new TrailPart[max_sprites]; public Vector2 Size; + private readonly VertexBuffer vertexBuffer = new QuadVertexBuffer(max_sprites, BufferUsageHint.DynamicDraw); + public TrailDrawNode() { for (int i = 0; i < max_sprites; i++) @@ -194,9 +188,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public override void Draw(Action vertexAction) { - if (Shared.VertexBuffer == null) - Shared.VertexBuffer = new QuadVertexBuffer(max_sprites, BufferUsageHint.DynamicDraw); - Shader.GetUniform("g_FadeClock").UpdateValue(ref Time); int updateStart = -1, updateEnd = 0; @@ -218,7 +209,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), DrawColourInfo.Colour, null, - v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex + v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex { Position = v.Position, TexturePosition = v.TexturePosition, @@ -230,24 +221,31 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } else if (updateStart != -1) { - Shared.VertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); + vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); updateStart = -1; } } // Update all remaining vertices that have been changed. if (updateStart != -1) - Shared.VertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); + vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4); base.Draw(vertexAction); Shader.Bind(); Texture.TextureGL.Bind(); - Shared.VertexBuffer.Draw(); + vertexBuffer.Draw(); Shader.Unbind(); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + vertexBuffer.Dispose(); + } } [StructLayout(LayoutKind.Sequential)] @@ -255,10 +253,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { [VertexMember(2, VertexAttribPointerType.Float)] public Vector2 Position; + [VertexMember(4, VertexAttribPointerType.Float)] public Color4 Colour; + [VertexMember(2, VertexAttribPointerType.Float)] public Vector2 TexturePosition; + [VertexMember(1, VertexAttribPointerType.Float)] public float Time; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs deleted file mode 100644 index 4aa30777e9..0000000000 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.Bindings; -using osu.Game.Beatmaps; -using osu.Game.Configuration; -using osu.Game.Skinning; -using osuTK; -using osuTK.Graphics; - -namespace osu.Game.Rulesets.Osu.UI.Cursor -{ - public class GameplayCursor : CursorContainer, IKeyBindingHandler - { - protected override Drawable CreateCursor() => new OsuCursor(); - - protected override Container Content => fadeContainer; - - private readonly Container fadeContainer; - - public GameplayCursor() - { - InternalChild = fadeContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new CursorTrail { Depth = 1 } - } - }; - } - - private int downCount; - - private const float pressed_scale = 1.2f; - private const float released_scale = 1f; - - private float targetScale => downCount > 0 ? pressed_scale : released_scale; - - public bool OnPressed(OsuAction action) - { - switch (action) - { - case OsuAction.LeftButton: - case OsuAction.RightButton: - downCount++; - ActiveCursor.ScaleTo(released_scale).ScaleTo(targetScale, 100, Easing.OutQuad); - break; - } - - return false; - } - - public bool OnReleased(OsuAction action) - { - switch (action) - { - case OsuAction.LeftButton: - case OsuAction.RightButton: - if (--downCount == 0) - ActiveCursor.ScaleTo(targetScale, 200, Easing.OutQuad); - break; - } - - return false; - } - - public override bool HandlePositionalInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input. - - protected override void PopIn() - { - fadeContainer.FadeTo(1, 300, Easing.OutQuint); - ActiveCursor.ScaleTo(targetScale, 400, Easing.OutQuint); - } - - protected override void PopOut() - { - fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); - ActiveCursor.ScaleTo(targetScale * 0.8f, 450, Easing.OutQuint); - } - - public class OsuCursor : Container - { - private Drawable cursorContainer; - - private Bindable cursorScale; - private Bindable autoCursorScale; - private readonly IBindable beatmap = new Bindable(); - - public OsuCursor() - { - Origin = Anchor.Centre; - Size = new Vector2(42); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config, IBindableBeatmap beatmap) - { - Child = cursorContainer = new SkinnableDrawable("cursor", _ => new CircularContainer - { - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 6, - BorderColour = Color4.White, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Pink.Opacity(0.5f), - Radius = 5, - }, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - BorderThickness = Size.X / 3, - BorderColour = Color4.White.Opacity(0.5f), - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - AlwaysPresent = true, - }, - }, - }, - new CircularContainer - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.1f), - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.White, - }, - }, - }, - } - }, restrictSize: false) - { - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - }; - - this.beatmap.BindTo(beatmap); - this.beatmap.ValueChanged += v => calculateScale(); - - cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); - cursorScale.ValueChanged += v => calculateScale(); - - autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); - autoCursorScale.ValueChanged += v => calculateScale(); - - calculateScale(); - } - - private void calculateScale() - { - float scale = (float)cursorScale.Value; - - if (autoCursorScale && beatmap.Value != null) - { - // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. - scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); - } - - cursorContainer.Scale = new Vector2(scale); - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs new file mode 100644 index 0000000000..8c6723f5be --- /dev/null +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursorContainer.cs @@ -0,0 +1,223 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.UI.Cursor +{ + public class GameplayCursorContainer : CursorContainer, IKeyBindingHandler + { + protected override Drawable CreateCursor() => new OsuCursor(); + + protected override Container Content => fadeContainer; + + private readonly Container fadeContainer; + + public GameplayCursorContainer() + { + InternalChild = fadeContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new CursorTrail { Depth = 1 } + } + }; + } + + private int downCount; + + private void updateExpandedState() + { + if (downCount > 0) + (ActiveCursor as OsuCursor)?.Expand(); + else + (ActiveCursor as OsuCursor)?.Contract(); + } + + public bool OnPressed(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + downCount++; + updateExpandedState(); + break; + } + + return false; + } + + public bool OnReleased(OsuAction action) + { + switch (action) + { + case OsuAction.LeftButton: + case OsuAction.RightButton: + if (--downCount == 0) + updateExpandedState(); + break; + } + + return false; + } + + public override bool HandlePositionalInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input. + + protected override void PopIn() + { + fadeContainer.FadeTo(1, 300, Easing.OutQuint); + ActiveCursor.ScaleTo(1, 400, Easing.OutQuint); + } + + protected override void PopOut() + { + fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); + ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); + } + + public class OsuCursor : SkinReloadableDrawable + { + private bool cursorExpand; + + private Bindable cursorScale; + private Bindable autoCursorScale; + private readonly IBindable beatmap = new Bindable(); + + private Container expandTarget; + private Drawable scaleTarget; + + public OsuCursor() + { + Origin = Anchor.Centre; + Size = new Vector2(28); + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + cursorExpand = skin.GetValue(s => s.CursorExpand ?? true); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config, IBindable beatmap) + { + InternalChild = expandTarget = new Container + { + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Child = scaleTarget = new SkinnableDrawable("cursor", _ => new CircularContainer + { + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = Size.X / 6, + BorderColour = Color4.White, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Pink.Opacity(0.5f), + Radius = 5, + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = Size.X / 3, + BorderColour = Color4.White.Opacity(0.5f), + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true, + }, + }, + }, + new CircularContainer + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.1f), + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + }, + }, + } + }, restrictSize: false) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + } + }; + + this.beatmap.BindTo(beatmap); + this.beatmap.ValueChanged += _ => calculateScale(); + + cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); + cursorScale.ValueChanged += _ => calculateScale(); + + autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); + autoCursorScale.ValueChanged += _ => calculateScale(); + + calculateScale(); + } + + private void calculateScale() + { + float scale = (float)cursorScale.Value; + + if (autoCursorScale.Value && beatmap.Value != null) + { + // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. + scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); + } + + scaleTarget.Scale = new Vector2(scale); + } + + private const float pressed_scale = 1.2f; + private const float released_scale = 1f; + + public void Expand() + { + if (!cursorExpand) return; + + expandTarget.ScaleTo(released_scale).ScaleTo(pressed_scale, 100, Easing.OutQuad); + } + + public void Contract() => expandTarget.ScaleTo(released_scale, 100, Easing.OutQuad); + } + } +} diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs similarity index 69% rename from osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs rename to osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs index c0e6eae494..b632e0fb05 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/DrawableOsuRuleset.cs @@ -1,26 +1,27 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.UI { - public class OsuRulesetContainer : RulesetContainer + public class DrawableOsuRuleset : DrawableRuleset { - public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + protected new OsuRulesetConfigManager Config => (OsuRulesetConfigManager)base.Config; + + public DrawableOsuRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } @@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); public override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { @@ -46,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.UI return null; } - protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay); + protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuFramedReplayInputHandler(replay); public override double GameplayStartTime { @@ -56,7 +57,5 @@ namespace osu.Game.Rulesets.Osu.UI return first.StartTime - first.TimePreempt; } } - - protected override CursorContainer CreateCursor() => new GameplayCursor(); } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 3399fdb9a0..51733c3c01 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -10,18 +10,26 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; using osu.Game.Rulesets.UI; using System.Linq; +using osu.Framework.Graphics.Cursor; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.UI.Cursor; namespace osu.Game.Rulesets.Osu.UI { public class OsuPlayfield : Playfield { - private readonly Container approachCircles; + private readonly ApproachCircleProxyContainer approachCircles; private readonly JudgementContainer judgementLayer; private readonly ConnectionRenderer connectionLayer; public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); + private readonly PlayfieldAdjustmentContainer adjustmentContainer; + + protected override Container CursorTargetContainer => adjustmentContainer; + + protected override CursorContainer CreateCursor() => new GameplayCursorContainer(); + public OsuPlayfield() { Anchor = Anchor.Centre; @@ -29,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.UI Size = new Vector2(0.75f); - InternalChild = new PlayfieldAdjustmentContainer + InternalChild = adjustmentContainer = new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -45,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.UI Depth = 1, }, HitObjectContainer, - approachCircles = new Container + approachCircles = new ApproachCircleProxyContainer { RelativeSizeAxes = Axes.Both, Depth = -1, @@ -58,13 +66,26 @@ namespace osu.Game.Rulesets.Osu.UI { h.OnNewResult += onNewResult; - var c = h as IDrawableHitObjectWithProxiedApproach; - if (c != null) - approachCircles.Add(c.ProxiedLayer.CreateProxy()); + if (h is IDrawableHitObjectWithProxiedApproach c) + { + var original = c.ProxiedLayer; + + // Hitobjects only have lifetimes set on LoadComplete. For nested hitobjects (e.g. SliderHeads), this only happens when the parenting slider becomes visible. + // This delegation is required to make sure that the approach circles for those not-yet-loaded objects aren't added prematurely. + original.OnLoadComplete += addApproachCircleProxy; + } base.Add(h); } + private void addApproachCircleProxy(Drawable d) + { + var proxy = d.CreateProxy(); + proxy.LifetimeStart = d.LifetimeStart; + proxy.LifetimeEnd = d.LifetimeEnd; + approachCircles.Add(proxy); + } + public override void PostProcess() { connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); @@ -72,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.UI private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayResult || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements.Value) return; DrawableOsuJudgement explosion = new DrawableOsuJudgement(result, judgedObject) @@ -86,5 +107,10 @@ namespace osu.Game.Rulesets.Osu.UI } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos); + + private class ApproachCircleProxyContainer : LifetimeManagementContainer + { + public void Add(Drawable approachCircleProxy) => AddInternal(approachCircleProxy); + } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettings.cs b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs similarity index 51% rename from osu.Game.Rulesets.Osu/UI/OsuSettings.cs rename to osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs index 25c009b117..ce3432c73d 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettings.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs @@ -1,36 +1,38 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Configuration; using osu.Game.Overlays.Settings; +using osu.Game.Rulesets.Osu.Configuration; namespace osu.Game.Rulesets.Osu.UI { - public class OsuSettings : RulesetSettingsSubsection + public class OsuSettingsSubsection : RulesetSettingsSubsection { protected override string Header => "osu!"; - public OsuSettings(Ruleset ruleset) + public OsuSettingsSubsection(Ruleset ruleset) : base(ruleset) { } [BackgroundDependencyLoader] - private void load(OsuConfigManager config) + private void load() { + var config = (OsuRulesetConfigManager)Config; + Children = new Drawable[] { new SettingsCheckbox { LabelText = "Snaking in sliders", - Bindable = config.GetBindable(OsuSetting.SnakingInSliders) + Bindable = config.GetBindable(OsuRulesetSetting.SnakingInSliders) }, new SettingsCheckbox { LabelText = "Snaking out sliders", - Bindable = config.GetBindable(OsuSetting.SnakingOutSliders) + Bindable = config.GetBindable(OsuRulesetSetting.SnakingOutSliders) }, }; } diff --git a/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs index df5bd84e75..c383c47491 100644 --- a/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/PlayfieldAdjustmentContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs new file mode 100644 index 0000000000..567220f316 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/AppDelegate.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; +using osu.Game.Tests; + +namespace osu.Game.Rulesets.Taiko.Tests.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs new file mode 100644 index 0000000000..6613e9e2b4 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.Game.Rulesets.Taiko.Tests.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Entitlements.plist b/osu.Game.Rulesets.Taiko.Tests.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist new file mode 100644 index 0000000000..5fe822946a --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleName + osu.Game.Rulesets.Taiko.Tests.iOS + CFBundleIdentifier + ppy.osu-Game-Rulesets-Taiko-Tests-iOS + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj new file mode 100644 index 0000000000..d2817b743c --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests.iOS/osu.Game.Rulesets.Taiko.Tests.iOS.csproj @@ -0,0 +1,45 @@ + + + + + Debug + iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A} + Exe + osu.Game.Rulesets.Taiko.Tests + osu.Game.Rulesets.Taiko.Tests.iOS + + + + + + + libbass.a + PreserveNewest + + + libbass_fx.a + PreserveNewest + + + Linker.xml + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {F167E17A-7DE6-4AF5-B920-A5112296C695} + osu.Game.Rulesets.Taiko + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index db8480c742..68ae7544c2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs new file mode 100644 index 0000000000..e7b6d8615b --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs @@ -0,0 +1,25 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Taiko.Difficulty; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TaikoDifficultyCalculatorTest : DifficultyCalculatorTest + { + protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; + + [TestCase(2.9811338051242915d, "diffcalc-test")] + [TestCase(2.9811338051242915d, "diffcalc-test-strong")] + public void Test(double expected, string name) + => base.Test(expected, name); + + protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(new TaikoRuleset(), beatmap); + + protected override Ruleset CreateRuleset() => new TaikoRuleset(); + } +} diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs index b88aea0bbd..136d9067d5 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseInputDrum.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index dad7f34e71..369cdd49d2 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override double TimePerAction => default_duration * 2; private readonly Random rng = new Random(1337); - private TaikoRulesetContainer rulesetContainer; + private DrawableTaikoRuleset drawableRuleset; private Container playfieldContainer; [BackgroundDependencyLoader] @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Ruleset = new TaikoRuleset().RulesetInfo }, ControlPointInfo = controlPointInfo - }); + }, Clock); Add(playfieldContainer = new Container { @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 768, - Children = new[] { rulesetContainer = new TaikoRulesetContainer(new TaikoRuleset(), beatmap) } + Children = new[] { drawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap) } }); } @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); } private void addStrongHitJudgement(bool kiai) @@ -154,33 +154,33 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() { - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) { - BarLine bl = new BarLine { StartTime = rulesetContainer.Playfield.Time.Current + delay }; + BarLine bl = new BarLine { StartTime = drawableRuleset.Playfield.Time.Current + delay }; - rulesetContainer.Playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); + drawableRuleset.Playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); } private void addSwell(double duration = default_duration) { var swell = new Swell { - StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, + StartTime = drawableRuleset.Playfield.Time.Current + scroll_time, Duration = duration, }; swell.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - rulesetContainer.Playfield.Add(new DrawableSwell(swell)); + drawableRuleset.Playfield.Add(new DrawableSwell(swell)); } private void addDrumRoll(bool strong, double duration = default_duration) @@ -190,40 +190,40 @@ namespace osu.Game.Rulesets.Taiko.Tests var d = new DrumRoll { - StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, + StartTime = drawableRuleset.Playfield.Time.Current + scroll_time, IsStrong = strong, Duration = duration, }; d.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - rulesetContainer.Playfield.Add(new DrawableDrumRoll(d)); + drawableRuleset.Playfield.Add(new DrawableDrumRoll(d)); } private void addCentreHit(bool strong) { Hit h = new Hit { - StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, + StartTime = drawableRuleset.Playfield.Time.Current + scroll_time, IsStrong = strong }; h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - rulesetContainer.Playfield.Add(new DrawableCentreHit(h)); + drawableRuleset.Playfield.Add(new DrawableCentreHit(h)); } private void addRimHit(bool strong) { Hit h = new Hit { - StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, + StartTime = drawableRuleset.Playfield.Time.Current + scroll_time, IsStrong = strong }; h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - rulesetContainer.Playfield.Add(new DrawableRimHit(h)); + drawableRuleset.Playfield.Add(new DrawableRimHit(h)); } private class TestStrongNestedHit : DrawableStrongNestedHit diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 0fc01deed6..72ce6c947b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,9 +2,9 @@ - + - + diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index 91aafdae76..d7fa661e8a 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs index 36f6df7869..2bc39a1c58 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index c4a84f416e..3e0e2624bf 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs new file mode 100644 index 0000000000..24345275c1 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing +{ + public class TaikoDifficultyHitObject : DifficultyHitObject + { + public readonly bool HasTypeChange; + + public TaikoDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) + { + HasTypeChange = lastObject is RimHit != hitObject is RimHit; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs new file mode 100644 index 0000000000..c6fe273b50 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs @@ -0,0 +1,95 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Difficulty.Skills +{ + public class Strain : Skill + { + private const double rhythm_change_base_threshold = 0.2; + private const double rhythm_change_base = 2.0; + + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.3; + + private ColourSwitch lastColourSwitch = ColourSwitch.None; + + private int sameColourCount = 1; + + protected override double StrainValueOf(DifficultyHitObject current) + { + double addition = 1; + + // We get an extra addition if we are not a slider or spinner + if (current.LastObject is Hit && current.BaseObject is Hit && current.DeltaTime < 1000) + { + if (hasColourChange(current)) + addition += 0.75; + + if (hasRhythmChange(current)) + addition += 1; + } + else + { + lastColourSwitch = ColourSwitch.None; + sameColourCount = 1; + } + + double additionFactor = 1; + + // Scale the addition factor linearly from 0.4 to 1 for DeltaTime from 0 to 50 + if (current.DeltaTime < 50) + additionFactor = 0.4 + 0.6 * current.DeltaTime / 50; + + return additionFactor * addition; + } + + private bool hasRhythmChange(DifficultyHitObject current) + { + // We don't want a division by zero if some random mapper decides to put two HitObjects at the same time. + if (current.DeltaTime == 0 || Previous.Count == 0 || Previous[0].DeltaTime == 0) + return false; + + double timeElapsedRatio = Math.Max(Previous[0].DeltaTime / current.DeltaTime, current.DeltaTime / Previous[0].DeltaTime); + + if (timeElapsedRatio >= 8) + return false; + + double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0; + + return difference > rhythm_change_base_threshold && difference < 1 - rhythm_change_base_threshold; + } + + private bool hasColourChange(DifficultyHitObject current) + { + var taikoCurrent = (TaikoDifficultyHitObject)current; + + if (!taikoCurrent.HasTypeChange) + { + sameColourCount++; + return false; + } + + var oldColourSwitch = lastColourSwitch; + var newColourSwitch = sameColourCount % 2 == 0 ? ColourSwitch.Even : ColourSwitch.Odd; + + lastColourSwitch = newColourSwitch; + sameColourCount = 1; + + // We only want a bonus if the parity of the color switch changes + return oldColourSwitch != ColourSwitch.None && oldColourSwitch != newColourSwitch; + } + + private enum ColourSwitch + { + None, + Even, + Odd + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index d18d03b1db..75d3807bba 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Difficulty { @@ -10,10 +9,5 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { public double GreatHitWindow; public int MaxCombo; - - public TaikoDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 8b527c2c82..685ad9949b 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -1,137 +1,51 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; +using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty { - internal class TaikoDifficultyCalculator : DifficultyCalculator + public class TaikoDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.04125; - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 400; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.9; - public TaikoDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new TaikoDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new TaikoDifficultyAttributes { Mods = mods }; - var difficultyHitObjects = new List(); - - foreach (var hitObject in beatmap.HitObjects) - difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject)); - - // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. - difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new DifficultyAttributes(mods, 0); - - double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - - return new TaikoDifficultyAttributes(mods, starRating) + return new TaikoDifficultyAttributes { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate, - MaxCombo = beatmap.HitObjects.Count(h => h is Hit) + StarRating = skills.Single().DifficultyValue() * star_scaling_factor, + Mods = mods, + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, + MaxCombo = beatmap.HitObjects.Count(h => h is Hit), }; } - private bool calculateStrainValues(List objects, double timeRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (var hitObjectsEnumerator = objects.GetEnumerator()) - { - if (!hitObjectsEnumerator.MoveNext()) return false; - - TaikoHitObjectDifficulty current = hitObjectsEnumerator.Current; - - // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. - while (hitObjectsEnumerator.MoveNext()) - { - var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, timeRate); - current = next; - } - - return true; - } + for (int i = 1; i < beatmap.HitObjects.Count; i++) + yield return new TaikoDifficultyHitObject(beatmap.HitObjects[i], beatmap.HitObjects[i - 1], clockRate); } - private double calculateDifficulty(List objects, double timeRate) - { - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - List highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - TaikoHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double decay = Math.Pow(TaikoHitObjectDifficulty.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.Strain * decay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - maximumStrain = Math.Max(hitObject.Strain, maximumStrain); - - previousHitObject = hitObject; - } - - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= decay_weight; - } - - return difficulty; - } + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] { new Strain() }; protected override Mod[] DifficultyAdjustmentMods => new Mod[] { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index e4960c9680..70249db0f6 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 8c88d6d073..e5ebd5c647 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index e11bdf225f..32d4b77ca4 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 4f397cda09..427d38aaa7 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index 81dfaf4cc3..e045ea324f 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index 024e0e618f..f0f621d12b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs index 448c16dad6..b28b6a0d17 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index 62111ae74a..5b890b3d03 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModAutoplay : ModAutoplay { - protected override Score CreateReplayScore(Beatmap beatmap) => new Score + public override Score CreateReplayScore(IBeatmap beatmap) => new Score { ScoreInfo = new ScoreInfo { User = new User { Username = "mekkadosu!" } }, Replay = new TaikoAutoGenerator(beatmap).Generate(), diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs index 80d8da6cf6..84aa5e6bba 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs index 21e48f2c8c..bc38213acc 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs index 16364964f8..c51b47dc6e 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index 79dad84696..b7db3307ad 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; @@ -21,10 +22,10 @@ namespace osu.Game.Rulesets.Taiko.Mods private TaikoPlayfield playfield; - public override void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public override void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - playfield = (TaikoPlayfield)rulesetContainer.Playfield; - base.ApplyToRulesetContainer(rulesetContainer); + playfield = (TaikoPlayfield)drawableRuleset.Playfield; + base.ApplyToDrawableRuleset(drawableRuleset); } private class TaikoFlashlight : Flashlight @@ -48,9 +49,9 @@ namespace osu.Game.Rulesets.Taiko.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs index ef609b893d..68d6305fbf 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs index 908778d4d6..49d225cdb5 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs index f4e12ede21..502dd54e9e 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs index abe4b2e25e..e45081b6d6 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs index 5a8e903fc6..bf1006f1aa 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs index 027feed112..b107b14a03 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs index fd72291f1f..7be70d9ac3 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs index 6ed1ad3bda..7a0f6c7cd1 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index f7496642dd..a07012fd71 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs index 898c562ea9..a6354b16ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index d6f8522b77..5e4c6edb43 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 3a1b4e33d2..4d3a1a3f8a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs index a6e9972dd3..4979135f50 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 632dff4525..9b4df74a61 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index a70d7bde0e..9259c693d9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index d4f0360b40..d3837946c9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs index 188cafe1db..5a12d71cea 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs index b27de3832a..98a2e8a721 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 153e5733e5..9211eccc40 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -229,6 +229,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables // Ensure alternating centre and rim hits if (lastWasCentre == isCentre) return false; + lastWasCentre = isCentre; UpdateResult(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 0a73474cf3..41a8fd9a75 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index cee9b40730..5f755c7cc3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Input.Bindings; @@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected void ProxyContent() { if (isProxied) return; + isProxied = true; nonProxiedContent.Remove(Content); @@ -62,6 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected void UnproxyContent() { if (!isProxied) return; + isProxied = false; proxiedContent.Remove(Content); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs index b4cb3a35f6..7ed61ede96 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index fdb73235de..53dbe5d08e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces /// public override Color4 AccentColour { - get { return base.AccentColour; } + get => base.AccentColour; set { base.AccentColour = value; @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces /// public override bool KiaiMode { - get { return base.KiaiMode; } + get => base.KiaiMode; set { base.KiaiMode = value; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs index c5b8228439..7e3272e42b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs index 613d8debb5..e4c964a884 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs index 8455f4af58..f8dcaa0b45 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs index 6795338a83..773e3ae907 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osuTK.Graphics; @@ -11,26 +11,25 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces public class TaikoPiece : BeatSyncedContainer, IHasAccentColour { private Color4 accentColour; + /// /// The colour of the inner circle and outer glows. /// public virtual Color4 AccentColour { - get { return accentColour; } - set { accentColour = value; } + get => accentColour; + set => accentColour = value; } private bool kiaiMode; + /// /// Whether Kiai mode effects are enabled for this circle piece. /// public virtual bool KiaiMode { - get { return kiaiMode; } - set - { - kiaiMode = value; - } + get => kiaiMode; + set => kiaiMode = value; } public TaikoPiece() diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs index 7327b9c565..83cf7a64ec 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,9 +23,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces private const float tick_size = 0.35f; private bool filled; + public bool Filled { - get { return filled; } + get => filled; set { filled = value; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 89d0512e9c..6f3bdca6fb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; using System; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 967d5acfd7..8448036f76 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 0b47aa490b..6cc9357580 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/RimHit.cs b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs index 2e52e57f1f..6f6b089e03 100644 --- a/osu.Game.Rulesets.Taiko/Objects/RimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index fac3705110..2a03c23934 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 68433429c6..befa728570 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Rulesets.Objects.Types; @@ -19,7 +19,10 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public int RequiredHits = 10; - public override bool IsStrong { set => throw new NotSupportedException($"{nameof(Swell)} cannot be a strong hitobject."); } + public override bool IsStrong + { + set => throw new NotSupportedException($"{nameof(Swell)} cannot be a strong hitobject."); + } protected override void CreateNestedHitObjects() { diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 38f77fa1e7..c2ae784b2a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 9c86b60688..3592d73004 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs deleted file mode 100644 index 70a516af79..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; - -namespace osu.Game.Rulesets.Taiko.Objects -{ - internal class TaikoHitObjectDifficulty - { - /// - /// Factor by how much individual / overall strain decays per second. - /// - /// - /// These values are results of tweaking a lot and taking into account general feedback. - /// - internal const double DECAY_BASE = 0.30; - - private const double type_change_bonus = 0.75; - private const double rhythm_change_bonus = 1.0; - private const double rhythm_change_base_threshold = 0.2; - private const double rhythm_change_base = 2.0; - - internal TaikoHitObject BaseHitObject; - - /// - /// Measures note density in a way - /// - internal double Strain = 1; - - private double timeElapsed; - private int sameTypeSince = 1; - - private bool isRim => BaseHitObject is RimHit; - - public TaikoHitObjectDifficulty(TaikoHitObject baseHitObject) - { - BaseHitObject = baseHitObject; - } - - internal void CalculateStrains(TaikoHitObjectDifficulty previousHitObject, double timeRate) - { - // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. - // See Taiko feedback thread. - timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); - - double addition = 1; - - // Only if we are no slider or spinner we get an extra addition - if (previousHitObject.BaseHitObject is Hit && BaseHitObject is Hit - && BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime < 1000) // And we only want to check out hitobjects which aren't so far in the past - { - addition += typeChangeAddition(previousHitObject); - addition += rhythmChangeAddition(previousHitObject); - } - - double additionFactor = 1.0; - // Scale AdditionFactor linearly from 0.4 to 1 for TimeElapsed from 0 to 50 - if (timeElapsed < 50.0) - additionFactor = 0.4 + 0.6 * timeElapsed / 50.0; - - Strain = previousHitObject.Strain * decay + addition * additionFactor; - } - - private TypeSwitch lastTypeSwitchEven = TypeSwitch.None; - private double typeChangeAddition(TaikoHitObjectDifficulty previousHitObject) - { - // If we don't have the same hit type, trigger a type change! - if (previousHitObject.isRim != isRim) - { - lastTypeSwitchEven = previousHitObject.sameTypeSince % 2 == 0 ? TypeSwitch.Even : TypeSwitch.Odd; - - // We only want a bonus if the parity of the type switch changes! - switch (previousHitObject.lastTypeSwitchEven) - { - case TypeSwitch.Even: - if (lastTypeSwitchEven == TypeSwitch.Odd) - return type_change_bonus; - break; - case TypeSwitch.Odd: - if (lastTypeSwitchEven == TypeSwitch.Even) - return type_change_bonus; - break; - } - } - // No type change? Increment counter and keep track of last type switch - else - { - lastTypeSwitchEven = previousHitObject.lastTypeSwitchEven; - sameTypeSince = previousHitObject.sameTypeSince + 1; - } - - return 0; - } - - private double rhythmChangeAddition(TaikoHitObjectDifficulty previousHitObject) - { - // We don't want a division by zero if some random mapper decides to put 2 HitObjects at the same time. - if (timeElapsed == 0 || previousHitObject.timeElapsed == 0) - return 0; - - double timeElapsedRatio = Math.Max(previousHitObject.timeElapsed / timeElapsed, timeElapsed / previousHitObject.timeElapsed); - - if (timeElapsedRatio >= 8) - return 0; - - double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0; - - if (isWithinChangeThreshold(difference)) - return rhythm_change_bonus; - - return 0; - } - - private bool isWithinChangeThreshold(double value) - { - return value > rhythm_change_base_threshold && value < 1 - rhythm_change_base_threshold; - } - - private enum TypeSwitch - { - None, - Even, - Odd - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs index 9199e6f141..ce841fff80 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitWindows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs index 26f70bc927..81f15fb293 100644 --- a/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests")] [assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Rulesets.Taiko.Tests.iOS")] diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index 2794a3c166..01ba53e07b 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -9,14 +9,17 @@ using osu.Game.Replays; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Taiko.Beatmaps; namespace osu.Game.Rulesets.Taiko.Replays { - public class TaikoAutoGenerator : AutoGenerator + public class TaikoAutoGenerator : AutoGenerator { + public new TaikoBeatmap Beatmap => (TaikoBeatmap)base.Beatmap; + private const double swell_hit_speed = 50; - public TaikoAutoGenerator(Beatmap beatmap) + public TaikoAutoGenerator(IBeatmap beatmap) : base(beatmap) { Replay = new Replay(); diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index 9748cb08be..d97d7626ef 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Replays; using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 44fd43d660..5203415e90 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test-strong.osu b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test-strong.osu new file mode 100644 index 0000000000..33510eceb7 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test-strong.osu @@ -0,0 +1,257 @@ +osu file format v14 + +[General] +Mode: 1 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +62500,-500,4,2,1,50,0,0 +71000,-100,4,2,1,50,0,0 + +[HitObjects] +// Same as diffcalc-test with finishers on every note +142,122,0,5,4,0:0:0:0: +142,122,125,1,4,0:0:0:0: +142,122,250,1,4,0:0:0:0: +142,122,375,1,4,0:0:0:0: +142,122,500,1,4,0:0:0:0: +142,122,625,1,4,0:0:0:0: +142,122,750,1,4,0:0:0:0: +142,122,875,1,4,0:0:0:0: +142,122,1000,1,4,0:0:0:0: +142,122,1125,1,4,0:0:0:0: +142,122,1250,1,4,0:0:0:0: +142,122,1375,1,4,0:0:0:0: +142,122,1500,1,4,0:0:0:0: +119,106,2500,1,6,0:0:0:0: +119,106,2625,1,6,0:0:0:0: +119,106,2750,1,6,0:0:0:0: +119,106,2875,1,6,0:0:0:0: +119,106,3000,1,6,0:0:0:0: +119,106,3125,1,6,0:0:0:0: +119,106,3250,1,6,0:0:0:0: +119,106,3375,1,6,0:0:0:0: +119,106,3500,1,6,0:0:0:0: +119,106,3625,1,6,0:0:0:0: +119,106,3750,1,6,0:0:0:0: +119,106,3875,1,6,0:0:0:0: +119,106,4000,1,6,0:0:0:0: +136,90,5000,1,4,0:0:0:0: +136,90,5125,1,6,0:0:0:0: +136,90,5250,1,4,0:0:0:0: +136,90,5375,1,6,0:0:0:0: +136,90,5500,1,4,0:0:0:0: +136,90,5625,1,6,0:0:0:0: +136,90,5750,1,4,0:0:0:0: +136,90,5875,1,6,0:0:0:0: +136,90,6000,1,4,0:0:0:0: +136,90,6125,1,6,0:0:0:0: +136,90,6250,1,4,0:0:0:0: +136,90,6375,1,6,0:0:0:0: +136,90,6500,1,4,0:0:0:0: +86,113,7500,1,4,0:0:0:0: +86,113,7625,1,4,0:0:0:0: +86,113,7750,1,6,0:0:0:0: +86,113,7875,1,6,0:0:0:0: +86,113,8000,1,4,0:0:0:0: +86,113,8125,1,4,0:0:0:0: +86,113,8250,1,6,0:0:0:0: +86,113,8375,1,6,0:0:0:0: +86,113,8500,1,4,0:0:0:0: +86,113,8625,1,4,0:0:0:0: +86,113,8750,1,6,0:0:0:0: +86,113,8875,1,6,0:0:0:0: +86,113,9000,1,4,0:0:0:0: +146,90,10000,1,4,0:0:0:0: +146,90,10125,1,4,0:0:0:0: +146,90,10250,1,4,0:0:0:0: +146,90,10375,1,6,0:0:0:0: +146,90,10500,1,6,0:0:0:0: +146,90,10625,1,6,0:0:0:0: +146,90,10750,1,4,0:0:0:0: +146,90,10875,1,4,0:0:0:0: +146,90,11000,1,4,0:0:0:0: +146,90,11125,1,6,0:0:0:0: +146,90,11250,1,6,0:0:0:0: +146,90,11375,1,6,0:0:0:0: +146,90,11500,1,4,0:0:0:0: +146,90,11625,1,4,0:0:0:0: +146,90,11750,1,4,0:0:0:0: +146,90,11875,1,6,0:0:0:0: +146,90,12000,1,6,0:0:0:0: +146,90,12125,1,6,0:0:0:0: +146,90,12250,1,4,0:0:0:0: +146,90,12375,1,4,0:0:0:0: +146,90,12500,1,4,0:0:0:0: +69,99,13500,1,4,0:0:0:0: +69,99,13625,1,4,0:0:0:0: +69,99,13750,1,4,0:0:0:0: +69,99,13875,1,6,0:0:0:0: +69,99,14000,1,4,0:0:0:0: +69,99,14125,1,4,0:0:0:0: +69,99,14250,1,4,0:0:0:0: +69,99,14375,1,6,0:0:0:0: +69,99,14500,1,4,0:0:0:0: +69,99,14625,1,4,0:0:0:0: +69,99,14750,1,4,0:0:0:0: +69,99,14875,1,6,0:0:0:0: +69,99,15000,1,4,0:0:0:0: +69,99,15125,1,4,0:0:0:0: +69,99,15250,1,4,0:0:0:0: +69,99,15375,1,6,0:0:0:0: +69,99,15500,1,4,0:0:0:0: +83,89,16500,1,4,0:0:0:0: +83,89,16625,1,6,0:0:0:0: +83,89,16750,1,6,0:0:0:0: +83,89,16875,1,4,0:0:0:0: +83,89,17000,1,4,0:0:0:0: +83,89,17125,1,4,0:0:0:0: +83,89,17250,1,6,0:0:0:0: +83,89,17375,1,6,0:0:0:0: +83,89,17500,1,6,0:0:0:0: +83,89,17625,1,6,0:0:0:0: +83,89,17750,1,4,0:0:0:0: +83,89,17875,1,4,0:0:0:0: +83,89,18000,1,4,0:0:0:0: +83,89,18125,1,4,0:0:0:0: +83,89,18250,1,4,0:0:0:0: +83,89,18375,1,6,0:0:0:0: +83,89,18500,1,6,0:0:0:0: +83,89,18625,1,6,0:0:0:0: +83,89,18750,1,6,0:0:0:0: +83,89,18875,1,4,0:0:0:0: +83,89,19000,1,4,0:0:0:0: +83,89,19125,1,4,0:0:0:0: +83,89,19250,1,4,0:0:0:0: +83,89,19375,1,6,0:0:0:0: +83,89,19500,1,6,0:0:0:0: +83,89,19625,1,4,0:0:0:0: +84,122,20500,1,4,0:0:0:0: +84,122,20625,2,4,L|217:123,1,120 +84,122,21125,1,4,0:0:0:0: +84,122,21250,2,4,L|217:123,1,120 +84,122,21750,1,4,0:0:0:0: +84,122,21875,2,4,L|217:123,1,120 +84,122,22375,1,4,0:0:0:0: +84,122,22500,2,4,L|217:123,1,120 +84,122,23000,1,4,0:0:0:0: +84,122,23125,2,4,L|217:123,1,120 +99,106,24500,1,4,0:0:0:0: +99,106,24625,1,4,0:0:0:0: +99,106,24750,2,4,L|194:107,1,80 +99,106,25125,1,4,0:0:0:0: +99,106,25250,1,4,0:0:0:0: +99,106,25375,2,4,L|194:107,1,80 +99,106,25750,1,4,0:0:0:0: +99,106,25875,1,4,0:0:0:0: +99,106,26000,2,4,L|194:107,1,80 +99,106,26375,1,4,0:0:0:0: +99,106,26500,1,4,0:0:0:0: +99,106,26625,2,4,L|194:107,1,80 +99,106,27000,1,4,0:0:0:0: +99,106,27125,1,4,0:0:0:0: +99,106,27250,2,4,L|194:107,1,80 +121,103,28500,1,4,0:0:0:0: +121,103,28625,1,4,0:0:0:0: +121,103,28750,1,4,0:0:0:0: +121,103,28875,2,4,L|190:103,1,40 +121,103,29125,1,4,0:0:0:0: +121,103,29250,1,4,0:0:0:0: +121,103,29375,1,4,0:0:0:0: +121,103,29500,2,4,L|190:103,1,40 +121,103,29750,1,4,0:0:0:0: +121,103,29875,1,4,0:0:0:0: +121,103,30000,1,4,0:0:0:0: +121,103,30125,2,4,L|190:103,1,40 +121,103,30375,1,4,0:0:0:0: +121,103,30500,1,4,0:0:0:0: +121,103,30625,1,4,0:0:0:0: +121,103,30750,2,4,L|190:103,1,40 +121,103,31000,1,4,0:0:0:0: +121,103,31125,1,4,0:0:0:0: +121,103,31250,1,4,0:0:0:0: +121,103,31375,2,4,L|190:103,1,40 +121,103,32500,1,4,0:0:0:0: +121,103,32625,1,6,0:0:0:0: +121,103,32750,1,4,0:0:0:0: +121,103,32875,2,4,L|190:103,1,40 +121,103,33125,1,4,0:0:0:0: +121,103,33250,1,6,0:0:0:0: +121,103,33375,1,4,0:0:0:0: +121,103,33500,2,4,L|190:103,1,40 +121,103,33750,1,4,0:0:0:0: +121,103,33875,1,6,0:0:0:0: +121,103,34000,1,4,0:0:0:0: +121,103,34125,2,4,L|190:103,1,40 +121,103,34375,1,4,0:0:0:0: +121,103,34500,1,6,0:0:0:0: +121,103,34625,1,4,0:0:0:0: +121,103,34750,2,4,L|190:103,1,40 +121,103,35000,1,4,0:0:0:0: +121,103,35125,1,6,0:0:0:0: +121,103,35250,1,4,0:0:0:0: +121,103,35375,2,4,L|190:103,1,40 +121,103,36500,1,4,0:0:0:0: +121,103,36625,1,4,0:0:0:0: +121,103,36750,1,6,0:0:0:0: +121,103,36875,2,4,L|190:103,1,40 +121,103,37125,1,4,0:0:0:0: +121,103,37250,1,4,0:0:0:0: +121,103,37375,1,6,0:0:0:0: +121,103,37500,2,4,L|190:103,1,40 +121,103,37750,1,4,0:0:0:0: +121,103,37875,1,4,0:0:0:0: +121,103,38000,1,6,0:0:0:0: +121,103,38125,2,4,L|190:103,1,40 +121,103,38375,1,4,0:0:0:0: +121,103,38500,1,4,0:0:0:0: +121,103,38625,1,6,0:0:0:0: +121,103,38750,2,4,L|190:103,1,40 +121,103,39000,1,4,0:0:0:0: +121,103,39125,1,4,0:0:0:0: +121,103,39250,1,6,0:0:0:0: +121,103,39375,2,4,L|190:103,1,40 +107,106,40500,1,4,0:0:0:0: +107,106,40625,1,4,0:0:0:0: +107,106,40750,1,6,0:0:0:0: +107,106,40875,1,6,0:0:0:0: +46,112,41000,2,4,L|214:112,1,160 +107,106,41625,1,4,0:0:0:0: +107,106,41750,1,4,0:0:0:0: +107,106,41875,1,6,0:0:0:0: +107,106,42000,1,6,0:0:0:0: +46,112,42125,2,4,L|214:112,1,160 +107,106,42750,1,4,0:0:0:0: +107,106,42875,1,4,0:0:0:0: +107,106,43000,1,6,0:0:0:0: +107,106,43125,1,6,0:0:0:0: +46,112,43250,2,4,L|214:112,1,160 +107,106,43875,1,4,0:0:0:0: +107,106,44000,1,4,0:0:0:0: +107,106,44125,1,6,0:0:0:0: +107,106,44250,1,6,0:0:0:0: +46,112,44375,2,4,L|214:112,1,160 +107,106,45000,1,4,0:0:0:0: +107,106,45125,1,4,0:0:0:0: +107,106,45250,1,6,0:0:0:0: +107,106,45375,1,6,0:0:0:0: +46,112,45500,2,4,L|214:112,1,160 +256,192,47000,12,4,47500,0:0:0:0: +256,192,47625,12,4,48000,0:0:0:0: +256,192,48125,12,4,48500,0:0:0:0: +256,192,48625,12,4,49000,0:0:0:0: +256,192,50000,12,4,50500,0:0:0:0: +183,143,50625,5,4,0:0:0:0: +256,192,50750,12,4,51250,0:0:0:0: +114,106,51375,5,4,0:0:0:0: +256,192,51625,12,4,52125,0:0:0:0: +154,143,52250,5,4,0:0:0:0: +256,192,52375,12,4,52875,0:0:0:0: +116,111,53000,5,4,0:0:0:0: diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test.osu b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test.osu new file mode 100644 index 0000000000..15326162ea --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/diffcalc-test.osu @@ -0,0 +1,285 @@ +osu file format v14 + +[General] +Mode: 1 + +[Difficulty] +CircleSize:4 +OverallDifficulty:7 +ApproachRate:8.3 +SliderMultiplier:1.6 +SliderTickRate:1 + +[TimingPoints] +500,500,4,2,1,50,1,0 +62500,-500,4,2,1,50,0,0 +71000,-100,4,2,1,50,0,0 + +[HitObjects] +// dd, spaced 1/4 beat apart +142,122,0,5,0,0:0:0:0: +142,122,125,1,0,0:0:0:0: +142,122,250,1,0,0:0:0:0: +142,122,375,1,0,0:0:0:0: +142,122,500,1,0,0:0:0:0: +142,122,625,1,0,0:0:0:0: +142,122,750,1,0,0:0:0:0: +142,122,875,1,0,0:0:0:0: +142,122,1000,1,0,0:0:0:0: +142,122,1125,1,0,0:0:0:0: +142,122,1250,1,0,0:0:0:0: +142,122,1375,1,0,0:0:0:0: +142,122,1500,1,0,0:0:0:0: + +// kk, spaced 1/4 beat apart +119,106,2500,1,2,0:0:0:0: +119,106,2625,1,2,0:0:0:0: +119,106,2750,1,2,0:0:0:0: +119,106,2875,1,2,0:0:0:0: +119,106,3000,1,2,0:0:0:0: +119,106,3125,1,2,0:0:0:0: +119,106,3250,1,2,0:0:0:0: +119,106,3375,1,2,0:0:0:0: +119,106,3500,1,2,0:0:0:0: +119,106,3625,1,2,0:0:0:0: +119,106,3750,1,2,0:0:0:0: +119,106,3875,1,2,0:0:0:0: +119,106,4000,1,2,0:0:0:0: + +// dk, spaced 1/4 beat apart +136,90,5000,1,0,0:0:0:0: +136,90,5125,1,2,0:0:0:0: +136,90,5250,1,0,0:0:0:0: +136,90,5375,1,2,0:0:0:0: +136,90,5500,1,0,0:0:0:0: +136,90,5625,1,2,0:0:0:0: +136,90,5750,1,0,0:0:0:0: +136,90,5875,1,2,0:0:0:0: +136,90,6000,1,0,0:0:0:0: +136,90,6125,1,2,0:0:0:0: +136,90,6250,1,0,0:0:0:0: +136,90,6375,1,2,0:0:0:0: +136,90,6500,1,0,0:0:0:0: + +// ddkk, spaced 1/4 beat apart +86,113,7500,1,0,0:0:0:0: +86,113,7625,1,0,0:0:0:0: +86,113,7750,1,2,0:0:0:0: +86,113,7875,1,2,0:0:0:0: +86,113,8000,1,0,0:0:0:0: +86,113,8125,1,0,0:0:0:0: +86,113,8250,1,2,0:0:0:0: +86,113,8375,1,2,0:0:0:0: +86,113,8500,1,0,0:0:0:0: +86,113,8625,1,0,0:0:0:0: +86,113,8750,1,2,0:0:0:0: +86,113,8875,1,2,0:0:0:0: +86,113,9000,1,0,0:0:0:0: + +// dddkkk, spaced 1/4 beat apart +146,90,10000,1,0,0:0:0:0: +146,90,10125,1,0,0:0:0:0: +146,90,10250,1,0,0:0:0:0: +146,90,10375,1,2,0:0:0:0: +146,90,10500,1,2,0:0:0:0: +146,90,10625,1,2,0:0:0:0: +146,90,10750,1,0,0:0:0:0: +146,90,10875,1,0,0:0:0:0: +146,90,11000,1,0,0:0:0:0: +146,90,11125,1,2,0:0:0:0: +146,90,11250,1,2,0:0:0:0: +146,90,11375,1,2,0:0:0:0: +146,90,11500,1,0,0:0:0:0: +146,90,11625,1,0,0:0:0:0: +146,90,11750,1,0,0:0:0:0: +146,90,11875,1,2,0:0:0:0: +146,90,12000,1,2,0:0:0:0: +146,90,12125,1,2,0:0:0:0: +146,90,12250,1,0,0:0:0:0: +146,90,12375,1,0,0:0:0:0: +146,90,12500,1,0,0:0:0:0: + +// dddk, spaced 1/4 beat apart +69,99,13500,1,0,0:0:0:0: +69,99,13625,1,0,0:0:0:0: +69,99,13750,1,0,0:0:0:0: +69,99,13875,1,2,0:0:0:0: +69,99,14000,1,0,0:0:0:0: +69,99,14125,1,0,0:0:0:0: +69,99,14250,1,0,0:0:0:0: +69,99,14375,1,2,0:0:0:0: +69,99,14500,1,0,0:0:0:0: +69,99,14625,1,0,0:0:0:0: +69,99,14750,1,0,0:0:0:0: +69,99,14875,1,2,0:0:0:0: +69,99,15000,1,0,0:0:0:0: +69,99,15125,1,0,0:0:0:0: +69,99,15250,1,0,0:0:0:0: +69,99,15375,1,2,0:0:0:0: +69,99,15500,1,0,0:0:0:0: + +// arbitrary pattern, spaced 1/4 beat apart +83,89,16500,1,0,0:0:0:0: +83,89,16625,1,2,0:0:0:0: +83,89,16750,1,2,0:0:0:0: +83,89,16875,1,0,0:0:0:0: +83,89,17000,1,0,0:0:0:0: +83,89,17125,1,0,0:0:0:0: +83,89,17250,1,2,0:0:0:0: +83,89,17375,1,2,0:0:0:0: +83,89,17500,1,2,0:0:0:0: +83,89,17625,1,2,0:0:0:0: +83,89,17750,1,0,0:0:0:0: +83,89,17875,1,0,0:0:0:0: +83,89,18000,1,0,0:0:0:0: +83,89,18125,1,0,0:0:0:0: +83,89,18250,1,0,0:0:0:0: +83,89,18375,1,2,0:0:0:0: +83,89,18500,1,2,0:0:0:0: +83,89,18625,1,2,0:0:0:0: +83,89,18750,1,2,0:0:0:0: +83,89,18875,1,0,0:0:0:0: +83,89,19000,1,0,0:0:0:0: +83,89,19125,1,0,0:0:0:0: +83,89,19250,1,0,0:0:0:0: +83,89,19375,1,2,0:0:0:0: +83,89,19500,1,2,0:0:0:0: +83,89,19625,1,0,0:0:0:0: + +// d-slider pattern, spaced 1/4 beat apart +84,122,20500,1,0,0:0:0:0: +84,122,20625,2,0,L|217:123,1,120 +84,122,21125,1,0,0:0:0:0: +84,122,21250,2,0,L|217:123,1,120 +84,122,21750,1,0,0:0:0:0: +84,122,21875,2,0,L|217:123,1,120 +84,122,22375,1,0,0:0:0:0: +84,122,22500,2,0,L|217:123,1,120 +84,122,23000,1,0,0:0:0:0: +84,122,23125,2,0,L|217:123,1,120 + +// dd-slider pattern, spaced 1/4 beat apart +99,106,24500,1,0,0:0:0:0: +99,106,24625,1,0,0:0:0:0: +99,106,24750,2,0,L|194:107,1,80 +99,106,25125,1,0,0:0:0:0: +99,106,25250,1,0,0:0:0:0: +99,106,25375,2,0,L|194:107,1,80 +99,106,25750,1,0,0:0:0:0: +99,106,25875,1,0,0:0:0:0: +99,106,26000,2,0,L|194:107,1,80 +99,106,26375,1,0,0:0:0:0: +99,106,26500,1,0,0:0:0:0: +99,106,26625,2,0,L|194:107,1,80 +99,106,27000,1,0,0:0:0:0: +99,106,27125,1,0,0:0:0:0: +99,106,27250,2,0,L|194:107,1,80 + +// ddd-slider pattern, spaced 1/4 beat apart +121,103,28500,1,0,0:0:0:0: +121,103,28625,1,0,0:0:0:0: +121,103,28750,1,0,0:0:0:0: +121,103,28875,2,0,L|190:103,1,40 +121,103,29125,1,0,0:0:0:0: +121,103,29250,1,0,0:0:0:0: +121,103,29375,1,0,0:0:0:0: +121,103,29500,2,0,L|190:103,1,40 +121,103,29750,1,0,0:0:0:0: +121,103,29875,1,0,0:0:0:0: +121,103,30000,1,0,0:0:0:0: +121,103,30125,2,0,L|190:103,1,40 +121,103,30375,1,0,0:0:0:0: +121,103,30500,1,0,0:0:0:0: +121,103,30625,1,0,0:0:0:0: +121,103,30750,2,0,L|190:103,1,40 +121,103,31000,1,0,0:0:0:0: +121,103,31125,1,0,0:0:0:0: +121,103,31250,1,0,0:0:0:0: +121,103,31375,2,0,L|190:103,1,40 + +// dkd-slider pattern, spaced 1/4 beat apart +121,103,32500,1,0,0:0:0:0: +121,103,32625,1,2,0:0:0:0: +121,103,32750,1,0,0:0:0:0: +121,103,32875,2,0,L|190:103,1,40 +121,103,33125,1,0,0:0:0:0: +121,103,33250,1,2,0:0:0:0: +121,103,33375,1,0,0:0:0:0: +121,103,33500,2,0,L|190:103,1,40 +121,103,33750,1,0,0:0:0:0: +121,103,33875,1,2,0:0:0:0: +121,103,34000,1,0,0:0:0:0: +121,103,34125,2,0,L|190:103,1,40 +121,103,34375,1,0,0:0:0:0: +121,103,34500,1,2,0:0:0:0: +121,103,34625,1,0,0:0:0:0: +121,103,34750,2,0,L|190:103,1,40 +121,103,35000,1,0,0:0:0:0: +121,103,35125,1,2,0:0:0:0: +121,103,35250,1,0,0:0:0:0: +121,103,35375,2,0,L|190:103,1,40 + +//ddk-slider pattern, spaced 1/4 beat apart +121,103,36500,1,0,0:0:0:0: +121,103,36625,1,0,0:0:0:0: +121,103,36750,1,2,0:0:0:0: +121,103,36875,2,0,L|190:103,1,40 +121,103,37125,1,0,0:0:0:0: +121,103,37250,1,0,0:0:0:0: +121,103,37375,1,2,0:0:0:0: +121,103,37500,2,0,L|190:103,1,40 +121,103,37750,1,0,0:0:0:0: +121,103,37875,1,0,0:0:0:0: +121,103,38000,1,2,0:0:0:0: +121,103,38125,2,0,L|190:103,1,40 +121,103,38375,1,0,0:0:0:0: +121,103,38500,1,0,0:0:0:0: +121,103,38625,1,2,0:0:0:0: +121,103,38750,2,0,L|190:103,1,40 +121,103,39000,1,0,0:0:0:0: +121,103,39125,1,0,0:0:0:0: +121,103,39250,1,2,0:0:0:0: +121,103,39375,2,0,L|190:103,1,40 + +//ddkk-slider pattern, spaced 1/4 beat apart +107,106,40500,1,0,0:0:0:0: +107,106,40625,1,0,0:0:0:0: +107,106,40750,1,2,0:0:0:0: +107,106,40875,1,2,0:0:0:0: +46,112,41000,2,0,L|214:112,1,160 +107,106,41625,1,0,0:0:0:0: +107,106,41750,1,0,0:0:0:0: +107,106,41875,1,2,0:0:0:0: +107,106,42000,1,2,0:0:0:0: +46,112,42125,2,0,L|214:112,1,160 +107,106,42750,1,0,0:0:0:0: +107,106,42875,1,0,0:0:0:0: +107,106,43000,1,2,0:0:0:0: +107,106,43125,1,2,0:0:0:0: +46,112,43250,2,0,L|214:112,1,160 +107,106,43875,1,0,0:0:0:0: +107,106,44000,1,0,0:0:0:0: +107,106,44125,1,2,0:0:0:0: +107,106,44250,1,2,0:0:0:0: +46,112,44375,2,0,L|214:112,1,160 +107,106,45000,1,0,0:0:0:0: +107,106,45125,1,0,0:0:0:0: +107,106,45250,1,2,0:0:0:0: +107,106,45375,1,2,0:0:0:0: +46,112,45500,2,0,L|214:112,1,160 + +// spinner-spinner pattern, spaced 1/4 beat apart +256,192,47000,12,0,47500,0:0:0:0: +256,192,47625,12,0,48000,0:0:0:0: +256,192,48125,12,0,48500,0:0:0:0: +256,192,48625,12,0,49000,0:0:0:0: + +// spinner-d pattern, spaced 1/4 beat apart +256,192,50000,12,0,50500,0:0:0:0: +183,143,50625,5,0,0:0:0:0: +256,192,50750,12,0,51250,0:0:0:0: +114,106,51375,5,0,0:0:0:0: +256,192,51625,12,0,52125,0:0:0:0: +154,143,52250,5,0,0:0:0:0: +256,192,52375,12,0,52875,0:0:0:0: +116,111,53000,5,0,0:0:0:0: diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 87481c800d..442cca49f8 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -32,8 +32,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// private double hpMissMultiplier; - public TaikoScoreProcessor(RulesetContainer rulesetContainer) - : base(rulesetContainer) + public TaikoScoreProcessor(DrawableRuleset drawableRuleset) + : base(drawableRuleset) { } @@ -67,6 +67,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring Health.Value = 0; } - protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); + public override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index 3b430e7ad1..058bec5111 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Framework.Input.Bindings; @@ -19,10 +19,13 @@ namespace osu.Game.Rulesets.Taiko { [Description("Left (rim)")] LeftRim, + [Description("Left (centre)")] LeftCentre, + [Description("Right (centre)")] RightCentre, + [Description("Right (rim)")] RightRim } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7094f9d71b..3e94775eb6 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -11,6 +11,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Replays.Types; +using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new TaikoRulesetContainer(this, beatmap); + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) => new DrawableTaikoRuleset(this, beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap); public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] @@ -99,6 +100,11 @@ namespace osu.Game.Rulesets.Taiko new MultiMod(new TaikoModAutoplay(), new ModCinema()), new TaikoModRelax(), }; + case ModType.Fun: + return new Mod[] + { + new MultiMod(new ModWindUp(), new ModWindDown()) + }; default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index c7eba91564..943adaed4b 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; @@ -39,12 +39,10 @@ namespace osu.Game.Rulesets.Taiko.UI } } - protected override void LoadComplete() + protected override void ApplyHitAnimations() { - if (Result.IsHit) - this.MoveToY(-100, 500); - - base.LoadComplete(); + this.MoveToY(-100, 500); + base.ApplyHitAnimations(); } } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs similarity index 88% rename from osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs rename to osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index 8f6e55c0d1..899b91863e 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Beatmaps; @@ -20,13 +20,13 @@ using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoRulesetContainer : ScrollingRulesetContainer + public class DrawableTaikoRuleset : DrawableScrollingRuleset { protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; protected override bool UserScrollSpeedAdjustment => false; - public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + public DrawableTaikoRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { Direction.Value = ScrollingDirection.Left; @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); - public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); + protected override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo); diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index 84e40427f2..404960c26f 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/HitTarget.cs b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs index ab5bc841a6..2bb208bd1d 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitTarget.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 6d84b69638..aa37ff7008 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index ad9b967ac6..bed2c554ec 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs b/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs index 73751e845e..0f0ad59fd3 100644 --- a/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/PlayfieldAdjustmentContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osuTK; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 333b1ba83a..35b941b52b 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.UI public class TaikoPlayfield : ScrollingPlayfield { /// - /// Default height of a when inside a . + /// Default height of a when inside a . /// public const float DEFAULT_HEIGHT = 178; @@ -225,7 +225,7 @@ namespace osu.Game.Rulesets.Taiko.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!DisplayJudgements) + if (!DisplayJudgements.Value) return; if (!judgedObject.DisplayResult) diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 002d6a7e8d..656ebcc7c2 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Tests.iOS/AppDelegate.cs b/osu.Game.Tests.iOS/AppDelegate.cs new file mode 100644 index 0000000000..1e703e0c0a --- /dev/null +++ b/osu.Game.Tests.iOS/AppDelegate.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; + +namespace osu.Game.Tests.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuTestBrowser(); + } +} diff --git a/osu.Game.Tests.iOS/Application.cs b/osu.Game.Tests.iOS/Application.cs new file mode 100644 index 0000000000..a23fe4e129 --- /dev/null +++ b/osu.Game.Tests.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.Game.Tests.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.Game.Tests.iOS/Entitlements.plist b/osu.Game.Tests.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.Game.Tests.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.Game.Tests.iOS/Info.plist b/osu.Game.Tests.iOS/Info.plist new file mode 100644 index 0000000000..98a4223116 --- /dev/null +++ b/osu.Game.Tests.iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleName + osu.Game.Tests.iOS + CFBundleIdentifier + ppy.osu-Game-Tests-iOS + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj new file mode 100644 index 0000000000..ea5ab699f3 --- /dev/null +++ b/osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj @@ -0,0 +1,60 @@ + + + + + Debug + iPhoneSimulator + Exe + {65FF8E19-6934-469B-B690-23C6D6E56A17} + osu.Game.Tests + osu.Game.Tests.iOS + + + + + + + libbass.a + PreserveNewest + + + libbass_fx.a + PreserveNewest + + + Linker.xml + + + + + %(RecursiveDir)%(Filename)%(Extension) + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {C92A607B-1FDD-4954-9F92-03FF547D9080} + osu.Game.Rulesets.Osu + + + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} + osu.Game.Rulesets.Catch + + + {48F4582B-7687-4621-9CBE-5C24197CB536} + osu.Game.Rulesets.Mania + + + {F167E17A-7DE6-4AF5-B920-A5112296C695} + osu.Game.Rulesets.Taiko + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index f0211e1ead..02dff6993d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using NUnit.Framework; @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Beatmaps.Formats [Test] public void TestDecodeBeatmapVersion() { - using (var resStream = Resource.OpenResource("beatmap-version.osu")) + using (var resStream = TestResources.OpenResource("beatmap-version.osu")) using (var stream = new StreamReader(resStream)) { var decoder = Decoder.GetDecoder(stream); @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapGeneral() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapEditor() { var decoder = new LegacyBeatmapDecoder(); - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var beatmapInfo = decoder.Decode(stream).BeatmapInfo; @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapMetadata() { var decoder = new LegacyBeatmapDecoder(); - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapDifficulty() { var decoder = new LegacyBeatmapDecoder(); - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var difficulty = decoder.Decode(stream).BeatmapInfo.BaseDifficulty; @@ -137,7 +137,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapEvents() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -155,7 +155,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapTimingPoints() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -190,7 +190,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapColours() { var decoder = new LegacySkinDecoder(); - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var comboColors = decoder.Decode(stream).ComboColours; @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapComboOffsetsOsu() { var decoder = new LegacyBeatmapDecoder(); - using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) + using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -237,7 +237,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapComboOffsetsCatch() { var decoder = new LegacyBeatmapDecoder(); - using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) + using (var resStream = TestResources.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); @@ -259,7 +259,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeBeatmapHitObjects() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) + using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -286,7 +286,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeControlPointCustomSampleBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("controlpoint-custom-samplebank.osu")) + using (var resStream = TestResources.OpenResource("controlpoint-custom-samplebank.osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -307,7 +307,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectCustomSampleBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("hitobject-custom-samplebank.osu")) + using (var resStream = TestResources.OpenResource("hitobject-custom-samplebank.osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -324,7 +324,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectFileSamples() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("hitobject-file-samples.osu")) + using (var resStream = TestResources.OpenResource("hitobject-file-samples.osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -333,6 +333,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual("hit_2.wav", getTestableSampleInfo(hitObjects[1]).LookupNames.First()); Assert.AreEqual("normal-hitnormal2", getTestableSampleInfo(hitObjects[2]).LookupNames.First()); Assert.AreEqual("hit_1.wav", getTestableSampleInfo(hitObjects[3]).LookupNames.First()); + Assert.AreEqual(70, getTestableSampleInfo(hitObjects[3]).Volume); } SampleInfo getTestableSampleInfo(HitObject hitObject) => hitObject.SampleControlPoint.ApplyTo(hitObject.Samples[0]); @@ -342,7 +343,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeSliderSamples() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("slider-samples.osu")) + using (var resStream = TestResources.OpenResource("slider-samples.osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; @@ -385,7 +386,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeHitObjectNullAdditionBank() { var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; - using (var resStream = Resource.OpenResource("hitobject-no-addition-bank.osu")) + using (var resStream = TestResources.OpenResource("hitobject-no-addition-bank.osu")) using (var stream = new StreamReader(resStream)) { var hitObjects = decoder.Decode(stream).HitObjects; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 40857198f1..136d1de930 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using System.Linq; @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeStoryboardEvents() { var decoder = new LegacyStoryboardDecoder(); - using (var resStream = Resource.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu")) + using (var resStream = TestResources.OpenResource("Himeringo - Yotsuya-san ni Yoroshiku (RLC) [Winber1's Extreme].osu")) using (var stream = new StreamReader(resStream)) { var storyboard = decoder.Decode(stream); @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void TestDecodeVariableWithSuffix() { var decoder = new LegacyStoryboardDecoder(); - using (var resStream = Resource.OpenResource("variable-with-suffix.osb")) + using (var resStream = TestResources.OpenResource("variable-with-suffix.osb")) using (var stream = new StreamReader(resStream)) { var storyboard = decoder.Decode(stream); diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index f7e1653cdd..a867ddebae 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using System.Linq; @@ -113,6 +113,7 @@ namespace osu.Game.Tests.Beatmaps.Formats [TestCase(normal)] [TestCase(marathon)] + [Ignore("temporarily disabled pending DeepEqual fix (https://github.com/jamesfoster/DeepEqual/pull/35)")] // Currently fails: // [TestCase(with_sb)] public void TestParity(string beatmap) @@ -146,10 +147,9 @@ namespace osu.Game.Tests.Beatmaps.Formats /// The after being decoded by an . private Beatmap decode(string filename, out Beatmap jsonDecoded) { - using (var stream = Resource.OpenResource(filename)) + using (var stream = TestResources.OpenResource(filename)) using (var sr = new StreamReader(stream)) { - var legacyDecoded = new LegacyBeatmapDecoder { ApplyOffsets = false }.Decode(sr); using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms)) diff --git a/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs new file mode 100644 index 0000000000..b3863bcf44 --- /dev/null +++ b/osu.Game.Tests/Beatmaps/Formats/ParsingTest.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Globalization; +using NUnit.Framework; +using osu.Game.Beatmaps.Formats; + +namespace osu.Game.Tests.Beatmaps.Formats +{ + [TestFixture] + public class ParsingTest + { + [Test] + public void TestNaNHandling() => allThrow("NaN"); + + [Test] + public void TestBadStringHandling() => allThrow("Random string 123"); + + [TestCase(Parsing.MAX_PARSE_VALUE)] + [TestCase(-1)] + [TestCase(0)] + [TestCase(1)] + [TestCase(-Parsing.MAX_PARSE_VALUE)] + [TestCase(10, 10)] + [TestCase(-10, 10)] + public void TestValidRanges(double input, double limit = Parsing.MAX_PARSE_VALUE) + { + Assert.AreEqual(Parsing.ParseInt((input).ToString(CultureInfo.InvariantCulture), (int)limit), (int)input); + Assert.AreEqual(Parsing.ParseFloat((input).ToString(CultureInfo.InvariantCulture), (float)limit), (float)input); + Assert.AreEqual(Parsing.ParseDouble((input).ToString(CultureInfo.InvariantCulture), limit), input); + } + + [TestCase(double.PositiveInfinity)] + [TestCase(double.NegativeInfinity)] + [TestCase(999999999999)] + [TestCase(Parsing.MAX_PARSE_VALUE * 1.1)] + [TestCase(-Parsing.MAX_PARSE_VALUE * 1.1)] + [TestCase(11, 10)] + [TestCase(-11, 10)] + public void TestOutOfRangeHandling(double input, double limit = Parsing.MAX_PARSE_VALUE) + => allThrow(input.ToString(CultureInfo.InvariantCulture), limit); + + private void allThrow(string input, double limit = Parsing.MAX_PARSE_VALUE) + where T : Exception + { + Assert.Throws(getIntParseException(input) ?? typeof(T), () => Parsing.ParseInt(input, (int)limit)); + Assert.Throws(() => Parsing.ParseFloat(input, (float)limit)); + Assert.Throws(() => Parsing.ParseDouble(input, limit)); + } + + /// + /// may not be able to parse some inputs. + /// In this case we expect to receive the raw parsing exception. + /// + /// The input attempting to be parsed. + /// The type of exception thrown by . Null if no exception is thrown. + private Type getIntParseException(string input) + { + try + { + var _ = int.Parse(input); + } + catch (Exception e) + { + return e.GetType(); + } + + return null; + } + } +} diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index c8fd531fcc..f020c2a805 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -12,6 +12,7 @@ using osu.Framework.Platform; using osu.Game.IPC; using osu.Framework.Allocation; using osu.Game.Beatmaps; +using osu.Game.Tests.Resources; using SharpCompress.Archives.Zip; namespace osu.Game.Tests.Beatmaps.IO @@ -19,8 +20,6 @@ namespace osu.Game.Tests.Beatmaps.IO [TestFixture] public class ImportBeatmapTest { - public const string TEST_OSZ_PATH = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; - [Test] public void TestImportWhenClosed() { @@ -102,7 +101,7 @@ namespace osu.Game.Tests.Beatmaps.IO int fireCount = 0; // ReSharper disable once AccessToModifiedClosure - manager.ItemAdded += (_, __, ___) => fireCount++; + manager.ItemAdded += (_, __) => fireCount++; manager.ItemRemoved += _ => fireCount++; var imported = LoadOszIntoOsu(osu); @@ -114,7 +113,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.AreEqual(0, fireCount -= 2); - var breakTemp = createTemporaryBeatmap(); + var breakTemp = TestResources.GetTestBeatmapForImport(); MemoryStream brokenOsu = new MemoryStream(new byte[] { 1, 3, 3, 7 }); MemoryStream brokenOsz = new MemoryStream(File.ReadAllBytes(breakTemp)); @@ -208,6 +207,96 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [TestCase(true)] + [TestCase(false)] + public void TestImportThenDeleteThenImportWithOnlineIDMismatch(bool set) + { + //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"TestImportThenDeleteThenImport-{set}")) + { + try + { + var osu = loadOsu(host); + + var imported = LoadOszIntoOsu(osu); + + if (set) + imported.OnlineBeatmapSetID = 1234; + else + imported.Beatmaps.First().OnlineBeatmapID = 1234; + + osu.Dependencies.Get().Update(imported); + + deleteBeatmapSet(imported, osu); + + var importedSecondTime = LoadOszIntoOsu(osu); + + // check the newly "imported" beatmap has been reimported due to mismatch (even though hashes matched) + Assert.IsTrue(imported.ID != importedSecondTime.ID); + Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public void TestImportWithDuplicateBeatmapIDs() + { + //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWithDuplicateBeatmapID")) + { + try + { + var osu = loadOsu(host); + + var metadata = new BeatmapMetadata + { + Artist = "SomeArtist", + AuthorString = "SomeAuthor" + }; + + var difficulty = new BeatmapDifficulty(); + + var toImport = new BeatmapSetInfo + { + OnlineBeatmapSetID = 1, + Metadata = metadata, + Beatmaps = new List + { + new BeatmapInfo + { + OnlineBeatmapID = 2, + Metadata = metadata, + BaseDifficulty = difficulty + }, + new BeatmapInfo + { + OnlineBeatmapID = 2, + Metadata = metadata, + Status = BeatmapSetOnlineStatus.Loved, + BaseDifficulty = difficulty + } + } + }; + + var manager = osu.Dependencies.Get(); + + var imported = manager.Import(toImport); + + Assert.NotNull(imported); + Assert.AreEqual(null, imported.Beatmaps[0].OnlineBeatmapID); + Assert.AreEqual(null, imported.Beatmaps[1].OnlineBeatmapID); + } + finally + { + host.Exit(); + } + } + } + [Test] [NonParallelizable] [Ignore("Binding IPC on Appveyor isn't working (port in use). Need to figure out why")] @@ -223,7 +312,7 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); - var temp = createTemporaryBeatmap(); + var temp = TestResources.GetTestBeatmapForImport(); var importer = new ArchiveImportIPCChannel(client); if (!importer.ImportAsync(temp).Wait(10000)) @@ -248,7 +337,7 @@ namespace osu.Game.Tests.Beatmaps.IO try { var osu = loadOsu(host); - var temp = createTemporaryBeatmap(); + var temp = TestResources.GetTestBeatmapForImport(); using (File.OpenRead(temp)) osu.Dependencies.Get().Import(temp); ensureLoaded(osu); @@ -262,17 +351,9 @@ namespace osu.Game.Tests.Beatmaps.IO } } - private static string createTemporaryBeatmap() - { - var temp = Path.GetTempFileName() + ".osz"; - File.Copy(TEST_OSZ_PATH, temp, true); - Assert.IsTrue(File.Exists(temp)); - return temp; - } - public static BeatmapSetInfo LoadOszIntoOsu(OsuGameBase osu, string path = null) { - var temp = path ?? createTemporaryBeatmap(); + var temp = path ?? TestResources.GetTestBeatmapForImport(); var manager = osu.Dependencies.Get(); diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index 0039516c0c..17197aff27 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using System.Linq; @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Beatmaps.IO [Test] public void TestReadBeatmaps() { - using (var osz = Resource.OpenResource("Beatmaps.241526 Soleily - Renatus.osz")) + using (var osz = TestResources.GetTestBeatmapStream()) { var reader = new ZipArchiveReader(osz); string[] expected = @@ -44,7 +44,7 @@ namespace osu.Game.Tests.Beatmaps.IO [Test] public void TestReadMetadata() { - using (var osz = Resource.OpenResource("Beatmaps.241526 Soleily - Renatus.osz")) + using (var osz = TestResources.GetTestBeatmapStream()) { var reader = new ZipArchiveReader(osz); @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Beatmaps.IO [Test] public void TestReadFile() { - using (var osz = Resource.OpenResource("Beatmaps.241526 Soleily - Renatus.osz")) + using (var osz = TestResources.GetTestBeatmapStream()) { var reader = new ZipArchiveReader(osz); using (var stream = new StreamReader( diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index e91cd2a624..720d93cb10 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Online.Chat; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 42fe4065c7..760a033aff 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -1,10 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.NonVisual @@ -15,7 +18,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestNoMods() { - var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(1, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -24,7 +27,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestSingleMod() { - var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(2, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -34,7 +37,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestDoubleMod() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(4, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -49,7 +52,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestIncompatibleMods() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -60,7 +63,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestDoubleIncompatibleMods() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(8, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -83,7 +86,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestIncompatibleThroughBaseType() { - var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -136,9 +139,9 @@ namespace osu.Game.Tests.NonVisual public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; } - private class TestDifficultyCalculator : DifficultyCalculator + private class TestLegacyDifficultyCalculator : DifficultyCalculator { - public TestDifficultyCalculator(params Mod[] mods) + public TestLegacyDifficultyCalculator(params Mod[] mods) : base(null, null) { DifficultyAdjustmentMods = mods; @@ -146,7 +149,20 @@ namespace osu.Game.Tests.NonVisual protected override Mod[] DifficultyAdjustmentMods { get; } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) => throw new NotImplementedException(); + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + { + throw new NotImplementedException(); + } + + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + throw new NotImplementedException(); + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) + { + throw new NotImplementedException(); + } } } } diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs new file mode 100644 index 0000000000..1c78b63499 --- /dev/null +++ b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs @@ -0,0 +1,115 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Rulesets.Difficulty.Utils; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class LimitedCapacityStackTest + { + private const int capacity = 3; + + private LimitedCapacityStack stack; + + [SetUp] + public void Setup() + { + stack = new LimitedCapacityStack(capacity); + } + + [Test] + public void TestEmptyStack() + { + Assert.AreEqual(0, stack.Count); + + Assert.Throws(() => + { + int unused = stack[0]; + }); + + int count = 0; + foreach (var unused in stack) + count++; + + Assert.AreEqual(0, count); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void TestInRangeElements(int count) + { + // e.g. 0 -> 1 -> 2 + for (int i = 0; i < count; i++) + stack.Push(i); + + Assert.AreEqual(count, stack.Count); + + // e.g. 2 -> 1 -> 0 (reverse order) + for (int i = 0; i < stack.Count; i++) + Assert.AreEqual(count - 1 - i, stack[i]); + + // e.g. indices 3, 4, 5, 6 (out of range) + for (int i = stack.Count; i < stack.Count + capacity; i++) + { + Assert.Throws(() => + { + int unused = stack[i]; + }); + } + } + + [TestCase(4)] + [TestCase(5)] + [TestCase(6)] + public void TestOverflowElements(int count) + { + // e.g. 0 -> 1 -> 2 -> 3 + for (int i = 0; i < count; i++) + stack.Push(i); + + Assert.AreEqual(capacity, stack.Count); + + // e.g. 3 -> 2 -> 1 (reverse order) + for (int i = 0; i < stack.Count; i++) + Assert.AreEqual(count - 1 - i, stack[i]); + + // e.g. indices 3, 4, 5, 6 (out of range) + for (int i = stack.Count; i < stack.Count + capacity; i++) + { + Assert.Throws(() => + { + int unused = stack[i]; + }); + } + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + [TestCase(4)] + [TestCase(5)] + [TestCase(6)] + public void TestEnumerator(int count) + { + // e.g. 0 -> 1 -> 2 -> 3 + for (int i = 0; i < count; i++) + stack.Push(i); + + int enumeratorCount = 0; + int expectedValue = count - 1; + + foreach (var item in stack) + { + Assert.AreEqual(expectedValue, item); + enumeratorCount++; + expectedValue--; + } + + Assert.AreEqual(stack.Count, enumeratorCount); + } + } +} diff --git a/osu.Game.Tests/Resources/Resource.cs b/osu.Game.Tests/Resources/Resource.cs deleted file mode 100644 index ef90591561..0000000000 --- a/osu.Game.Tests/Resources/Resource.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.IO; -using System.Reflection; - -namespace osu.Game.Tests.Resources -{ - public static class Resource - { - public static Stream OpenResource(string name) - { - var localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); - - return Assembly.GetExecutingAssembly().GetManifestResourceStream($@"osu.Game.Tests.Resources.{name}") ?? - Assembly.LoadFrom(Path.Combine(localPath, @"osu.Game.Resources.dll")).GetManifestResourceStream($@"osu.Game.Resources.{name}"); - } - } -} diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs new file mode 100644 index 0000000000..9cb85a63bf --- /dev/null +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -0,0 +1,28 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.IO; +using NUnit.Framework; +using osu.Framework.IO.Stores; + +namespace osu.Game.Tests.Resources +{ + public static class TestResources + { + public static Stream OpenResource(string name) => new DllResourceStore("osu.Game.Tests.dll").GetStream($"Resources/{name}"); + + public static Stream GetTestBeatmapStream() => new DllResourceStore("osu.Game.Resources.dll").GetStream("Beatmaps/241526 Soleily - Renatus.osz"); + + public static string GetTestBeatmapForImport() + { + var temp = Path.GetTempFileName() + ".osz"; + + using (var stream = GetTestBeatmapStream()) + using (var newFile = File.Create(temp)) + stream.CopyTo(newFile); + + Assert.IsTrue(File.Exists(temp)); + return temp; + } + } +} diff --git a/osu.Game.Tests/Resources/hitobject-file-samples.osu b/osu.Game.Tests/Resources/hitobject-file-samples.osu index 588672e2d9..7c69f259b8 100644 --- a/osu.Game.Tests/Resources/hitobject-file-samples.osu +++ b/osu.Game.Tests/Resources/hitobject-file-samples.osu @@ -13,4 +13,4 @@ SampleSet: Normal 255,193,2170,1,0,0:0:0:0:hit_1.wav 256,191,2638,5,0,0:0:0:0:hit_2.wav 255,193,3107,1,0,0:0:0:0: -256,191,3576,1,0,0:0:0:0:hit_1.wav +256,191,3576,1,0,0:0:0:70:hit_1.wav diff --git a/osu.Game.Tests/Resources/skin-empty.ini b/osu.Game.Tests/Resources/skin-empty.ini new file mode 100644 index 0000000000..b6c319fe3c --- /dev/null +++ b/osu.Game.Tests/Resources/skin-empty.ini @@ -0,0 +1,2 @@ +[General] +Name: test skin \ No newline at end of file diff --git a/osu.Game.Tests/Resources/skin.ini b/osu.Game.Tests/Resources/skin.ini new file mode 100644 index 0000000000..0e5737b4ea --- /dev/null +++ b/osu.Game.Tests/Resources/skin.ini @@ -0,0 +1,8 @@ +[General] +Name: test skin + +[Colours] +Combo1 : 142,199,255 +Combo2 : 255,128,128 +Combo3 : 128,255,255 +Combo7 : 100,100,100,100 \ No newline at end of file diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 7ee7acd539..e39f18c3cd 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -1,9 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -16,14 +15,13 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Tests.Resources; using osu.Game.Users; namespace osu.Game.Tests.Scores.IO { public class ImportScoreTest { - public const string TEST_OSZ_PATH = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; - [Test] public void TestBasicImport() { @@ -132,21 +130,13 @@ namespace osu.Game.Tests.Scores.IO return scoreManager.GetAllUsableScores().First(); } - private string createTemporaryBeatmap() - { - var temp = Path.GetTempFileName() + ".osz"; - File.Copy(TEST_OSZ_PATH, temp, true); - Assert.IsTrue(File.Exists(temp)); - return temp; - } - private OsuGameBase loadOsu(GameHost host) { var osu = new OsuGameBase(); Task.Run(() => host.Run(osu)); waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time"); - var beatmapFile = createTemporaryBeatmap(); + var beatmapFile = TestResources.GetTestBeatmapForImport(); var beatmapManager = osu.Dependencies.Get(); beatmapManager.Import(beatmapFile); diff --git a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs index 5e01213a48..d7f709dc03 100644 --- a/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/ConstantScrollTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Rulesets.UI.Scrolling.Algorithms; diff --git a/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs index c1a5a0f3c9..106aa88be3 100644 --- a/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/OverlappingScrollTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Lists; diff --git a/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs b/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs index 990fb92e6c..1f0c069f8d 100644 --- a/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs +++ b/osu.Game.Tests/ScrollAlgorithms/SequentialScrollTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Lists; diff --git a/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs new file mode 100644 index 0000000000..2a97519e21 --- /dev/null +++ b/osu.Game.Tests/Skins/LegacySkinDecoderTest.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.IO; +using NUnit.Framework; +using osu.Game.Skinning; +using osu.Game.Tests.Resources; +using osuTK.Graphics; + +namespace osu.Game.Tests.Skins +{ + [TestFixture] + public class LegacySkinDecoderTest + { + [TestCase(true)] + [TestCase(false)] + public void TestDecodeSkinColours(bool hasColours) + { + var decoder = new LegacySkinDecoder(); + using (var resStream = TestResources.OpenResource(hasColours ? "skin.ini" : "skin-empty.ini")) + using (var stream = new StreamReader(resStream)) + { + var comboColors = decoder.Decode(stream).ComboColours; + + List expectedColors; + if (hasColours) + expectedColors = new List + { + new Color4(142, 199, 255, 255), + new Color4(255, 128, 128, 255), + new Color4(128, 255, 255, 255), + new Color4(100, 100, 100, 100), + }; + else + expectedColors = new DefaultSkin().Configuration.ComboColours; + + Assert.AreEqual(expectedColors.Count, comboColors.Count); + for (int i = 0; i < expectedColors.Count; i++) + Assert.AreEqual(expectedColors[i], comboColors[i]); + } + } + } +} diff --git a/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs new file mode 100644 index 0000000000..e56156752b --- /dev/null +++ b/osu.Game.Tests/Visual/Background/TestCaseBackgroundScreenBeatmap.cs @@ -0,0 +1,421 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; +using osu.Framework.Input.States; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Scoring; +using osu.Game.Screens; +using osu.Game.Screens.Backgrounds; +using osu.Game.Screens.Play; +using osu.Game.Screens.Play.PlayerSettings; +using osu.Game.Screens.Select; +using osu.Game.Tests.Resources; +using osu.Game.Users; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Background +{ + [TestFixture] + public class TestCaseBackgroundScreenBeatmap : ManualInputManagerTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ScreenWithBeatmapBackground), + typeof(PlayerLoader), + typeof(Player), + typeof(UserDimContainer), + typeof(OsuScreen) + }; + + private DummySongSelect songSelect; + private TestPlayerLoader playerLoader; + private TestPlayer player; + private DatabaseContextFactory factory; + private BeatmapManager manager; + private RulesetStore rulesets; + + [BackgroundDependencyLoader] + private void load(GameHost host) + { + factory = new DatabaseContextFactory(LocalStorage); + factory.ResetDatabase(); + + using (var usage = factory.Get()) + usage.Migrate(); + + factory.ResetDatabase(); + + using (var usage = factory.Get()) + usage.Migrate(); + + Dependencies.Cache(rulesets = new RulesetStore(factory)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, Beatmap.Default)); + Dependencies.Cache(new OsuConfigManager(LocalStorage)); + + manager.Import(TestResources.GetTestBeatmapForImport()); + + Beatmap.SetDefault(); + } + + [SetUp] + public virtual void SetUp() => Schedule(() => + { + Child = new OsuScreenStack(songSelect = new DummySongSelect()) + { + RelativeSizeAxes = Axes.Both + }; + }); + + /// + /// Check if properly triggers the visual settings preview when a user hovers over the visual settings panel. + /// + [Test] + public void PlayerLoaderSettingsHoverTest() + { + setupUserSettings(); + AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer()))); + AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false); + AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent()); + AddStep("Trigger background preview", () => + { + InputManager.MoveMouseTo(playerLoader.ScreenPos); + InputManager.MoveMouseTo(playerLoader.VisualSettingsPos); + }); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + AddStep("Stop background preview", () => InputManager.MoveMouseTo(playerLoader.ScreenPos)); + waitForDim(); + AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && playerLoader.IsBlurCorrect()); + } + + /// + /// In the case of a user triggering the dim preview the instant player gets loaded, then moving the cursor off of the visual settings: + /// The OnHover of PlayerLoader will trigger, which could potentially cause visual settings to be unapplied unless checked for in PlayerLoader. + /// We need to check that in this scenario, the dim and blur is still properly applied after entering player. + /// + [Test] + public void PlayerLoaderTransitionTest() + { + performFullSetup(); + AddStep("Trigger hover event", () => playerLoader.TriggerOnHover()); + AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent()); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + } + + /// + /// Make sure the background is fully invisible (Alpha == 0) when the background should be disabled by the storyboard. + /// + [Test] + public void StoryboardBackgroundVisibilityTest() + { + performFullSetup(); + createFakeStoryboard(); + AddStep("Storyboard Enabled", () => + { + player.ReplacesBackground.Value = true; + player.StoryboardEnabled.Value = true; + }); + waitForDim(); + AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible()); + AddStep("Storyboard Disabled", () => + { + player.ReplacesBackground.Value = false; + player.StoryboardEnabled.Value = false; + }); + waitForDim(); + AddAssert("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && player.IsStoryboardInvisible()); + } + + /// + /// When exiting player, the screen that it suspends/exits to needs to have a fully visible (Alpha == 1) background. + /// + [Test] + public void StoryboardTransitionTest() + { + performFullSetup(); + createFakeStoryboard(); + AddStep("Exit to song select", () => player.Exit()); + waitForDim(); + AddAssert("Background is visible", () => songSelect.IsBackgroundVisible()); + } + + /// + /// Check if the is properly accepting user-defined visual changes at all. + /// + [Test] + public void DisableUserDimTest() + { + performFullSetup(); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + AddStep("EnableUserDim disabled", () => songSelect.DimEnabled.Value = false); + waitForDim(); + AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.IsUserBlurDisabled()); + AddStep("EnableUserDim enabled", () => songSelect.DimEnabled.Value = true); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + } + + /// + /// Check if the visual settings container retains dim and blur when pausing + /// + [Test] + public void PauseTest() + { + performFullSetup(true); + AddStep("Pause", () => player.Pause()); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + AddStep("Unpause", () => player.Resume()); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + } + + /// + /// Check if the visual settings container removes user dim when suspending for + /// + [Test] + public void TransitionTest() + { + performFullSetup(); + var results = new FadeAccessibleResults(new ScoreInfo { User = new User { Username = "osu!" } }); + AddStep("Transition to Results", () => player.Push(results)); + AddUntilStep("Wait for results is current", results.IsCurrentScreen); + waitForDim(); + AddAssert("Screen is undimmed, original background retained", () => + songSelect.IsBackgroundUndimmed() && songSelect.IsBackgroundCurrent() && results.IsBlurCorrect()); + } + + /// + /// Check if background gets undimmed and unblurred when leaving for + /// + [Test] + public void TransitionOutTest() + { + performFullSetup(); + AddStep("Exit to song select", () => player.Exit()); + waitForDim(); + AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && songSelect.IsBlurCorrect()); + } + + /// + /// Check if hovering on the visual settings dialogue after resuming from player still previews the background dim. + /// + [Test] + public void ResumeFromPlayerTest() + { + performFullSetup(); + AddStep("Move mouse to Visual Settings", () => InputManager.MoveMouseTo(playerLoader.VisualSettingsPos)); + AddStep("Resume PlayerLoader", () => player.Restart()); + waitForDim(); + AddAssert("Screen is dimmed and blur applied", () => songSelect.IsBackgroundDimmed() && songSelect.IsUserBlurApplied()); + AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos)); + waitForDim(); + AddAssert("Screen is undimmed and user blur removed", () => songSelect.IsBackgroundUndimmed() && playerLoader.IsBlurCorrect()); + } + + private void waitForDim() => AddWaitStep("Wait for dim", 5); + + private void createFakeStoryboard() => AddStep("Create storyboard", () => + { + player.StoryboardEnabled.Value = false; + player.ReplacesBackground.Value = false; + player.CurrentStoryboardContainer.Add(new SpriteText + { + Size = new Vector2(250, 50), + Alpha = 1, + Colour = Color4.Tomato, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "THIS IS A STORYBOARD", + }); + }); + + private void performFullSetup(bool allowPause = false) + { + setupUserSettings(); + + AddStep("Start player loader", () => + { + songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer + { + AllowPause = allowPause, + Ready = true, + })); + }); + AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded); + AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos)); + AddUntilStep("Wait for player to load", () => player.IsLoaded); + } + + private void setupUserSettings() + { + AddUntilStep("Song select has selection", () => songSelect.Carousel.SelectedBeatmap != null); + AddStep("Set default user settings", () => + { + Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { new OsuModNoFail() }); + songSelect.DimLevel.Value = 0.7f; + songSelect.BlurLevel.Value = 0.4f; + }); + } + + private class DummySongSelect : PlaySongSelect + { + protected override BackgroundScreen CreateBackground() + { + FadeAccessibleBackground background = new FadeAccessibleBackground(Beatmap.Value); + DimEnabled.BindTo(background.EnableUserDim); + return background; + } + + public readonly Bindable DimEnabled = new Bindable(); + public readonly Bindable DimLevel = new Bindable(); + public readonly Bindable BlurLevel = new Bindable(); + + public new BeatmapCarousel Carousel => base.Carousel; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + config.BindWith(OsuSetting.DimLevel, DimLevel); + config.BindWith(OsuSetting.BlurLevel, BlurLevel); + } + + public bool IsBackgroundDimmed() => ((FadeAccessibleBackground)Background).CurrentColour == OsuColour.Gray(1 - (float)DimLevel.Value); + + public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White; + + public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * 25); + + public bool IsUserBlurDisabled() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(0); + + public bool IsBackgroundInvisible() => ((FadeAccessibleBackground)Background).CurrentAlpha == 0; + + public bool IsBackgroundVisible() => ((FadeAccessibleBackground)Background).CurrentAlpha == 1; + + public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR); + + /// + /// Make sure every time a screen gets pushed, the background doesn't get replaced + /// + /// Whether or not the original background (The one created in DummySongSelect) is still the current background + public bool IsBackgroundCurrent() => ((FadeAccessibleBackground)Background).IsCurrentScreen(); + } + + private class FadeAccessibleResults : SoloResults + { + public FadeAccessibleResults(ScoreInfo score) + : base(score) + { + } + + protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); + + public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR); + } + + private class TestPlayer : Player + { + protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); + + protected override UserDimContainer CreateStoryboardContainer() + { + return new TestUserDimContainer(true) + { + RelativeSizeAxes = Axes.Both, + Alpha = 1, + EnableUserDim = { Value = true } + }; + } + + public UserDimContainer CurrentStoryboardContainer => StoryboardContainer; + + // Whether or not the player should be allowed to load. + public bool Ready; + + public Bindable StoryboardEnabled; + public readonly Bindable ReplacesBackground = new Bindable(); + public readonly Bindable IsPaused = new Bindable(); + + public bool IsStoryboardVisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha == 1; + + public bool IsStoryboardInvisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha <= 1; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + while (!Ready) + Thread.Sleep(1); + StoryboardEnabled = config.GetBindable(OsuSetting.ShowStoryboard); + ReplacesBackground.BindTo(Background.StoryboardReplacesBackground); + DrawableRuleset.IsPaused.BindTo(IsPaused); + } + } + + private class TestPlayerLoader : PlayerLoader + { + public VisualSettings VisualSettingsPos => VisualSettings; + public BackgroundScreen ScreenPos => Background; + + public TestPlayerLoader(Player player) + : base(() => player) + { + } + + public void TriggerOnHover() => OnHover(new HoverEvent(new InputState())); + + public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR); + + protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value); + } + + private class FadeAccessibleBackground : BackgroundScreenBeatmap + { + protected override UserDimContainer CreateFadeContainer() => fadeContainer = new TestUserDimContainer { RelativeSizeAxes = Axes.Both }; + + public Color4 CurrentColour => fadeContainer.CurrentColour; + + public float CurrentAlpha => fadeContainer.CurrentAlpha; + + public Vector2 CurrentBlur => Background.BlurSigma; + + private TestUserDimContainer fadeContainer; + + public FadeAccessibleBackground(WorkingBeatmap beatmap) + : base(beatmap) + { + } + } + + private class TestUserDimContainer : UserDimContainer + { + public Color4 CurrentColour => DimContainer.Colour; + public float CurrentAlpha => DimContainer.Alpha; + + public TestUserDimContainer(bool isStoryboard = false) + : base(isStoryboard) + { + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseIdleTracker.cs b/osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs similarity index 84% rename from osu.Game.Tests/Visual/TestCaseIdleTracker.cs rename to osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs index 33e2df9ff0..bf59c116bb 100644 --- a/osu.Game.Tests/Visual/TestCaseIdleTracker.cs +++ b/osu.Game.Tests/Visual/Components/TestCaseIdleTracker.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -9,7 +9,7 @@ using osu.Game.Input; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Components { [TestFixture] public class TestCaseIdleTracker : ManualInputManagerTestCase @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual { AddStep("move mouse to top left", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre)); - AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle"); + AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); AddStep("nudge mouse", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre + new Vector2(1))); @@ -87,7 +87,7 @@ namespace osu.Game.Tests.Visual AddAssert("check idle", () => !box3.IsIdle); AddAssert("check idle", () => !box4.IsIdle); - AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle"); + AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); } [Test] @@ -96,13 +96,13 @@ namespace osu.Game.Tests.Visual AddStep("move mouse", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); AddAssert("check not idle", () => !box1.IsIdle && !box2.IsIdle && !box3.IsIdle && !box4.IsIdle); - AddUntilStep(() => box1.IsIdle, "Wait for idle"); + AddUntilStep("Wait for idle", () => box1.IsIdle); AddAssert("check not idle", () => !box2.IsIdle && !box3.IsIdle && !box4.IsIdle); - AddUntilStep(() => box2.IsIdle, "Wait for idle"); + AddUntilStep("Wait for idle", () => box2.IsIdle); AddAssert("check not idle", () => !box3.IsIdle && !box4.IsIdle); - AddUntilStep(() => box3.IsIdle, "Wait for idle"); + AddUntilStep("Wait for idle", () => box3.IsIdle); - AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle"); + AddUntilStep("Wait for all idle", () => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle); } private class IdleTrackingBox : CompositeDrawable @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual }, }; - idleTracker.IsIdle.BindValueChanged(idle => box.Colour = idle ? Color4.White : Color4.Black, true); + idleTracker.IsIdle.BindValueChanged(idle => box.Colour = idle.NewValue ? Color4.White : Color4.Black, true); } } } diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs similarity index 89% rename from osu.Game.Tests/Visual/TestCasePollingComponent.cs rename to osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs index b4b9d465e5..6582145f6e 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/Components/TestCasePollingComponent.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Threading.Tasks; @@ -13,7 +13,7 @@ using osu.Game.Online; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Components { public class TestCasePollingComponent : OsuTestCase { @@ -56,6 +56,7 @@ namespace osu.Game.Tests.Visual }); [Test] + [Ignore("polling is threaded, and it's very hard to hook into it correctly")] public void TestInstantPolling() { createPoller(true); @@ -106,8 +107,11 @@ namespace osu.Game.Tests.Visual private void checkCount(int checkValue) { - Logger.Log($"value is {count}"); - AddAssert($"count is {checkValue}", () => count == checkValue); + AddAssert($"count is {checkValue}", () => + { + Logger.Log($"value is {count}"); + return count == checkValue; + }); } private void createPoller(bool instant) => AddStep("create poller", () => diff --git a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs similarity index 95% rename from osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs rename to osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs index 041fce6ce3..4b6ae696fe 100644 --- a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/Components/TestCasePreviewTrackManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Audio; using osu.Game.Beatmaps; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Components { public class TestCasePreviewTrackManager : OsuTestCase, IPreviewTrackOwner { diff --git a/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs b/osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs similarity index 78% rename from osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs rename to osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs index c11bb5d17b..e822e01110 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatDivisorControl.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseBeatDivisorControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -9,7 +9,7 @@ using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Compose.Components; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { public class TestCaseBeatDivisorControl : OsuTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs similarity index 73% rename from osu.Game.Tests/Visual/TestCaseEditorCompose.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs index 5c53fdfac4..aa7c7f5cb3 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorCompose.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit.Compose; using osu.Game.Tests.Beatmaps; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorCompose : EditorClockTestCase @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock); Child = new ComposeScreen(); } } diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs index 9df36b0bc1..499db1b69f 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeRadioButtons.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -7,7 +7,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Screens.Edit.Components.RadioButtons; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorComposeRadioButtons : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs similarity index 93% rename from osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs index f548dfe666..d7712293c3 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorComposeTimeline.cs @@ -1,12 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osuTK; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -14,9 +13,10 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Screens.Edit.Compose.Components.Timeline; +using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorComposeTimeline : EditorClockTestCase @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual } [BackgroundDependencyLoader] - private void load(IAdjustableClock adjustableClock, IBindableBeatmap beatmap) + private void load(IAdjustableClock adjustableClock, IBindable beatmap) { this.adjustableClock = adjustableClock; this.beatmap.BindTo(beatmap); diff --git a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs similarity index 96% rename from osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs index eab799011d..b012d4b52d 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorMenuBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -10,7 +10,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Edit.Components.Menus; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorMenuBar : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs similarity index 98% rename from osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs index 8bbbe6b918..9daba54b58 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorSeekSnapping.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorSeekSnapping : EditorClockTestCase @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual { TimingPoints = { - new TimingControlPoint { Time = 0, BeatLength = 200}, + new TimingControlPoint { Time = 0, BeatLength = 200 }, new TimingControlPoint { Time = 100, BeatLength = 400 }, new TimingControlPoint { Time = 175, BeatLength = 800 }, new TimingControlPoint { Time = 350, BeatLength = 200 }, @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual } }; - Beatmap.Value = new TestWorkingBeatmap(testBeatmap); + Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; } diff --git a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs similarity index 79% rename from osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs rename to osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs index ff28a0aad2..99d6385804 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseEditorSummaryTimeline.cs @@ -1,17 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osuTK; -using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Game.Rulesets.Osu; +using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Game.Tests.Beatmaps; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseEditorSummaryTimeline : EditorClockTestCase @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null); Add(new SummaryTimeline { diff --git a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs b/osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs similarity index 93% rename from osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs rename to osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs index 6620fbeef3..be335fb71f 100644 --- a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseHitObjectComposer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -7,7 +7,6 @@ using JetBrains.Annotations; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Timing; -using osuTK; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; @@ -20,8 +19,9 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Tests.Beatmaps; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] [Cached(Type = typeof(IPlacementHandler))] diff --git a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs b/osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs similarity index 77% rename from osu.Game.Tests/Visual/TestCasePlaybackControl.cs rename to osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs index 4352b2bc3a..7d9b43251e 100644 --- a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs +++ b/osu.Game.Tests/Visual/Editor/TestCasePlaybackControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -10,7 +10,7 @@ using osu.Game.Screens.Edit.Components; using osu.Game.Tests.Beatmaps; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCasePlaybackControl : OsuTestCase @@ -26,10 +26,10 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(200,100) + Size = new Vector2(200, 100) }; - Beatmap.Value = new TestWorkingBeatmap(new Beatmap()); + Beatmap.Value = new TestWorkingBeatmap(new Beatmap(), Clock); Child = playback; } diff --git a/osu.Game.Tests/Visual/TestCaseWaveContainer.cs b/osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs similarity index 85% rename from osu.Game.Tests/Visual/TestCaseWaveContainer.cs rename to osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs index 69f1e33579..e87304ded6 100644 --- a/osu.Game.Tests/Visual/TestCaseWaveContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseWaveContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -12,7 +12,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseWaveContainer : OsuTestCase @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Text = @"Wave Container", }, }, diff --git a/osu.Game.Tests/Visual/TestCaseWaveform.cs b/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseWaveform.cs rename to osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs index f97091e58d..c35e8741c1 100644 --- a/osu.Game.Tests/Visual/TestCaseWaveform.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseWaveform.cs @@ -1,17 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osuTK; -using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { [TestFixture] public class TestCaseWaveform : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs similarity index 96% rename from osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs rename to osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs index 7dca99685e..e2cf1ef28a 100644 --- a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs +++ b/osu.Game.Tests/Visual/Editor/TestCaseZoomableScrollContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -14,7 +14,7 @@ using osu.Game.Screens.Edit.Compose.Components.Timeline; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Editor { public class TestCaseZoomableScrollContainer : ManualInputManagerTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs similarity index 53% rename from osu.Game.Tests/Visual/TestCaseAutoplay.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs index 4abfec4371..2b0254f232 100644 --- a/osu.Game.Tests/Visual/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using System.Linq; @@ -7,10 +7,10 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with an autoplay mod.")] - public class TestCaseAutoplay : TestCasePlayer + public class TestCaseAutoplay : AllPlayersTestCase { protected override Player CreatePlayer(Ruleset ruleset) { @@ -23,11 +23,16 @@ namespace osu.Game.Tests.Visual }; } - protected override bool ContinueCondition(Player player) => base.ContinueCondition(player) && ((ScoreAccessiblePlayer)player).ScoreProcessor.TotalScore > 0; + protected override void AddCheckSteps() + { + AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); + AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + } private class ScoreAccessiblePlayer : Player { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + public new HUDOverlay HUDOverlay => base.HUDOverlay; } } } diff --git a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseBreakOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs index 442ca1322a..dda8005f70 100644 --- a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseBreakOverlay.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps.Timing; using System.Collections.Generic; using NUnit.Framework; +using osu.Game.Beatmaps.Timing; using osu.Game.Screens.Play; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseBreakOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs similarity index 82% rename from osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs index ee97ff7af7..8e43bf6d3a 100644 --- a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseGameplayMenuOverlay.cs @@ -1,42 +1,52 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; -using osuTK.Input; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; +using osu.Game.Input.Bindings; using osu.Game.Screens.Play; using osuTK; +using osuTK.Input; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [Description("player pause/fail screens")] public class TestCaseGameplayMenuOverlay : ManualInputManagerTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseOverlay) }; private FailOverlay failOverlay; - private PauseContainer.PauseOverlay pauseOverlay; + private PauseOverlay pauseOverlay; + + private GlobalActionContainer globalActionContainer; [BackgroundDependencyLoader] - private void load() + private void load(OsuGameBase game) { - Add(pauseOverlay = new PauseContainer.PauseOverlay + Child = globalActionContainer = new GlobalActionContainer(game) { - OnResume = () => Logger.Log(@"Resume"), - OnRetry = () => Logger.Log(@"Retry"), - OnQuit = () => Logger.Log(@"Quit"), - }); + Children = new Drawable[] + { + pauseOverlay = new PauseOverlay + { + OnResume = () => Logger.Log(@"Resume"), + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), + }, + failOverlay = new FailOverlay - Add(failOverlay = new FailOverlay - { - OnRetry = () => Logger.Log(@"Retry"), - OnQuit = () => Logger.Log(@"Quit"), - }); + { + OnRetry = () => Logger.Log(@"Retry"), + OnQuit = () => Logger.Log(@"Quit"), + } + } + }; var retryCount = 0; @@ -76,13 +86,7 @@ namespace osu.Game.Tests.Visual AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First())); AddStep("Hide overlay", () => failOverlay.Hide()); - AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected)); - } - - private void press(Key key) - { - InputManager.PressKey(key); - InputManager.ReleaseKey(key); + AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected.Value)); } /// @@ -92,7 +96,7 @@ namespace osu.Game.Tests.Visual { AddStep("Show overlay", () => pauseOverlay.Show()); - AddStep("Press enter", () => press(Key.Enter)); + AddStep("Press select", () => press(GlobalAction.Select)); AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible); AddStep("Hide overlay", () => pauseOverlay.Hide()); @@ -106,7 +110,7 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -119,7 +123,7 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -132,11 +136,11 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => failOverlay.Show()); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Hide overlay", () => failOverlay.Hide()); } @@ -149,11 +153,11 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => failOverlay.Show()); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => failOverlay.Hide()); } @@ -169,8 +173,8 @@ namespace osu.Game.Tests.Visual AddStep("Down arrow", () => press(Key.Down)); AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); - AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected); - AddAssert("Second button selected", () => secondButton.Selected); + AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected.Value); + AddAssert("Second button selected", () => secondButton.Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -190,8 +194,8 @@ namespace osu.Game.Tests.Visual AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Second button not selected", () => !secondButton.Selected); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + AddAssert("Second button not selected", () => !secondButton.Selected.Value); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -208,7 +212,7 @@ namespace osu.Game.Tests.Visual AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero)); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); // Initial state condition + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); // Initial state condition AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -265,9 +269,22 @@ namespace osu.Game.Tests.Visual pauseOverlay.OnRetry = lastAction; lastAction = null; } + return triggered; }); AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); } + + private void press(Key key) + { + InputManager.PressKey(key); + InputManager.ReleaseKey(key); + } + + private void press(GlobalAction action) + { + globalActionContainer.TriggerPressed(action); + globalActionContainer.TriggerReleased(action); + } } } diff --git a/osu.Game.Tests/Visual/TestCaseHoldForMenuButton.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs similarity index 76% rename from osu.Game.Tests/Visual/TestCaseHoldForMenuButton.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs index 944921bc2e..14e9c7cdb6 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldForMenuButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseHoldForMenuButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using NUnit.Framework; @@ -10,7 +10,7 @@ using osu.Game.Screens.Play.HUD; using osuTK; using osuTK.Input; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [Description("'Hold to Quit' UI element")] public class TestCaseHoldForMenuButton : ManualInputManagerTestCase @@ -32,9 +32,9 @@ namespace osu.Game.Tests.Visual var text = holdForMenuButton.Children.OfType().First(); AddStep("Trigger text fade in", () => InputManager.MoveMouseTo(holdForMenuButton)); - AddUntilStep(() => text.IsPresent && !exitAction, "Text visible"); + AddUntilStep("Text visible", () => text.IsPresent && !exitAction); AddStep("Trigger text fade out", () => InputManager.MoveMouseTo(Vector2.One)); - AddUntilStep(() => !text.IsPresent && !exitAction, "Text is not visible"); + AddUntilStep("Text is not visible", () => !text.IsPresent && !exitAction); AddStep("Trigger exit action", () => { @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual AddAssert("action not triggered", () => !exitAction); AddStep("Trigger exit action", () => InputManager.PressButton(MouseButton.Left)); - AddUntilStep(() => exitAction, $"{nameof(holdForMenuButton.Action)} was triggered"); + AddUntilStep($"{nameof(holdForMenuButton.Action)} was triggered", () => exitAction); } } } diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseKeyCounter.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs index 465b943651..f616ffe4ed 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseKeyCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -11,7 +11,7 @@ using osu.Framework.Timing; using osu.Game.Screens.Play; using osuTK.Input; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseKeyCounter : ManualInputManagerTestCase @@ -39,7 +39,6 @@ namespace osu.Game.Tests.Visual }, }; - AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); diff --git a/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs similarity index 80% rename from osu.Game.Tests/Visual/TestCaseMedalOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs index c2df8d33ca..dd686c36e6 100644 --- a/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseMedalOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.MedalSplash; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseMedalOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs new file mode 100644 index 0000000000..1ed61c9fe1 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePause.cs @@ -0,0 +1,152 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCasePause : PlayerTestCase + { + protected new PausePlayer Player => (PausePlayer)base.Player; + + public TestCasePause() + : base(new OsuRuleset()) + { + } + + [Test] + public void TestPauseResume() + { + pauseAndConfirm(); + resumeAndConfirm(); + } + + [Test] + public void TestPauseTooSoon() + { + pauseAndConfirm(); + resumeAndConfirm(); + + pause(); + + confirmClockRunning(true); + confirmPauseOverlayShown(false); + } + + [Test] + public void TestExitTooSoon() + { + pauseAndConfirm(); + + resume(); + + AddStep("exit too soon", () => Player.Exit()); + + confirmClockRunning(true); + confirmPauseOverlayShown(false); + + AddAssert("not exited", () => Player.IsCurrentScreen()); + } + + [Test] + public void TestPauseAfterFail() + { + AddUntilStep("wait for fail", () => Player.HasFailed); + AddAssert("fail overlay shown", () => Player.FailOverlayVisible); + + confirmClockRunning(false); + + pause(); + + confirmClockRunning(false); + confirmPauseOverlayShown(false); + + AddAssert("fail overlay still shown", () => Player.FailOverlayVisible); + + exitAndConfirm(); + } + + [Test] + public void TestExitFromGameplay() + { + AddStep("exit", () => Player.Exit()); + + confirmPaused(); + + exitAndConfirm(); + } + + [Test] + public void TestExitFromPause() + { + pauseAndConfirm(); + exitAndConfirm(); + } + + private void pauseAndConfirm() + { + pause(); + confirmPaused(); + } + + private void resumeAndConfirm() + { + resume(); + confirmResumed(); + } + + private void exitAndConfirm() + { + AddUntilStep("player not exited", () => Player.IsCurrentScreen()); + AddStep("exit", () => Player.Exit()); + confirmExited(); + } + + private void confirmPaused() + { + confirmClockRunning(false); + AddAssert("pause overlay shown", () => Player.PauseOverlayVisible); + } + + private void confirmResumed() + { + confirmClockRunning(true); + confirmPauseOverlayShown(false); + } + + private void confirmExited() + { + AddUntilStep("player exited", () => !Player.IsCurrentScreen()); + } + + private void pause() => AddStep("pause", () => Player.Pause()); + private void resume() => AddStep("resume", () => Player.Resume()); + + private void confirmPauseOverlayShown(bool isShown) => + AddAssert("pause overlay " + (isShown ? "shown" : "hidden"), () => Player.PauseOverlayVisible == isShown); + + private void confirmClockRunning(bool isRunning) => + AddAssert("clock " + (isRunning ? "running" : "stopped"), () => Player.GameplayClockContainer.GameplayClock.IsRunning == isRunning); + + protected override bool AllowFail => true; + + protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer(); + + protected class PausePlayer : Player + { + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; + + public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; + } + } +} diff --git a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs similarity index 54% rename from osu.Game.Tests/Visual/TestCasePlayerLoader.cs rename to osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs index 6ec3bd108b..be2a21d23d 100644 --- a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerLoader.cs @@ -1,38 +1,53 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Screens; using osu.Game.Screens.Play; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { public class TestCasePlayerLoader : ManualInputManagerTestCase { private PlayerLoader loader; + private readonly OsuScreenStack stack; + + public TestCasePlayerLoader() + { + InputManager.Add(stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }); + } [BackgroundDependencyLoader] private void load(OsuGameBase game) { Beatmap.Value = new DummyWorkingBeatmap(game); - AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(() => new Player + AddStep("load dummy beatmap", () => stack.Push(loader = new PlayerLoader(() => new Player { AllowPause = false, AllowLeadIn = false, AllowResults = false, }))); + AddUntilStep("wait for current", () => loader.IsCurrentScreen()); + AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); - AddUntilStep(() => !loader.IsCurrentScreen, "wait for no longer current"); + AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); + + AddStep("exit loader", () => loader.Exit()); + + AddUntilStep("wait for no longer alive", () => !loader.IsAlive); AddStep("load slow dummy beatmap", () => { SlowLoadPlayer slow = null; - Add(loader = new PlayerLoader(() => slow = new SlowLoadPlayer + stack.Push(loader = new PlayerLoader(() => slow = new SlowLoadPlayer { AllowPause = false, AllowLeadIn = false, @@ -42,7 +57,7 @@ namespace osu.Game.Tests.Visual Scheduler.AddDelayed(() => slow.Ready = true, 5000); }); - AddUntilStep(() => !loader.IsCurrentScreen, "wait for no longer current"); + AddUntilStep("wait for no longer current", () => !loader.IsCurrentScreen()); } protected class SlowLoadPlayer : Player @@ -57,5 +72,4 @@ namespace osu.Game.Tests.Visual } } } - } diff --git a/osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs new file mode 100644 index 0000000000..5937d489f2 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCasePlayerReferenceLeaking.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Lists; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCasePlayerReferenceLeaking : AllPlayersTestCase + { + private readonly WeakList workingWeakReferences = new WeakList(); + + private readonly WeakList playerWeakReferences = new WeakList(); + + protected override void AddCheckSteps() + { + AddUntilStep("no leaked beatmaps", () => + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + int count = 0; + + workingWeakReferences.ForEachAlive(_ => count++); + return count == 1; + }); + + AddUntilStep("no leaked players", () => + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + int count = 0; + + playerWeakReferences.ForEachAlive(_ => count++); + return count == 1; + }); + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock) + { + var working = base.CreateWorkingBeatmap(beatmap, clock); + workingWeakReferences.Add(working); + return working; + } + + protected override Player CreatePlayer(Ruleset ruleset) + { + var player = base.CreatePlayer(ruleset); + playerWeakReferences.Add(player); + return player; + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs new file mode 100644 index 0000000000..b98ce96fbb --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplay.cs @@ -0,0 +1,40 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.ComponentModel; +using System.Linq; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + [Description("Player instantiated with a replay.")] + public class TestCaseReplay : AllPlayersTestCase + { + protected override Player CreatePlayer(Ruleset ruleset) + { + var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo); + + return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); + } + + protected override void AddCheckSteps() + { + AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); + AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + public new HUDOverlay HUDOverlay => base.HUDOverlay; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score) + { + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs index a57cc5b79d..2fdfda0d80 100644 --- a/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseReplaySettingsOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseReplaySettingsOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs similarity index 84% rename from osu.Game.Tests/Visual/TestCaseResults.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs index 98aaa23beb..d9da45f39a 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseResults.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -13,10 +13,10 @@ using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking.Pages; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseResults : OsuTestCase + public class TestCaseResults : ScreenTestCase { private BeatmapManager beatmaps; @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - Add(new SoloResults(new ScoreInfo + LoadScreen(new SoloResults(new ScoreInfo { TotalScore = 2845370, Accuracy = 0.98, diff --git a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseScoreCounter.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs index c32ca104ed..3dd5c99e45 100644 --- a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseScoreCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -9,7 +9,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseScoreCounter : OsuTestCase @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual AddStep(@"Hit! :D", delegate { - score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0); + score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current.Value > 0 ? comboCounter.Current.Value - 1 : 0) / 25.0); comboCounter.Increment(); numerator++; denominator++; diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs index 3ac85cd846..a1cec1e18f 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseScrollingHitObjects.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; -using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -15,8 +14,9 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseScrollingHitObjects : OsuTestCase diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs new file mode 100644 index 0000000000..a9fbf35d37 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseSkinReloadable.cs @@ -0,0 +1,153 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Audio.Sample; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Skinning; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestCaseSkinReloadable : OsuTestCase + { + [Test] + public void TestInitialLoad() + { + var secondarySource = new SecondarySource(); + SkinConsumer consumer = null; + + AddStep("setup layout", () => + { + Child = new SkinSourceContainer + { + RelativeSizeAxes = Axes.Both, + Child = new LocalSkinOverrideContainer(secondarySource) + { + RelativeSizeAxes = Axes.Both, + Child = consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true) + } + }; + }); + + AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); + AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); + } + + [Test] + public void TestOverride() + { + var secondarySource = new SecondarySource(); + + SkinConsumer consumer = null; + Container target = null; + + AddStep("setup layout", () => + { + Child = new SkinSourceContainer + { + RelativeSizeAxes = Axes.Both, + Child = target = new LocalSkinOverrideContainer(secondarySource) + { + RelativeSizeAxes = Axes.Both, + } + }; + }); + + AddStep("add permissive", () => target.Add(consumer = new SkinConsumer("test", name => new NamedBox("Default Implementation"), source => true))); + AddAssert("consumer using override source", () => consumer.Drawable is SecondarySourceBox); + AddAssert("skinchanged only called once", () => consumer.SkinChangedCount == 1); + } + + private class NamedBox : Container + { + public NamedBox(string name) + { + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new SpriteText + { + Font = OsuFont.Default.With(size: 40), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = name + } + }; + } + } + + private class SkinConsumer : SkinnableDrawable + { + public new Drawable Drawable => base.Drawable; + public int SkinChangedCount { get; private set; } + + public SkinConsumer(string name, Func defaultImplementation, Func allowFallback = null, bool restrictSize = true) + : base(name, defaultImplementation, allowFallback, restrictSize) + { + } + + protected override void SkinChanged(ISkinSource skin, bool allowFallback) + { + base.SkinChanged(skin, allowFallback); + SkinChangedCount++; + } + } + + private class BaseSourceBox : NamedBox + { + public BaseSourceBox() + : base("Base Source") + { + } + } + + private class SecondarySourceBox : NamedBox + { + public SecondarySourceBox() + : base("Secondary Source") + { + } + } + + private class SecondarySource : ISkinSource + { + public event Action SourceChanged; + + public void TriggerSourceChanged() => SourceChanged?.Invoke(); + + public Drawable GetDrawableComponent(string componentName) => new SecondarySourceBox(); + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + } + + private class SkinSourceContainer : Container, ISkinSource + { + public event Action SourceChanged; + + public void TriggerSourceChanged() => SourceChanged?.Invoke(); + + public Drawable GetDrawableComponent(string componentName) => new BaseSourceBox(); + + public Texture GetTexture(string componentName) => throw new NotImplementedException(); + + public SampleChannel GetSample(string sampleName) => throw new NotImplementedException(); + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException(); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseSkipButton.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs similarity index 50% rename from osu.Game.Tests/Visual/TestCaseSkipButton.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs index 4f381fd7a8..b46d79ac04 100644 --- a/osu.Game.Tests/Visual/TestCaseSkipButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseSkipOverlay.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Screens.Play; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] - public class TestCaseSkipButton : OsuTestCase + public class TestCaseSkipOverlay : OsuTestCase { protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs new file mode 100644 index 0000000000..e17dcef19c --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseSongProgress.cs @@ -0,0 +1,98 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Framework.Timing; +using osu.Game.Rulesets.Objects; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual.Gameplay +{ + [TestFixture] + public class TestCaseSongProgress : OsuTestCase + { + private readonly SongProgress progress; + private readonly TestSongProgressGraph graph; + + private readonly StopwatchClock clock; + + [Cached] + private readonly GameplayClock gameplayClock; + + private readonly FramedClock framedClock; + + public TestCaseSongProgress() + { + clock = new StopwatchClock(true); + + gameplayClock = new GameplayClock(framedClock = new FramedClock(clock)); + + Add(progress = new SongProgress + { + RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }); + + Add(graph = new TestSongProgressGraph + { + RelativeSizeAxes = Axes.X, + Height = 200, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + + AddWaitStep("wait some", 5); + AddAssert("ensure not created", () => graph.CreationCount == 0); + + AddStep("display values", displayNewValues); + AddWaitStep("wait some", 5); + AddUntilStep("wait for creation count", () => graph.CreationCount == 1); + + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); + AddWaitStep("wait some", 5); + AddUntilStep("wait for creation count", () => graph.CreationCount == 1); + + AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); + AddWaitStep("wait some", 5); + AddUntilStep("wait for creation count", () => graph.CreationCount == 1); + AddRepeatStep("New Values", displayNewValues, 5); + + AddWaitStep("wait some", 5); + AddAssert("ensure debounced", () => graph.CreationCount == 2); + } + + private void displayNewValues() + { + List objects = new List(); + for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) + objects.Add(new HitObject { StartTime = i }); + + progress.Objects = objects; + graph.Objects = objects; + + progress.RequestSeek = pos => clock.Seek(pos); + } + + protected override void Update() + { + base.Update(); + framedClock.ProcessFrame(); + } + + private class TestSongProgressGraph : SongProgressGraph + { + public int CreationCount { get; private set; } + + protected override void RecreateGraph() + { + base.RecreateGraph(); + CreationCount++; + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseStoryboard.cs b/osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs similarity index 80% rename from osu.Game.Tests/Visual/TestCaseStoryboard.cs rename to osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs index 42c0134afa..651683a671 100644 --- a/osu.Game.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestCaseStoryboard.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -12,7 +13,7 @@ using osu.Game.Overlays; using osu.Game.Storyboards.Drawables; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Gameplay { [TestFixture] public class TestCaseStoryboard : OsuTestCase @@ -49,7 +50,10 @@ namespace osu.Game.Tests.Visual }); AddStep("Restart", restart); - AddToggleStep("Passing", passing => { if (storyboard != null) storyboard.Passing = passing; }); + AddToggleStep("Passing", passing => + { + if (storyboard != null) storyboard.Passing = passing; + }); } [BackgroundDependencyLoader] @@ -58,15 +62,15 @@ namespace osu.Game.Tests.Visual Beatmap.ValueChanged += beatmapChanged; } - private void beatmapChanged(WorkingBeatmap working) - => loadStoryboard(working); + private void beatmapChanged(ValueChangedEvent e) + => loadStoryboard(e.NewValue); private void restart() { var track = Beatmap.Value.Track; track.Reset(); - loadStoryboard(Beatmap); + loadStoryboard(Beatmap.Value); track.Start(); } @@ -78,7 +82,7 @@ namespace osu.Game.Tests.Visual var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; storyboardContainer.Clock = decoupledClock; - storyboard = working.Storyboard.CreateDrawable(Beatmap); + storyboard = working.Storyboard.CreateDrawable(Beatmap.Value); storyboard.Passing = false; storyboardContainer.Add(storyboard); diff --git a/osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs new file mode 100644 index 0000000000..68a1ceec16 --- /dev/null +++ b/osu.Game.Tests/Visual/Menus/TestCaseDisclaimer.cs @@ -0,0 +1,34 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Online.API; +using osu.Game.Screens.Menu; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Menus +{ + public class TestCaseDisclaimer : ScreenTestCase + { + [Cached(typeof(IAPIProvider))] + private readonly DummyAPIAccess api = new DummyAPIAccess(); + + [BackgroundDependencyLoader] + private void load() + { + Add(api); + + AddStep("load disclaimer", () => LoadScreen(new Disclaimer())); + + AddStep("toggle support", () => + { + api.LocalUser.Value = new User + { + Username = api.LocalUser.Value.Username, + Id = api.LocalUser.Value.Id, + IsSupporter = !api.LocalUser.Value.IsSupporter, + }; + }); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseIntroSequence.cs b/osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseIntroSequence.cs rename to osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs index 9ce8a4ddd6..0b924e56f5 100644 --- a/osu.Game.Tests/Visual/TestCaseIntroSequence.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseIntroSequence.cs @@ -1,17 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Timing; using osu.Game.Screens.Menu; +using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Menus { [TestFixture] public class TestCaseIntroSequence : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs similarity index 82% rename from osu.Game.Tests/Visual/TestCaseLoaderAnimation.cs rename to osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs index da2427ff6f..899f9d431b 100644 --- a/osu.Game.Tests/Visual/TestCaseLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseLoaderAnimation.cs @@ -1,14 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; using osu.Game.Screens; using osu.Game.Screens.Menu; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Menus { [TestFixture] public class TestCaseLoaderAnimation : OsuTestCase @@ -24,30 +25,30 @@ namespace osu.Game.Tests.Visual bool logoVisible = false; AddStep("almost instant display", () => Child = loader = new TestLoader(250)); - AddUntilStep(() => + AddUntilStep("loaded", () => { logoVisible = loader.Logo?.Alpha > 0; return loader.Logo != null && loader.ScreenLoaded; - }, "loaded"); + }); AddAssert("logo not visible", () => !logoVisible); AddStep("short load", () => Child = loader = new TestLoader(800)); - AddUntilStep(() => + AddUntilStep("loaded", () => { logoVisible = loader.Logo?.Alpha > 0; return loader.Logo != null && loader.ScreenLoaded; - }, "loaded"); + }); AddAssert("logo visible", () => logoVisible); - AddUntilStep(() => loader.Logo?.Alpha == 0, "logo gone"); + AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); AddStep("longer load", () => Child = loader = new TestLoader(1400)); - AddUntilStep(() => + AddUntilStep("loaded", () => { logoVisible = loader.Logo?.Alpha > 0; return loader.Logo != null && loader.ScreenLoaded; - }, "loaded"); + }); AddAssert("logo visible", () => logoVisible); - AddUntilStep(() => loader.Logo?.Alpha == 0, "logo gone"); + AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); } private class TestLoader : Loader @@ -57,7 +58,7 @@ namespace osu.Game.Tests.Visual public OsuLogo Logo; private TestScreen screen; - public bool ScreenLoaded => screen.IsCurrentScreen; + public bool ScreenLoaded => screen.IsCurrentScreen(); public TestLoader(double delay) { @@ -96,7 +97,7 @@ namespace osu.Game.Tests.Visual { public TestScreen() { - Child = new Box + InternalChild = new Box { RelativeSizeAxes = Axes.Both, Colour = Color4.DarkSlateGray, @@ -107,7 +108,7 @@ namespace osu.Game.Tests.Visual protected override void LogoArriving(OsuLogo logo, bool resuming) { base.LogoArriving(logo, resuming); - Child.FadeInFromZero(200); + InternalChild.FadeInFromZero(200); } } } diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs similarity index 70% rename from osu.Game.Tests/Visual/TestCaseToolbar.cs rename to osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs index 96f14e6b32..4da17f9944 100644 --- a/osu.Game.Tests/Visual/TestCaseToolbar.cs +++ b/osu.Game.Tests/Visual/Menus/TestCaseToolbar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Toolbar; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Menus { [TestFixture] public class TestCaseToolbar : OsuTestCase @@ -24,10 +24,13 @@ namespace osu.Game.Tests.Visual public TestCaseToolbar() { var toolbar = new Toolbar { State = Visibility.Visible }; + ToolbarNotificationButton notificationButton = null; - Add(toolbar); - - var notificationButton = toolbar.Children.OfType().Last().Children.OfType().First(); + AddStep("create toolbar", () => + { + Add(toolbar); + notificationButton = toolbar.Children.OfType().Last().Children.OfType().First(); + }); void setNotifications(int count) => AddStep($"set notification count to {count}", () => notificationButton.NotificationCount.Value = count); diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs similarity index 86% rename from osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs index 6b5bc875f1..34de61cb5b 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseLoungeRoomsContainer.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; @@ -14,9 +14,9 @@ using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Users; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseLoungeRoomsContainer : OsuTestCase + public class TestCaseLoungeRoomsContainer : MultiplayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual AddAssert("first room removed", () => container.Rooms.All(r => r.Room.RoomID.Value != 0)); AddStep("select first room", () => container.Rooms.First().Action?.Invoke()); - AddAssert("first room selected", () => container.SelectedRoom.Value == roomManager.Rooms.First()); + AddAssert("first room selected", () => Room == roomManager.Rooms.First()); AddStep("join first room", () => container.Rooms.First().Action?.Invoke()); AddAssert("first room joined", () => roomManager.Rooms.First().Status.Value is JoinedRoomStatus); @@ -71,7 +71,11 @@ namespace osu.Game.Tests.Visual private class TestRoomManager : IRoomManager { - public event Action RoomsUpdated; + public event Action RoomsUpdated + { + add { } + remove { } + } public readonly BindableList Rooms = new BindableList(); IBindableList IRoomManager.Rooms => Rooms; @@ -85,10 +89,6 @@ namespace osu.Game.Tests.Visual public void PartRoom() { } - - public void Filter(FilterCriteria criteria) - { - } } private class JoinedRoomStatus : RoomStatus diff --git a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs similarity index 70% rename from osu.Game.Tests/Visual/TestCaseMatchHeader.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs index 4c8cdbfd19..81cb90c7cd 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -10,9 +10,9 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Multi.Match.Components; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchHeader : OsuTestCase + public class TestCaseMatchHeader : MultiplayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -21,11 +21,7 @@ namespace osu.Game.Tests.Visual public TestCaseMatchHeader() { - var room = new Room(); - - var header = new Header(room); - - room.Playlist.Add(new PlaylistItem + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { @@ -46,9 +42,9 @@ namespace osu.Game.Tests.Visual } }); - room.Type.Value = new GameTypeTimeshift(); + Room.Type.Value = new GameTypeTimeshift(); - Child = header; + Child = new Header(); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs similarity index 76% rename from osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs index 8e733d388a..d2dc417100 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchHostInfo.cs @@ -1,14 +1,14 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { public class TestCaseMatchHostInfo : OsuTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs similarity index 66% rename from osu.Game.Tests/Visual/TestCaseMatchInfo.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs index 4da500427b..6b04b71da4 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchInfo.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -11,10 +11,10 @@ using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Match.Components; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMatchInfo : OsuTestCase + public class TestCaseMatchInfo : MultiplayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -27,18 +27,15 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - var room = new Room(); + Add(new Info()); - Info info = new Info(room); - Add(info); - - AddStep(@"set name", () => room.Name.Value = @"Room Name?"); - AddStep(@"set availability", () => room.Availability.Value = RoomAvailability.FriendsOnly); - AddStep(@"set status", () => room.Status.Value = new RoomStatusPlaying()); + AddStep(@"set name", () => Room.Name.Value = @"Room Name?"); + AddStep(@"set availability", () => Room.Availability.Value = RoomAvailability.FriendsOnly); + AddStep(@"set status", () => Room.Status.Value = new RoomStatusPlaying()); AddStep(@"set beatmap", () => { - room.Playlist.Clear(); - room.Playlist.Add(new PlaylistItem + Room.Playlist.Clear(); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { @@ -54,14 +51,14 @@ namespace osu.Game.Tests.Visual }); }); - AddStep(@"change name", () => room.Name.Value = @"Room Name!"); - AddStep(@"change availability", () => room.Availability.Value = RoomAvailability.InviteOnly); - AddStep(@"change status", () => room.Status.Value = new RoomStatusOpen()); - AddStep(@"null beatmap", () => room.Playlist.Clear()); + AddStep(@"change name", () => Room.Name.Value = @"Room Name!"); + AddStep(@"change availability", () => Room.Availability.Value = RoomAvailability.InviteOnly); + AddStep(@"change status", () => Room.Status.Value = new RoomStatusOpen()); + AddStep(@"null beatmap", () => Room.Playlist.Clear()); AddStep(@"change beatmap", () => { - room.Playlist.Clear(); - room.Playlist.Add(new PlaylistItem + Room.Playlist.Clear(); + Room.Playlist.Add(new PlaylistItem { Beatmap = new BeatmapInfo { diff --git a/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs similarity index 79% rename from osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs index cf475de1f0..8ec323dbc3 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchLeaderboard.cs @@ -1,23 +1,24 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Online.API; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchLeaderboard : OsuTestCase + public class TestCaseMatchLeaderboard : MultiplayerTestCase { public TestCaseMatchLeaderboard() { - Add(new MatchLeaderboard(new Room { RoomID = { Value = 3 } }) + Room.RoomID.Value = 3; + + Add(new MatchLeaderboard { Origin = Anchor.Centre, Anchor = Anchor.Centre, @@ -27,7 +28,7 @@ namespace osu.Game.Tests.Visual } [Resolved] - private APIAccess api { get; set; } + private IAPIProvider api { get; set; } [BackgroundDependencyLoader] private void load() diff --git a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs similarity index 54% rename from osu.Game.Tests/Visual/TestCaseMatchParticipants.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs index 27aeb9b5eb..5382726516 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchParticipants.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchParticipants.cs @@ -1,32 +1,22 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] - public class TestCaseMatchParticipants : OsuTestCase + public class TestCaseMatchParticipants : MultiplayerTestCase { - private readonly Bindable maxParticipants = new Bindable(); - private readonly Bindable> users = new Bindable>(); - public TestCaseMatchParticipants() { - Participants participants; + Add(new Participants { RelativeSizeAxes = Axes.Both }); - Add(participants = new Participants { RelativeSizeAxes = Axes.Both }); - - participants.MaxParticipants.BindTo(maxParticipants); - participants.Users.BindTo(users); - - AddStep(@"set max to null", () => maxParticipants.Value = null); - AddStep(@"set users", () => users.Value = new[] + AddStep(@"set max to null", () => Room.MaxParticipants.Value = null); + AddStep(@"set users", () => Room.Participants.Value = new[] { new User { @@ -54,9 +44,9 @@ namespace osu.Game.Tests.Visual }, }); - AddStep(@"set max", () => maxParticipants.Value = 10); - AddStep(@"clear users", () => users.Value = new User[] { }); - AddStep(@"set max to null", () => maxParticipants.Value = null); + AddStep(@"set max", () => Room.MaxParticipants.Value = 10); + AddStep(@"clear users", () => Room.Participants.Value = new User[] { }); + AddStep(@"set max to null", () => Room.MaxParticipants.Value = null); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMatchResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs similarity index 70% rename from osu.Game.Tests/Visual/TestCaseMatchResults.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs index 086f329608..69606c9ba7 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchResults.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchResults.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Ranking; @@ -17,9 +16,9 @@ using osu.Game.Screens.Multi.Ranking.Types; using osu.Game.Screens.Ranking; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchResults : OsuTestCase + public class TestCaseMatchResults : MultiplayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -38,68 +37,52 @@ namespace osu.Game.Tests.Visual if (beatmapInfo != null) Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); - Child = new TestMatchResults(new ScoreInfo + Room.RoomID.Value = 1; + Room.Name.Value = "an awesome room"; + + LoadScreen(new TestMatchResults(new ScoreInfo { User = new User { Id = 10 }, - }); + })); } private class TestMatchResults : MatchResults { - private readonly Room room; - public TestMatchResults(ScoreInfo score) - : this(score, new Room - { - RoomID = { Value = 1 }, - Name = { Value = "an awesome room" } - }) + : base(score) { } - public TestMatchResults(ScoreInfo score, Room room) - : base(score, room) - { - this.room = room; - } - - protected override IEnumerable CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap, room) }; + protected override IEnumerable CreateResultPages() => new[] { new TestRoomLeaderboardPageInfo(Score, Beatmap.Value) }; } private class TestRoomLeaderboardPageInfo : RoomLeaderboardPageInfo { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; - private readonly Room room; - public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room) - : base(score, beatmap, room) + public TestRoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) + : base(score, beatmap) { this.score = score; this.beatmap = beatmap; - this.room = room; } - public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap, room); + public override ResultsPage CreatePage() => new TestRoomLeaderboardPage(score, beatmap); } private class TestRoomLeaderboardPage : RoomLeaderboardPage { - public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) - : base(score, beatmap, room) + public TestRoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap) + : base(score, beatmap) { } - protected override MatchLeaderboard CreateLeaderboard(Room room) => new TestMatchLeaderboard(room); + protected override MatchLeaderboard CreateLeaderboard() => new TestMatchLeaderboard(); } private class TestMatchLeaderboard : RoomLeaderboardPage.ResultsMatchLeaderboard { - public TestMatchLeaderboard(Room room) - : base(room) - { - } - protected override APIRequest FetchScores(Action> scoresCallback) { var scores = Enumerable.Range(0, 50).Select(createRoomScore).ToArray(); diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs similarity index 75% rename from osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs index 6f084def48..51854800e3 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMatchSettingsOverlay.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -13,12 +13,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match.Components; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { - public class TestCaseMatchSettingsOverlay : OsuTestCase + public class TestCaseMatchSettingsOverlay : MultiplayerTestCase { public override IReadOnlyList RequiredTypes => new[] { @@ -28,14 +27,14 @@ namespace osu.Game.Tests.Visual [Cached(Type = typeof(IRoomManager))] private TestRoomManager roomManager = new TestRoomManager(); - private Room room; private TestRoomSettings settings; [SetUp] public void Setup() => Schedule(() => { - room = new Room(); - settings = new TestRoomSettings(room) + Room = new Room(); + + settings = new TestRoomSettings { RelativeSizeAxes = Axes.Both, State = Visibility.Visible @@ -49,20 +48,20 @@ namespace osu.Game.Tests.Visual { AddStep("clear name and beatmap", () => { - room.Name.Value = ""; - room.Playlist.Clear(); + Room.Name.Value = ""; + Room.Playlist.Clear(); }); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set name", () => room.Name.Value = "Room name"); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddStep("set name", () => Room.Name.Value = "Room name"); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); - AddStep("set beatmap", () => room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo })); - AddAssert("button enabled", () => settings.ApplyButton.Enabled); + AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo })); + AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); - AddStep("clear name", () => room.Name.Value = ""); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddStep("clear name", () => Room.Name.Value = ""); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); } [Test] @@ -112,22 +111,17 @@ namespace osu.Game.Tests.Visual settings.ApplyButton.Action.Invoke(); }); - AddUntilStep(() => !settings.ErrorText.IsPresent, "error not displayed"); + AddUntilStep("error not displayed", () => !settings.ErrorText.IsPresent); } private class TestRoomSettings : MatchSettingsOverlay { - public new TriangleButton ApplyButton => base.ApplyButton; + public TriangleButton ApplyButton => Settings.ApplyButton; - public new OsuTextBox NameField => base.NameField; - public new OsuDropdown DurationField => base.DurationField; + public OsuTextBox NameField => Settings.NameField; + public OsuDropdown DurationField => Settings.DurationField; - public new OsuSpriteText ErrorText => base.ErrorText; - - public TestRoomSettings(Room room) - : base(room) - { - } + public OsuSpriteText ErrorText => Settings.ErrorText; } private class TestRoomManager : IRoomManager @@ -136,7 +130,11 @@ namespace osu.Game.Tests.Visual public Func CreateRequested; - public event Action RoomsUpdated; + public event Action RoomsUpdated + { + add { } + remove { } + } public IBindableList Rooms { get; } = null; @@ -154,8 +152,6 @@ namespace osu.Game.Tests.Visual public void JoinRoom(Room room, Action onSuccess = null, Action onError = null) => throw new NotImplementedException(); public void PartRoom() => throw new NotImplementedException(); - - public void Filter(FilterCriteria criteria) => throw new NotImplementedException(); } } } diff --git a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs similarity index 57% rename from osu.Game.Tests/Visual/TestCaseMultiHeader.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs index 602108d078..b49bb7fd84 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiHeader.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiHeader.cs @@ -1,12 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Screens; using osu.Game.Screens; using osu.Game.Screens.Multi; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { [TestFixture] public class TestCaseMultiHeader : OsuTestCase @@ -15,15 +16,15 @@ namespace osu.Game.Tests.Visual { int index = 0; - OsuScreen currentScreen = new TestMultiplayerSubScreen(index); + OsuScreenStack screenStack = new OsuScreenStack(new TestMultiplayerSubScreen(index)) { RelativeSizeAxes = Axes.Both }; Children = new Drawable[] { - currentScreen, - new Header(currentScreen) + screenStack, + new Header(screenStack) }; - AddStep("push multi screen", () => currentScreen.Push(currentScreen = new TestMultiplayerSubScreen(++index))); + AddStep("push multi screen", () => screenStack.CurrentScreen.Push(new TestMultiplayerSubScreen(++index))); } private class TestMultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen diff --git a/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs new file mode 100644 index 0000000000..ef381efd67 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseMultiScreen.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + [TestFixture] + public class TestCaseMultiScreen : ScreenTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(Screens.Multi.Multiplayer), + typeof(LoungeSubScreen), + typeof(FilterControl) + }; + + public TestCaseMultiScreen() + { + Screens.Multi.Multiplayer multi = new Screens.Multi.Multiplayer(); + + AddStep(@"show", () => LoadScreen(multi)); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseRoomStatus.cs b/osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs similarity index 88% rename from osu.Game.Tests/Visual/TestCaseRoomStatus.cs rename to osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs index d44b399a95..a7c7d41ed4 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomStatus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestCaseRoomStatus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -9,7 +9,7 @@ using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Screens.Multi.Lounge.Components; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Multiplayer { public class TestCaseRoomStatus : OsuTestCase { diff --git a/osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs new file mode 100644 index 0000000000..5cdb90b61f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestCaseAccountCreationOverlay.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.API; +using osu.Game.Overlays; +using osu.Game.Overlays.AccountCreation; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestCaseAccountCreationOverlay : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ErrorTextFlowContainer), + typeof(AccountCreationBackground), + typeof(ScreenEntry), + typeof(ScreenWarning), + typeof(ScreenWelcome), + typeof(AccountCreationScreen), + }; + + [Cached(typeof(IAPIProvider))] + private DummyAPIAccess api = new DummyAPIAccess(); + + public TestCaseAccountCreationOverlay() + { + Container userPanelArea; + AccountCreationOverlay accountCreation; + + Children = new Drawable[] + { + api, + accountCreation = new AccountCreationOverlay(), + userPanelArea = new Container + { + Padding = new MarginPadding(10), + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + }; + + api.Logout(); + api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); + + AddStep("show", () => accountCreation.State = Visibility.Visible); + AddStep("logout", () => api.Logout()); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs b/osu.Game.Tests/Visual/Online/TestCaseBadgeContainer.cs similarity index 91% rename from osu.Game.Tests/Visual/TestCaseBadgeContainer.cs rename to osu.Game.Tests/Visual/Online/TestCaseBadgeContainer.cs index 8177e2e272..631cb190d2 100644 --- a/osu.Game.Tests/Visual/TestCaseBadgeContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseBadgeContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseBadgeContainer : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs similarity index 98% rename from osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs rename to osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs index 025562f75f..e2985623fc 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseBeatmapSetOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -14,7 +14,7 @@ using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseBeatmapSetOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseChannelTabControl.cs rename to osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs index 1127402adb..fdc3d5394f 100644 --- a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChannelTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -15,7 +15,7 @@ using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { public class TestCaseChannelTabControl : OsuTestCase { @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual }); channelTabControl.OnRequestLeave += channel => channelTabControl.RemoveChannel(channel); - channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.ToString(); + channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.NewValue.ToString(); AddStep("Add random private channel", addRandomPrivateChannel); AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2); @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual AddStep("set second channel", () => channelTabControl.Current.Value = channelTabControl.Items.Skip(1).First()); AddAssert("selector tab is inactive", () => !channelTabControl.ChannelSelectorActive.Value); - AddUntilStep(() => + AddUntilStep("remove all channels", () => { var first = channelTabControl.Items.First(); if (first.Name == "+") @@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual channelTabControl.RemoveChannel(first); return false; - }, "remove all channels"); + }); AddAssert("selector tab is active", () => channelTabControl.ChannelSelectorActive.Value); } diff --git a/osu.Game.Tests/Visual/TestCaseChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs similarity index 85% rename from osu.Game.Tests/Visual/TestCaseChatDisplay.cs rename to osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs index e3bd4026b3..6e20165c1b 100644 --- a/osu.Game.Tests/Visual/TestCaseChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChatDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -12,7 +12,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Chat; using osu.Game.Overlays.Chat.Tabs; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [Description("Testing chat api and overlay")] public class TestCaseChatDisplay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseChatLink.cs b/osu.Game.Tests/Visual/Online/TestCaseChatLink.cs similarity index 96% rename from osu.Game.Tests/Visual/TestCaseChatLink.cs rename to osu.Game.Tests/Visual/Online/TestCaseChatLink.cs index 8aa3283af7..8843f136a1 100644 --- a/osu.Game.Tests/Visual/TestCaseChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseChatLink.cs @@ -1,24 +1,24 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osuTK.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Game.Online.Chat; -using osu.Game.Overlays.Chat; -using osu.Game.Users; using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.Chat; using osu.Game.Overlays; -using osu.Framework.Configuration; +using osu.Game.Overlays.Chat; +using osu.Game.Users; +using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseChatLink : OsuTestCase @@ -56,7 +56,7 @@ namespace osu.Game.Tests.Visual var chatManager = new ChannelManager(); BindableList availableChannels = (BindableList)chatManager.AvailableChannels; - availableChannels.Add(new Channel { Name = "#english"}); + availableChannels.Add(new Channel { Name = "#english" }); availableChannels.Add(new Channel { Name = "#japanese" }); Dependencies.Cache(chatManager); @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual return true; } - bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast().All(sprite => sprite.Font == "Exo2.0-MediumItalic"); + bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast().All(sprite => sprite.Font.Italics); bool isShowingLinks() { @@ -159,7 +159,7 @@ namespace osu.Game.Tests.Visual Scheduler.AddDelayed(() => newLine.Message = new DummyMessage(completeText ?? text), delay); }); - AddUntilStep(() => textContainer.All(line => line.Message is DummyMessage), $"wait for msg #{echoCounter}"); + AddUntilStep($"wait for msg #{echoCounter}", () => textContainer.All(line => line.Message is DummyMessage)); } } diff --git a/osu.Game.Tests/Visual/TestCaseDirect.cs b/osu.Game.Tests/Visual/Online/TestCaseDirect.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseDirect.cs rename to osu.Game.Tests/Visual/Online/TestCaseDirect.cs index 2f45c87161..ff57104d8a 100644 --- a/osu.Game.Tests/Visual/TestCaseDirect.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseDirect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using NUnit.Framework; @@ -8,7 +8,7 @@ using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Rulesets; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseDirect : OsuTestCase diff --git a/osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs new file mode 100644 index 0000000000..fbda531792 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestCaseDirectPanel.cs @@ -0,0 +1,47 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Overlays.Direct; +using osu.Game.Rulesets.Osu; +using osu.Game.Tests.Beatmaps; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestCaseDirectPanel : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DirectGridPanel), + typeof(DirectListPanel), + typeof(IconPill) + }; + + [BackgroundDependencyLoader] + private void load() + { + var beatmap = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null); + beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true; + beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true; + + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Padding = new MarginPadding(20), + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + new DirectGridPanel(beatmap.BeatmapSetInfo), + new DirectListPanel(beatmap.BeatmapSetInfo) + } + }; + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs b/osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs similarity index 71% rename from osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs rename to osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs index 07bc59b29c..a73cbd86d0 100644 --- a/osu.Game.Tests/Visual/TestCaseExternalLinkButton.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseExternalLinkButton.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Game.Graphics.UserInterface; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { public class TestCaseExternalLinkButton : OsuTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseGraph.cs b/osu.Game.Tests/Visual/Online/TestCaseGraph.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseGraph.cs rename to osu.Game.Tests/Visual/Online/TestCaseGraph.cs index 0b0a80648b..77e850fc92 100644 --- a/osu.Game.Tests/Visual/TestCaseGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseGraph.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using NUnit.Framework; @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseGraph : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseHistoricalSection.cs rename to osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs index a576ac84e7..92aa9320c8 100644 --- a/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseHistoricalSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -12,7 +12,7 @@ using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Historical; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseHistoricalSection : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseRankGraph.cs b/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseRankGraph.cs rename to osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs index f8eea7d63c..dff018bf91 100644 --- a/osu.Game.Tests/Visual/TestCaseRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseRankGraph.cs @@ -1,19 +1,19 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osuTK; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using System.Collections.Generic; -using System; -using NUnit.Framework; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseRankGraph : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseSocial.cs b/osu.Game.Tests/Visual/Online/TestCaseSocial.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseSocial.cs rename to osu.Game.Tests/Visual/Online/TestCaseSocial.cs index 03f8fccae6..48325713df 100644 --- a/osu.Game.Tests/Visual/TestCaseSocial.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseSocial.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using osu.Game.Overlays; using osu.Game.Overlays.Social; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseSocial : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.cs b/osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.cs rename to osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs index b5ce1f1eaf..4c4b3b2612 100644 --- a/osu.Game.Tests/Visual/TestCaseStandAloneChatDisplay.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseStandAloneChatDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Game.Online.Chat; using osu.Game.Users; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { public class TestCaseStandAloneChatDisplay : OsuTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs similarity index 91% rename from osu.Game.Tests/Visual/TestCaseUserPanel.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs index a53af247f3..b2877f7bd7 100644 --- a/osu.Game.Tests/Visual/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Users; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseUserPanel : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs similarity index 91% rename from osu.Game.Tests/Visual/TestCaseUserProfile.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs index cb281d045b..5b86de28f9 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfile.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -13,13 +13,13 @@ using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseUserProfile : OsuTestCase { private readonly TestUserProfileOverlay profile; - private APIAccess api; + private IAPIProvider api; public override IReadOnlyList RequiredTypes => new[] { @@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; } @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual private void checkSupporterTag(bool isSupporter) { - AddUntilStep(() => profile.Header.User != null, "wait for load"); + AddUntilStep("wait for load", () => profile.Header.User != null); if (isSupporter) AddAssert("is supporter", () => profile.Header.SupporterTag.Alpha == 1); else diff --git a/osu.Game.Tests/Visual/TestCaseUserProfileRecentSection.cs b/osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs similarity index 96% rename from osu.Game.Tests/Visual/TestCaseUserProfileRecentSection.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs index b14606780d..6b29ed1e85 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfileRecentSection.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserProfileRecentSection.cs @@ -1,20 +1,20 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Recent; -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Online.API.Requests.Responses; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseUserProfileRecentSection : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseUserRanks.cs b/osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs similarity index 86% rename from osu.Game.Tests/Visual/TestCaseUserRanks.cs rename to osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs index 8329ad705a..64257f8877 100644 --- a/osu.Game.Tests/Visual/TestCaseUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestCaseUserRanks.cs @@ -1,6 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; +using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -8,11 +11,8 @@ using osu.Game.Graphics; using osu.Game.Overlays.Profile.Sections; using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Users; -using System; -using System.Collections.Generic; -using NUnit.Framework; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Online { [TestFixture] public class TestCaseUserRanks : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs similarity index 69% rename from osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs rename to osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs index fe88b46414..ce179c21ba 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Game.Tests/Visual/Settings/TestCaseKeyConfiguration.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Overlays; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Settings { [TestFixture] public class TestCaseKeyConfiguration : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseSettings.cs b/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs similarity index 79% rename from osu.Game.Tests/Visual/TestCaseSettings.cs rename to osu.Game.Tests/Visual/Settings/TestCaseSettings.cs index c942342168..e846d5c020 100644 --- a/osu.Game.Tests/Visual/TestCaseSettings.cs +++ b/osu.Game.Tests/Visual/Settings/TestCaseSettings.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Settings { [TestFixture] public class TestCaseSettings : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs index f156728981..1500605896 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapCarousel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -17,7 +17,7 @@ using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] public class TestCaseBeatmapCarousel : OsuTestCase @@ -40,7 +40,6 @@ namespace osu.Game.Tests.Visual typeof(DrawableCarouselBeatmapSet), }; - private readonly Stack selectedSets = new Stack(); private readonly HashSet eagerSelectedIDs = new HashSet(); @@ -88,7 +87,7 @@ namespace osu.Game.Tests.Visual carousel.BeatmapSetsChanged = () => changed = true; carousel.BeatmapSets = beatmapSets; }); - AddUntilStep(() => changed, "Wait for load"); + AddUntilStep("Wait for load", () => changed); } private void ensureRandomFetchSuccess() => @@ -148,9 +147,10 @@ namespace osu.Game.Tests.Visual private bool selectedBeatmapVisible() { - var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected); + var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State.Value == CarouselItemState.Selected); if (currentlySelected == null) return true; + return currentlySelected.Item.Visible; } @@ -167,8 +167,7 @@ namespace osu.Game.Tests.Visual carousel.Filter(new FilterCriteria { SearchText = "Dingo" }, false); carousel.Filter(new FilterCriteria(), false); eagerSelectedIDs.Add(carousel.SelectedBeatmapSet.ID); - } - ); + }); } /// @@ -215,7 +214,7 @@ namespace osu.Game.Tests.Visual checkSelected(3, 2); AddStep("Un-filter (debounce)", () => carousel.Filter(new FilterCriteria())); - AddUntilStep(() => !carousel.PendingFilterTask, "Wait for debounce"); + AddUntilStep("Wait for debounce", () => !carousel.PendingFilterTask); checkVisibleItemCount(diff: false, count: set_count); checkVisibleItemCount(diff: true, count: 3); @@ -328,13 +327,13 @@ namespace osu.Game.Tests.Visual AddStep("Remove first", () => carousel.RemoveBeatmapSet(carousel.BeatmapSets.First())); checkSelected(1); - AddUntilStep(() => + AddUntilStep("Remove all", () => { if (!carousel.BeatmapSets.Any()) return true; carousel.RemoveBeatmapSet(carousel.BeatmapSets.Last()); return false; - }, "Remove all"); + }); checkNoSelection(); } @@ -523,6 +522,7 @@ namespace osu.Game.Tests.Visual } }); } + return toReturn; } diff --git a/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs new file mode 100644 index 0000000000..722a63f2b0 --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetailArea.cs @@ -0,0 +1,160 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Screens.Select; +using osuTK; + +namespace osu.Game.Tests.Visual.SongSelect +{ + [TestFixture] + [System.ComponentModel.Description("PlaySongSelect leaderboard/details area")] + public class TestCaseBeatmapDetailArea : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(BeatmapDetails) }; + + public TestCaseBeatmapDetailArea() + { + BeatmapDetailArea detailsArea; + Add(detailsArea = new BeatmapDetailArea + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(550f, 450f), + }); + + AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap + { + BeatmapInfo = + { + Version = "All Metrics", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + } + } + ); + + AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap + { + BeatmapInfo = + { + Version = "All Metrics", + Metadata = new BeatmapMetadata + { + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + } + }); + + AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap + { + BeatmapInfo = + { + Version = "Only Ratings", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has ratings metrics but not retries or fails", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 6, + DrainRate = 9, + OverallDifficulty = 6, + ApproachRate = 6, + }, + StarDifficulty = 4.8f, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + }, + } + }); + + AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap + { + BeatmapInfo = + { + Version = "Only Retries and Fails", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has retries and fails but no ratings", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 3.7f, + DrainRate = 6, + OverallDifficulty = 6, + ApproachRate = 7, + }, + StarDifficulty = 2.91f, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + } + }); + + AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap + { + BeatmapInfo = + { + Version = "No Metrics", + Metadata = new BeatmapMetadata + { + Source = "osu!lazer", + Tags = "this beatmap has no metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 5, + DrainRate = 5, + OverallDifficulty = 5.5f, + ApproachRate = 6.5f, + }, + StarDifficulty = 1.97f, + } + }); + + AddStep("null beatmap", () => detailsArea.Beatmap = null); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs similarity index 72% rename from osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs index 0f7d871e5e..37987b8884 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapDetails.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using System.Linq; @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [Description("PlaySongSelect beatmap details")] public class TestCaseBeatmapDetails : OsuTestCase @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual Padding = new MarginPadding(150), }); - AddStep("beatmap all metrics", () => details.Beatmap = new BeatmapInfo + AddStep("all metrics", () => details.Beatmap = new BeatmapInfo { Version = "All Metrics", Metadata = new BeatmapMetadata @@ -45,7 +45,30 @@ namespace osu.Game.Tests.Visual }, }); - AddStep("beatmap ratings", () => details.Beatmap = new BeatmapInfo + AddStep("all except source", () => details.Beatmap = new BeatmapInfo + { + Version = "All Metrics", + Metadata = new BeatmapMetadata + { + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Ratings = Enumerable.Range(0, 11), + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6), + }, + }); + + AddStep("ratings", () => details.Beatmap = new BeatmapInfo { Version = "Only Ratings", Metadata = new BeatmapMetadata @@ -67,7 +90,7 @@ namespace osu.Game.Tests.Visual }, }); - AddStep("beatmap fails retries", () => details.Beatmap = new BeatmapInfo + AddStep("fails retries", () => details.Beatmap = new BeatmapInfo { Version = "Only Retries and Fails", Metadata = new BeatmapMetadata @@ -90,7 +113,7 @@ namespace osu.Game.Tests.Visual }, }); - AddStep("beatmap no metrics", () => details.Beatmap = new BeatmapInfo + AddStep("no metrics", () => details.Beatmap = new BeatmapInfo { Version = "No Metrics", Metadata = new BeatmapMetadata diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs similarity index 93% rename from osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs index 35cdfda92c..f3e44bd808 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapInfoWedge.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using NUnit.Framework; -using osuTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,8 +19,9 @@ using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osu.Game.Tests.Beatmaps; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] public class TestCaseBeatmapInfoWedge : OsuTestCase @@ -50,17 +50,17 @@ namespace osu.Game.Tests.Visual AddStep("show", () => { infoWedge.State = Visibility.Visible; - infoWedge.Beatmap = Beatmap; + infoWedge.Beatmap = Beatmap.Value; }); // select part is redundant, but wait for load isn't selectBeatmap(Beatmap.Value.Beatmap); - AddWaitStep(3); + AddWaitStep("wait for select", 3); AddStep("hide", () => { infoWedge.State = Visibility.Hidden; }); - AddWaitStep(3); + AddWaitStep("wait for hide", 3); AddStep("show", () => { infoWedge.State = Visibility.Visible; }); @@ -135,7 +135,7 @@ namespace osu.Game.Tests.Visual infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : new TestWorkingBeatmap(b); }); - AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load"); + AddUntilStep("wait for async load", () => infoWedge.Info != infoBefore); } private IBeatmap createTestBeatmap(RulesetInfo ruleset) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs similarity index 82% rename from osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs index a56b82d887..49038dc2cf 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapOptionsOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Game.Graphics; @@ -7,7 +7,7 @@ using osu.Game.Screens.Select.Options; using osuTK.Graphics; using osuTK.Input; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [Description("bottom beatmap details")] public class TestCaseBeatmapOptionsOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs similarity index 95% rename from osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs index ec85b33919..c7970b6ebb 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseBeatmapScoresContainer.cs @@ -1,31 +1,28 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; +using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapSet.Scores; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Users; -using System.Collections.Generic; -using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets.Osu; using osu.Game.Scoring; +using osu.Game.Users; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [System.ComponentModel.Description("in BeatmapOverlay")] public class TestCaseBeatmapScoresContainer : OsuTestCase { - private readonly IEnumerable scores; - private readonly IEnumerable anotherScores; - private readonly APIScoreInfo topScoreInfo; private readonly Box background; public TestCaseBeatmapScoresContainer() @@ -47,16 +44,7 @@ namespace osu.Game.Tests.Visual } }; - AddStep("scores pack 1", () => scoresContainer.Scores = scores); - AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); - AddStep("only top score", () => scoresContainer.Scores = new[] { topScoreInfo }); - AddStep("remove scores", () => scoresContainer.Scores = null); - AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); - AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); - AddStep("online scores", () => scoresContainer.Beatmap = new BeatmapInfo { OnlineBeatmapID = 75, Ruleset = new OsuRuleset().RulesetInfo }); - - - scores = new[] + IEnumerable scores = new[] { new APIScoreInfo { @@ -161,14 +149,15 @@ namespace osu.Game.Tests.Visual Accuracy = 0.6543, }, }; - foreach(var s in scores) + + foreach (var s in scores) { s.Statistics.Add(HitResult.Great, RNG.Next(2000)); s.Statistics.Add(HitResult.Good, RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); } - anotherScores = new[] + IEnumerable anotherScores = new[] { new APIScoreInfo { @@ -280,7 +269,7 @@ namespace osu.Game.Tests.Visual s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); } - topScoreInfo = new APIScoreInfo + var topScoreInfo = new APIScoreInfo { User = new User { @@ -305,6 +294,14 @@ namespace osu.Game.Tests.Visual topScoreInfo.Statistics.Add(HitResult.Great, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Good, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Meh, RNG.Next(2000)); + + AddStep("scores pack 1", () => scoresContainer.Scores = scores); + AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); + AddStep("only top score", () => scoresContainer.Scores = new[] { topScoreInfo }); + AddStep("remove scores", () => scoresContainer.Scores = null); + AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); + AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); + AddStep("online scores", () => scoresContainer.Beatmap = new BeatmapInfo { OnlineBeatmapID = 75, Ruleset = new OsuRuleset().RulesetInfo }); } [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs similarity index 97% rename from osu.Game.Tests/Visual/TestCaseLeaderboard.cs rename to osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs index 10d7eaee8a..13ae6f228a 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCaseLeaderboard.cs @@ -1,26 +1,27 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.ComponentModel; -using osu.Framework.Graphics; -using osu.Game.Screens.Select.Leaderboards; -using osu.Game.Users; -using osu.Framework.Allocation; -using osuTK; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Scoring; +using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Users; +using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [Description("PlaySongSelect leaderboard")] public class TestCaseLeaderboard : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { + public override IReadOnlyList RequiredTypes => new[] + { typeof(Placeholder), typeof(MessagePlaceholder), typeof(RetrievalFailurePlaceholder), diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs similarity index 72% rename from osu.Game.Tests/Visual/TestCasePlaySongSelect.cs rename to osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs index 29060ceb12..d5bc452d75 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestCasePlaySongSelect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,9 +8,11 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.MathUtils; +using osu.Framework.Platform; +using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets; @@ -21,10 +23,10 @@ using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.SongSelect { [TestFixture] - public class TestCasePlaySongSelect : OsuTestCase + public class TestCasePlaySongSelect : ScreenTestCase { private BeatmapManager manager; @@ -39,7 +41,7 @@ namespace osu.Game.Tests.Visual public override IReadOnlyList RequiredTypes => new[] { - typeof(SongSelect), + typeof(Screens.Select.SongSelect), typeof(BeatmapCarousel), typeof(CarouselItem), @@ -57,11 +59,19 @@ namespace osu.Game.Tests.Visual private class TestSongSelect : PlaySongSelect { + public Action StartRequested; + public new Bindable Ruleset => base.Ruleset; public WorkingBeatmap CurrentBeatmap => Beatmap.Value; public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; public new BeatmapCarousel Carousel => base.Carousel; + + protected override bool OnStart() + { + StartRequested?.Invoke(); + return base.OnStart(); + } } private TestSongSelect songSelect; @@ -73,7 +83,7 @@ namespace osu.Game.Tests.Visual } [BackgroundDependencyLoader] - private void load() + private void load(GameHost host) { factory = new DatabaseContextFactory(LocalStorage); factory.ResetDatabase(); @@ -87,30 +97,25 @@ namespace osu.Game.Tests.Visual usage.Migrate(); Dependencies.Cache(rulesets = new RulesetStore(factory)); - Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, null, defaultBeatmap = Beatmap.Default)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, defaultBeatmap = Beatmap.Default)); Beatmap.SetDefault(); } [SetUp] - public virtual void SetUp() - { - Schedule(() => - { - manager?.Delete(manager.GetAllUsableBeatmapSets()); - Child = songSelect = new TestSongSelect(); - }); - } + public virtual void SetUp() => + Schedule(() => { manager?.Delete(manager.GetAllUsableBeatmapSets()); }); [Test] public void TestDummy() { + createSongSelect(); AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap); - AddAssert("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap); + AddUntilStep("dummy shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap == defaultBeatmap); addManyTestMaps(); - AddWaitStep(3); + AddWaitStep("wait for select", 3); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); } @@ -118,8 +123,9 @@ namespace osu.Game.Tests.Visual [Test] public void TestSorting() { + createSongSelect(); addManyTestMaps(); - AddWaitStep(3); + AddWaitStep("wait for add", 3); AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap); @@ -133,29 +139,32 @@ namespace osu.Game.Tests.Visual [Ignore("needs fixing")] public void TestImportUnderDifferentRuleset() { + createSongSelect(); changeRuleset(2); importForRuleset(0); - AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection"); + AddUntilStep("no selection", () => songSelect.Carousel.SelectedBeatmap == null); } [Test] public void TestImportUnderCurrentRuleset() { + createSongSelect(); changeRuleset(2); importForRuleset(2); importForRuleset(1); - AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 2, "has selection"); + AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap.RulesetID == 2); changeRuleset(1); - AddUntilStep(() => songSelect.Carousel.SelectedBeatmap.RulesetID == 1, "has selection"); + AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap.RulesetID == 1); changeRuleset(0); - AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection"); + AddUntilStep("no selection", () => songSelect.Carousel.SelectedBeatmap == null); } [Test] public void TestRulesetChangeResetsMods() { + createSongSelect(); changeRuleset(0); changeMods(new OsuModHardRock()); @@ -178,8 +187,30 @@ namespace osu.Game.Tests.Visual AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); AddAssert("empty mods", () => !selectedMods.Value.Any()); - void onModChange(IEnumerable mods) => modChangeIndex = actionIndex++; - void onRulesetChange(RulesetInfo ruleset) => rulesetChangeIndex = actionIndex--; + void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; + void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; + } + + [Test] + public void TestStartAfterUnMatchingFilterDoesNotStart() + { + createSongSelect(); + addManyTestMaps(); + AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmap != null); + + bool startRequested = false; + + AddStep("set filter and finalize", () => + { + songSelect.StartRequested = () => startRequested = true; + + songSelect.Carousel.Filter(new FilterCriteria { SearchText = "somestringthatshouldn'tbematchable" }); + songSelect.FinaliseSelection(); + + songSelect.StartRequested = null; + }); + + AddAssert("start not requested", () => !startRequested); } private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); @@ -191,6 +222,12 @@ namespace osu.Game.Tests.Visual private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); + private void createSongSelect() + { + AddStep("create song select", () => LoadScreen(songSelect = new TestSongSelect())); + AddUntilStep("wait for present", () => songSelect.IsCurrentScreen()); + } + private void addManyTestMaps() { AddStep("import test maps", () => diff --git a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs b/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs deleted file mode 100644 index c54ac448dd..0000000000 --- a/osu.Game.Tests/Visual/TestCaseAccountCreationOverlay.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics.Containers; -using osu.Game.Overlays; -using osu.Game.Overlays.AccountCreation; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseAccountCreationOverlay : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(ErrorTextFlowContainer), - typeof(AccountCreationBackground), - typeof(ScreenEntry), - typeof(ScreenWarning), - typeof(ScreenWelcome), - typeof(AccountCreationScreen), - }; - - public TestCaseAccountCreationOverlay() - { - var accountCreation = new AccountCreationOverlay(); - Child = accountCreation; - - accountCreation.State = Visibility.Visible; - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseAllPlayers.cs b/osu.Game.Tests/Visual/TestCaseAllPlayers.cs deleted file mode 100644 index 4134ce3634..0000000000 --- a/osu.Game.Tests/Visual/TestCaseAllPlayers.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseAllPlayers : TestCasePlayer - { - } -} diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs b/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs deleted file mode 100644 index 4d19667926..0000000000 --- a/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Game.Screens.Select; -using osuTK; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - [System.ComponentModel.Description("PlaySongSelect leaderboard/details area")] - public class TestCaseBeatmapDetailArea : OsuTestCase - { - public TestCaseBeatmapDetailArea() - { - Add(new BeatmapDetailArea - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(550f, 450f), - }); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseDisclaimer.cs b/osu.Game.Tests/Visual/TestCaseDisclaimer.cs deleted file mode 100644 index b6b9a7adb4..0000000000 --- a/osu.Game.Tests/Visual/TestCaseDisclaimer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Game.Screens.Menu; -using osuTK.Graphics; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseDisclaimer : OsuTestCase - { - [BackgroundDependencyLoader] - private void load() - { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - new Disclaimer() - }; - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs deleted file mode 100644 index 88265d146f..0000000000 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Game.Screens.Multi; -using osu.Game.Screens.Multi.Lounge; -using osu.Game.Screens.Multi.Lounge.Components; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseMultiScreen : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(Multiplayer), - typeof(LoungeSubScreen), - typeof(FilterControl) - }; - - public TestCaseMultiScreen() - { - Multiplayer multi = new Multiplayer(); - - AddStep(@"show", () => Add(multi)); - AddWaitStep(5); - AddStep(@"exit", multi.Exit); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestCaseOsuGame.cs index 924a2b5e15..9e649b92e4 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestCaseOsuGame.cs @@ -1,12 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using NUnit.Framework; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Screens; +using osu.Framework.Platform; using osu.Game.Screens.Menu; using osuTK.Graphics; @@ -20,8 +21,12 @@ namespace osu.Game.Tests.Visual typeof(OsuLogo), }; - public TestCaseOsuGame() + [BackgroundDependencyLoader] + private void load(GameHost host) { + OsuGame game = new OsuGame(); + game.SetHost(host); + Children = new Drawable[] { new Box @@ -29,7 +34,7 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - new Loader() + game }; } } diff --git a/osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs b/osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs new file mode 100644 index 0000000000..0831228681 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseOsuScreenStack.cs @@ -0,0 +1,82 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Game.Screens; +using osu.Game.Screens.Play; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + [TestFixture] + public class TestCaseOsuScreenStack : OsuTestCase + { + private TestOsuScreenStack stack; + + [SetUpSteps] + public void SetUpSteps() + { + AddStep("Create new screen stack", () => { Child = stack = new TestOsuScreenStack { RelativeSizeAxes = Axes.Both }; }); + } + + [Test] + public void ParallaxAssignmentTest() + { + NoParallaxTestScreen noParallaxScreen = null; + TestScreen parallaxScreen = null; + + AddStep("Push no parallax", () => stack.Push(noParallaxScreen = new NoParallaxTestScreen("NO PARALLAX"))); + AddUntilStep("Wait for current", () => noParallaxScreen.IsLoaded); + AddAssert("Parallax is off", () => stack.ParallaxAmount == 0); + + AddStep("Push parallax", () => noParallaxScreen.Push(parallaxScreen = new TestScreen("PARALLAX"))); + AddUntilStep("Wait for current", () => parallaxScreen.IsLoaded); + AddAssert("Parallax is on", () => stack.ParallaxAmount > 0); + + AddStep("Exit from new screen", () => { noParallaxScreen.MakeCurrent(); }); + AddAssert("Parallax is off", () => stack.ParallaxAmount == 0); + } + + private class TestScreen : ScreenWithBeatmapBackground + { + private readonly string screenText; + + public TestScreen(string screenText) + { + this.screenText = screenText; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(new SpriteText + { + Text = screenText, + Colour = Color4.White, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + } + + private class NoParallaxTestScreen : TestScreen + { + public NoParallaxTestScreen(string screenText) + : base(screenText) + { + } + + public override float BackgroundParallaxAmount => 0.0f; + } + + private class TestOsuScreenStack : OsuScreenStack + { + public new float ParallaxAmount => base.ParallaxAmount; + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseReplay.cs b/osu.Game.Tests/Visual/TestCaseReplay.cs deleted file mode 100644 index 0fc4616f56..0000000000 --- a/osu.Game.Tests/Visual/TestCaseReplay.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.ComponentModel; -using System.Linq; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Play; - -namespace osu.Game.Tests.Visual -{ - [Description("Player instantiated with a replay.")] - public class TestCaseReplay : TestCasePlayer - { - protected override Player CreatePlayer(Ruleset ruleset) - { - // We create a dummy RulesetContainer just to get the replay - we don't want to use mods here - // to simulate setting a replay rather than having the replay already set for us - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); - var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(Beatmap.Value); - - // Reset the mods - Beatmap.Value.Mods.Value = Beatmap.Value.Mods.Value.Where(m => !(m is ModAutoplay)); - - return new ReplayPlayer(dummyRulesetContainer.ReplayScore); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseSongProgress.cs b/osu.Game.Tests/Visual/TestCaseSongProgress.cs deleted file mode 100644 index 1eb40a9486..0000000000 --- a/osu.Game.Tests/Visual/TestCaseSongProgress.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Graphics; -using osu.Framework.MathUtils; -using osu.Framework.Timing; -using osu.Game.Rulesets.Objects; -using osu.Game.Screens.Play; - -namespace osu.Game.Tests.Visual -{ - [TestFixture] - public class TestCaseSongProgress : OsuTestCase - { - private readonly SongProgress progress; - private readonly SongProgressGraph graph; - - private readonly StopwatchClock clock; - - public TestCaseSongProgress() - { - clock = new StopwatchClock(true); - - Add(progress = new SongProgress - { - RelativeSizeAxes = Axes.X, - AudioClock = new StopwatchClock(true), - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - }); - - Add(graph = new SongProgressGraph - { - RelativeSizeAxes = Axes.X, - Height = 200, - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, - }); - - AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddWaitStep(5); - AddStep("Toggle Bar", () => progress.AllowSeeking = !progress.AllowSeeking); - AddWaitStep(2); - AddRepeatStep("New Values", displayNewValues, 5); - - displayNewValues(); - } - - private void displayNewValues() - { - List objects = new List(); - for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) - objects.Add(new HitObject { StartTime = i }); - - progress.Objects = objects; - graph.Objects = objects; - - progress.AudioClock = clock; - progress.OnSeek = pos => clock.Seek(pos); - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs deleted file mode 100644 index bc449f645b..0000000000 --- a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Rulesets; -using osu.Game.Tests.Beatmaps.IO; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseUpdateableBeatmapBackgroundSprite : OsuTestCase - { - private UpdateableBeatmapBackgroundSprite backgroundSprite; - - [Resolved] - private BeatmapManager beatmaps { get; set; } - - [BackgroundDependencyLoader] - private void load(OsuGameBase osu, APIAccess api, RulesetStore rulesets) - { - Bindable beatmapBindable = new Bindable(); - - var imported = ImportBeatmapTest.LoadOszIntoOsu(osu); - - Child = backgroundSprite = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; - - backgroundSprite.Beatmap.BindTo(beatmapBindable); - - var req = new GetBeatmapSetRequest(1); - api.Queue(req); - - AddStep("null", () => beatmapBindable.Value = null); - - AddStep("imported", () => beatmapBindable.Value = imported.Beatmaps.First()); - - if (api.IsLoggedIn) - { - AddUntilStep(() => req.Result != null, "wait for api response"); - - AddStep("online", () => beatmapBindable.Value = new BeatmapInfo - { - BeatmapSet = req.Result?.ToBeatmapSet(rulesets) - }); - } - else - { - AddStep("online (login first)", () => { }); - } - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseDrawings.cs b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs similarity index 88% rename from osu.Game.Tests/Visual/TestCaseDrawings.cs rename to osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs index a6a3ef6747..9453d0a5b2 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawings.cs +++ b/osu.Game.Tests/Visual/Tournament/TestCaseDrawings.cs @@ -1,19 +1,19 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.ComponentModel; using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament.Teams; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.Tournament { [Description("for tournament use")] - public class TestCaseDrawings : OsuTestCase + public class TestCaseDrawings : ScreenTestCase { public TestCaseDrawings() { - Add(new Drawings + LoadScreen(new Drawings { TeamList = new TestTeamList(), }); diff --git a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs index ff383b6723..dcd194e050 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseBeatSyncedContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using NUnit.Framework; @@ -8,15 +8,16 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Lists; using osu.Framework.Timing; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osuTK.Graphics; -using osu.Framework.Lists; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseBeatSyncedContainer : OsuTestCase @@ -140,6 +141,7 @@ namespace osu.Game.Tests.Visual } private SortedList timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints; + private TimingControlPoint getNextTimingPoint(TimingControlPoint current) { if (timingPoints[timingPoints.Count - 1] == current) @@ -189,15 +191,15 @@ namespace osu.Game.Tests.Visual public double Value { - set { valueText.Text = $"{value:G}"; } + set => valueText.Text = $"{value:G}"; } public InfoString(string header) { AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; - Add(new OsuSpriteText { Text = header + @": ", TextSize = text_size }); - Add(valueText = new OsuSpriteText { TextSize = text_size }); + Add(new OsuSpriteText { Text = header + @": ", Font = OsuFont.GetFont(size: text_size) }); + Add(valueText = new OsuSpriteText { Font = OsuFont.GetFont(size: text_size) }); Margin = new MarginPadding(margin); } } diff --git a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs similarity index 85% rename from osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs index 73a97c6269..5e09e0a5b9 100644 --- a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseBreadcrumbs.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -7,7 +7,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseBreadcrumbs : OsuTestCase @@ -16,7 +16,6 @@ namespace osu.Game.Tests.Visual public TestCaseBreadcrumbs() { - Add(breadcrumbs = new BreadcrumbControl { Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/TestCaseButtonSystem.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs similarity index 85% rename from osu.Game.Tests/Visual/TestCaseButtonSystem.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs index 0506783310..261e87ff07 100644 --- a/osu.Game.Tests/Visual/TestCaseButtonSystem.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseButtonSystem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Screens.Menu; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseButtonSystem : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseContextMenu.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseContextMenu.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs index a0d0eaf015..71cde787f9 100644 --- a/osu.Game.Tests/Visual/TestCaseContextMenu.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseContextMenu.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -7,12 +7,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; -using osu.Game.Graphics.Cursor; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseContextMenu : OsuTestCase @@ -61,10 +61,10 @@ namespace osu.Game.Tests.Visual // Move box along a square trajectory container.Loop(c => c - .MoveTo(new Vector2(0, 100), duration).Then() - .MoveTo(new Vector2(100, 100), duration).Then() - .MoveTo(new Vector2(100, 0), duration).Then() - .MoveTo(Vector2.Zero, duration) + .MoveTo(new Vector2(0, 100), duration).Then() + .MoveTo(new Vector2(100, 100), duration).Then() + .MoveTo(new Vector2(100, 0), duration).Then() + .MoveTo(Vector2.Zero, duration) ); } diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs similarity index 98% rename from osu.Game.Tests/Visual/TestCaseCursors.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs index 293ca392ab..5f45d9ba4d 100644 --- a/osu.Game.Tests/Visual/TestCaseCursors.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseCursors.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Extensions.IEnumerableExtensions; @@ -14,7 +14,7 @@ using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseCursors : ManualInputManagerTestCase diff --git a/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs similarity index 92% rename from osu.Game.Tests/Visual/TestCaseDialogOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs index f0907ed28c..6b32f711e9 100644 --- a/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseDialogOverlay.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Game.Graphics; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseDialogOverlay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseDrawableDate.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs similarity index 89% rename from osu.Game.Tests/Visual/TestCaseDrawableDate.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs index 2e38f5eb28..e8662ce965 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableDate.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseDrawableDate.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -9,7 +9,7 @@ using osu.Game.Graphics; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseDrawableDate : OsuTestCase { @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual } }; - drawableDate.Current.ValueChanged += v => flash.FadeOutFromOne(500); + drawableDate.Current.ValueChanged += _ => flash.FadeOutFromOne(500); } } } diff --git a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs similarity index 81% rename from osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs index 6fa49c4edb..38dc4a11dc 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseHoldToConfirmOverlay.cs @@ -1,13 +1,14 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Menu; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseHoldToConfirmOverlay : OsuTestCase { @@ -22,7 +23,7 @@ namespace osu.Game.Tests.Visual Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Fired!", - TextSize = 50, + Font = OsuFont.GetFont(size: 50), Alpha = 0, }; @@ -48,7 +49,7 @@ namespace osu.Game.Tests.Visual AddStep("start confirming", () => overlay.Begin()); - AddUntilStep(() => fired, "wait until confirmed"); + AddUntilStep("wait until confirmed", () => fired); } private class TestHoldToConfirmOverlay : ExitConfirmOverlay diff --git a/osu.Game.Tests/Visual/TestCaseIconButton.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs similarity index 95% rename from osu.Game.Tests/Visual/TestCaseIconButton.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs index d1f0727af5..2898d1a1cc 100644 --- a/osu.Game.Tests/Visual/TestCaseIconButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseIconButton.cs @@ -1,17 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osuTK; -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseIconButton : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs similarity index 84% rename from osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs index e1470a860e..781dfbdcc1 100644 --- a/osu.Game.Tests/Visual/TestCaseLabelledTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLabelledTextBox.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using System; -using System.Collections.Generic; using osu.Game.Screens.Edit.Setup.Components.LabelledComponents; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseLabelledTextBox : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseLoadingAnimation.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs similarity index 88% rename from osu.Game.Tests/Visual/TestCaseLoadingAnimation.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs index e52564c40d..43f6f0e4db 100644 --- a/osu.Game.Tests/Visual/TestCaseLoadingAnimation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseLoadingAnimation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -7,7 +7,7 @@ using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseLoadingAnimation : GridTestCase { diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs similarity index 95% rename from osu.Game.Tests/Visual/TestCaseMods.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs index 029f7da5a9..aab44f7d92 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseMods.cs @@ -1,27 +1,27 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; +using osu.Game.Overlays.Mods.Sections; using osu.Game.Rulesets; -using osu.Game.Screens.Play.HUD; -using osuTK; +using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; -using System.Linq; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Configuration; -using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Mods.Sections; -using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play.HUD; +using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [Description("mod select and icon display")] public class TestCaseMods : OsuTestCase @@ -208,22 +208,22 @@ namespace osu.Game.Tests.Visual { checkLabelColor(Color4.White); selectNext(mod); - AddWaitStep(1, "wait for changing colour"); + AddWaitStep("wait for changing colour", 1); checkLabelColor(colour); selectPrevious(mod); - AddWaitStep(1, "wait for changing colour"); + AddWaitStep("wait for changing colour", 1); checkLabelColor(Color4.White); } private void testRankedText(Mod mod) { - AddWaitStep(1, "wait for fade"); + AddWaitStep("wait for fade", 1); AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); - AddWaitStep(1, "wait for fade"); + AddWaitStep("wait for fade", 1); AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); - AddWaitStep(1, "wait for fade"); + AddWaitStep("wait for fade", 1); AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } diff --git a/osu.Game.Tests/Visual/TestCaseMusicController.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs similarity index 79% rename from osu.Game.Tests/Visual/TestCaseMusicController.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs index 5ba0167f12..644c7eb4fc 100644 --- a/osu.Game.Tests/Visual/TestCaseMusicController.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseMusicController.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Timing; using osu.Game.Overlays; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseMusicController : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs similarity index 93% rename from osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs index 66ae2d3012..4819597d22 100644 --- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseNotificationOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -12,7 +12,7 @@ using osu.Framework.MathUtils; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseNotificationOverlay : OsuTestCase @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual void setState(Visibility state) => AddStep(state.ToString(), () => manager.State = state); void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected); - manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; }; + manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; }; setState(Visibility.Visible); AddStep(@"simple #1", sendHelloNotification); @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual setState(Visibility.Hidden); AddRepeatStep(@"add many simple", sendManyNotifications, 3); - AddWaitStep(5); + AddWaitStep("wait some", 5); checkProgressingCount(0); @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Visual AddAssert("Displayed count is 33", () => manager.UnreadCount.Value == 33); - AddWaitStep(10); + AddWaitStep("wait some", 10); checkProgressingCount(0); diff --git a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs similarity index 94% rename from osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs index bc232d814d..7ad42cb926 100644 --- a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseOnScreenDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Allocation; @@ -8,7 +8,7 @@ using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; using osu.Game.Overlays; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseOnScreenDisplay : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseParallaxContainer.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs similarity index 63% rename from osu.Game.Tests/Visual/TestCaseParallaxContainer.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs index 8c12589c6f..5de4c3f41f 100644 --- a/osu.Game.Tests/Visual/TestCaseParallaxContainer.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseParallaxContainer.cs @@ -1,10 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; +using osu.Framework.Screens; using osu.Game.Graphics.Containers; using osu.Game.Screens.Backgrounds; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseParallaxContainer : OsuTestCase { @@ -14,7 +16,10 @@ namespace osu.Game.Tests.Visual Add(parallax = new ParallaxContainer { - Child = new BackgroundScreenDefault { Alpha = 0.8f } + Child = new ScreenStack(new BackgroundScreenDefault { Alpha = 0.8f }) + { + RelativeSizeAxes = Axes.Both, + } }); AddStep("default parallax", () => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT); diff --git a/osu.Game.Tests/Visual/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs similarity index 83% rename from osu.Game.Tests/Visual/TestCasePopupDialog.cs rename to osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs index d88be1e7c7..490903a906 100644 --- a/osu.Game.Tests/Visual/TestCasePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCasePopupDialog.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Overlays.Dialog; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCasePopupDialog : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs similarity index 78% rename from osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs index 82da609e49..c92072eb71 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseScreenBreadcrumbControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using NUnit.Framework; @@ -13,22 +13,24 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseScreenBreadcrumbControl : OsuTestCase { private readonly ScreenBreadcrumbControl breadcrumbs; - private Screen currentScreen, changedScreen; + private readonly OsuScreenStack screenStack; public TestCaseScreenBreadcrumbControl() { - TestScreen startScreen; OsuSpriteText titleText; + IScreen startScreen = new TestScreenOne(); + screenStack = new OsuScreenStack(startScreen) { RelativeSizeAxes = Axes.Both }; + Children = new Drawable[] { - currentScreen = startScreen = new TestScreenOne(), + screenStack, new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -37,7 +39,7 @@ namespace osu.Game.Tests.Visual Spacing = new Vector2(10), Children = new Drawable[] { - breadcrumbs = new ScreenBreadcrumbControl(startScreen) + breadcrumbs = new ScreenBreadcrumbControl(screenStack) { RelativeSizeAxes = Axes.X, }, @@ -46,12 +48,7 @@ namespace osu.Game.Tests.Visual }, }; - breadcrumbs.Current.ValueChanged += s => - { - titleText.Text = $"Changed to {s.ToString()}"; - changedScreen = s; - }; - + breadcrumbs.Current.ValueChanged += screen => titleText.Text = $"Changed to {screen.NewValue.ToString()}"; breadcrumbs.Current.TriggerChange(); waitForCurrent(); @@ -60,18 +57,14 @@ namespace osu.Game.Tests.Visual pushNext(); waitForCurrent(); - AddStep(@"make start current", () => - { - startScreen.MakeCurrent(); - currentScreen = startScreen; - }); + AddStep(@"make start current", () => startScreen.MakeCurrent()); waitForCurrent(); pushNext(); waitForCurrent(); AddAssert(@"only 2 items", () => breadcrumbs.Items.Count() == 2); - AddStep(@"exit current", () => changedScreen.Exit()); - AddAssert(@"current screen is first", () => startScreen == changedScreen); + AddStep(@"exit current", () => screenStack.CurrentScreen.Exit()); + AddAssert(@"current screen is first", () => startScreen == screenStack.CurrentScreen); } [BackgroundDependencyLoader] @@ -80,8 +73,8 @@ namespace osu.Game.Tests.Visual breadcrumbs.StripColour = colours.Blue; } - private void pushNext() => AddStep(@"push next screen", () => currentScreen = ((TestScreen)currentScreen).PushNext()); - private void waitForCurrent() => AddUntilStep(() => currentScreen.IsCurrentScreen, "current screen"); + private void pushNext() => AddStep(@"push next screen", () => ((TestScreen)screenStack.CurrentScreen).PushNext()); + private void waitForCurrent() => AddUntilStep("current screen", () => screenStack.CurrentScreen.IsCurrentScreen()); private abstract class TestScreen : OsuScreen { @@ -91,14 +84,14 @@ namespace osu.Game.Tests.Visual public TestScreen PushNext() { TestScreen screen = CreateNextScreen(); - Push(screen); + this.Push(screen); return screen; } protected TestScreen() { - Child = new FillFlowContainer + InternalChild = new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/TestCaseTabControl.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs similarity index 74% rename from osu.Game.Tests/Visual/TestCaseTabControl.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs index 00b69fd415..480dc73dde 100644 --- a/osu.Game.Tests/Visual/TestCaseTabControl.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Framework.Graphics; @@ -8,7 +8,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [Description("SongSelect filter control")] public class TestCaseTabControl : OsuTestCase @@ -33,9 +33,9 @@ namespace osu.Game.Tests.Visual filter.PinItem(GroupMode.All); filter.PinItem(GroupMode.RecentlyPlayed); - filter.Current.ValueChanged += newFilter => + filter.Current.ValueChanged += grouping => { - text.Text = "Currently Selected: " + newFilter.ToString(); + text.Text = "Currently Selected: " + grouping.NewValue.ToString(); }; } } diff --git a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseTextAwesome.cs similarity index 87% rename from osu.Game.Tests/Visual/TestCaseTextAwesome.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseTextAwesome.cs index 50ebd3a6e5..40179387e2 100644 --- a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseTextAwesome.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using NUnit.Framework; @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Cursor; using osu.Game.Graphics; using osuTK; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] public class TestCaseTextAwesome : OsuTestCase diff --git a/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs similarity index 58% rename from osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs index 8079566947..8d3cc7a0f2 100644 --- a/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseTwoLayerButton.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { [Description("mostly back button")] public class TestCaseTwoLayerButton : OsuTestCase diff --git a/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs new file mode 100644 index 0000000000..74114b2e53 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Rulesets; +using osu.Game.Tests.Beatmaps.IO; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestCaseUpdateableBeatmapBackgroundSprite : OsuTestCase + { + private TestUpdateableBeatmapBackgroundSprite backgroundSprite; + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + [BackgroundDependencyLoader] + private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) + { + Bindable beatmapBindable = new Bindable(); + + var imported = ImportBeatmapTest.LoadOszIntoOsu(osu); + + Child = backgroundSprite = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; + + backgroundSprite.Beatmap.BindTo(beatmapBindable); + + var req = new GetBeatmapSetRequest(1); + api.Queue(req); + + AddStep("load null beatmap", () => beatmapBindable.Value = null); + AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); + AddStep("load imported beatmap", () => beatmapBindable.Value = imported.Beatmaps.First()); + AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); + + if (api.IsLoggedIn) + { + AddUntilStep("wait for api response", () => req.Result != null); + AddStep("load online beatmap", () => beatmapBindable.Value = new BeatmapInfo + { + BeatmapSet = req.Result?.ToBeatmapSet(rulesets) + }); + AddUntilStep("wait for cleanup...", () => backgroundSprite.ChildCount == 1); + } + else + { + AddStep("online (login first)", () => { }); + } + } + + private class TestUpdateableBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite + { + public int ChildCount => InternalChildren.Count; + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseVolumePieces.cs b/osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs similarity index 84% rename from osu.Game.Tests/Visual/TestCaseVolumePieces.cs rename to osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs index 5d7b7088e7..3ad1c922e4 100644 --- a/osu.Game.Tests/Visual/TestCaseVolumePieces.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestCaseVolumePieces.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using osu.Game.Overlays.Volume; using osuTK; using osuTK.Graphics; -namespace osu.Game.Tests.Visual +namespace osu.Game.Tests.Visual.UserInterface { public class TestCaseVolumePieces : OsuTestCase { diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 17aa7db14d..2028671b0e 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using System.Linq; @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO.Archives; -using osu.Game.Tests.Beatmaps.IO; +using osu.Game.Tests.Resources; namespace osu.Game.Tests { @@ -18,12 +18,12 @@ namespace osu.Game.Tests public class WaveformTestBeatmap : WorkingBeatmap { private readonly ZipArchiveReader reader; - private readonly FileStream stream; + private readonly Stream stream; public WaveformTestBeatmap() : base(new BeatmapInfo()) { - stream = File.OpenRead(ImportBeatmapTest.TEST_OSZ_PATH); + stream = TestResources.GetTestBeatmapStream(); reader = new ZipArchiveReader(stream); } diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index e6786dfd15..938e1ae0f8 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,9 +3,9 @@ - + - + diff --git a/osu.Game.props b/osu.Game.props index 4bcac479a0..1a3c0aec3e 100644 --- a/osu.Game.props +++ b/osu.Game.props @@ -16,7 +16,7 @@ ppy Pty Ltd - ppy Pty Ltd 2007-2018 + Copyright (c) 2019 ppy Pty Ltd NU1701 diff --git a/osu.Game/Audio/IPreviewTrackOwner.cs b/osu.Game/Audio/IPreviewTrackOwner.cs index f166096601..fdcae65e3c 100644 --- a/osu.Game/Audio/IPreviewTrackOwner.cs +++ b/osu.Game/Audio/IPreviewTrackOwner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Audio { diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 3c9122b941..3b21bdefc4 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -28,6 +28,7 @@ namespace osu.Game.Audio private void load() { track = GetTrack(); + track.Completed += () => Schedule(Stop); } /// @@ -50,15 +51,6 @@ namespace osu.Game.Audio /// public bool IsRunning => track?.IsRunning ?? false; - protected override void Update() - { - base.Update(); - - // Todo: Track currently doesn't signal its completion, so we have to handle it manually - if (hasStarted && track.HasCompleted) - Stop(); - } - private ScheduledDelegate startDelegate; /// @@ -71,6 +63,7 @@ namespace osu.Game.Audio if (hasStarted) return; + hasStarted = true; track.Restart(); @@ -89,6 +82,7 @@ namespace osu.Game.Audio if (!hasStarted) return; + hasStarted = false; track.Stop(); diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 07fbe86ff4..99c0d70ac9 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.IO.Stores; diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 4345d09e05..5bc6dce60b 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -50,12 +50,14 @@ namespace osu.Game.Audio { if (!string.IsNullOrEmpty(Suffix)) yield return $"{Namespace}/{Bank}-{Name}{Suffix}"; + yield return $"{Namespace}/{Bank}-{Name}"; } // check non-namespace as a fallback even when we have a namespace if (!string.IsNullOrEmpty(Suffix)) yield return $"{Bank}-{Name}{Suffix}"; + yield return $"{Bank}-{Name}"; } } diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 4ef7b28d49..4ebeee40bf 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index 3cb7833a12..b6fa6674f6 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -16,6 +16,7 @@ namespace osu.Game.Beatmaps where T : HitObject { private event Action> ObjectConverted; + event Action> IBeatmapConverter.ObjectConverted { add => ObjectConverted += value; diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 418bcb5ad1..8727431e0e 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Database; @@ -48,6 +48,7 @@ namespace osu.Game.Beatmaps return mid + (max - mid) * (difficulty - 5) / 5; if (difficulty < 5) return mid - (mid - min) * (5 - difficulty) / 5; + return mid; } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 6ad5b2070e..52238c26fe 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 73fd5da22c..9caa64ec96 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -11,13 +11,11 @@ using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Beatmaps.Formats; using osu.Game.Database; -using osu.Game.Graphics; using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -51,11 +49,6 @@ namespace osu.Game.Beatmaps /// public event Action BeatmapDownloadFailed; - /// - /// Fired when a beatmap load is requested (into the interactive game UI). - /// - public Action PresentBeatmap; - /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// @@ -71,19 +64,22 @@ namespace osu.Game.Beatmaps private readonly BeatmapStore beatmaps; - private readonly APIAccess api; + private readonly IAPIProvider api; private readonly AudioManager audioManager; + private readonly GameHost host; + private readonly List currentDownloads = new List(); - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null, + public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, AudioManager audioManager, GameHost host = null, WorkingBeatmap defaultBeatmap = null) - : base(storage, contextFactory, new BeatmapStore(contextFactory), importHost) + : base(storage, contextFactory, new BeatmapStore(contextFactory), host) { this.rulesets = rulesets; this.api = api; this.audioManager = audioManager; + this.host = host; DefaultBeatmap = defaultBeatmap; @@ -106,10 +102,16 @@ namespace osu.Game.Beatmaps b.BeatmapSet = beatmapSet; } - validateOnlineIds(beatmapSet.Beatmaps); + validateOnlineIds(beatmapSet); foreach (BeatmapInfo b in beatmapSet.Beatmaps) - fetchAndPopulateOnlineValues(b, beatmapSet.Beatmaps); + fetchAndPopulateOnlineValues(b); + } + + protected override void PreImport(BeatmapSetInfo beatmapSet) + { + if (beatmapSet.Beatmaps.Any(b => b.BaseDifficulty == null)) + throw new InvalidOperationException($"Cannot import {nameof(BeatmapInfo)} with null {nameof(BeatmapInfo.BaseDifficulty)}."); // check if a set already exists with the same online id, delete if it does. if (beatmapSet.OnlineBeatmapSetID != null) @@ -124,14 +126,30 @@ namespace osu.Game.Beatmaps } } - private void validateOnlineIds(List beatmaps) + private void validateOnlineIds(BeatmapSetInfo beatmapSet) { - var beatmapIds = beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList(); + var beatmapIds = beatmapSet.Beatmaps.Where(b => b.OnlineBeatmapID.HasValue).Select(b => b.OnlineBeatmapID).ToList(); - // ensure all IDs are unique in this set and none match existing IDs in the local beatmap store. - if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1) || QueryBeatmaps(b => beatmapIds.Contains(b.OnlineBeatmapID)).Any()) - // remove all online IDs if any problems were found. - beatmaps.ForEach(b => b.OnlineBeatmapID = null); + // ensure all IDs are unique + if (beatmapIds.GroupBy(b => b).Any(g => g.Count() > 1)) + { + resetIds(); + return; + } + + // find any existing beatmaps in the database that have matching online ids + var existingBeatmaps = QueryBeatmaps(b => beatmapIds.Contains(b.OnlineBeatmapID)).ToList(); + + if (existingBeatmaps.Count > 0) + { + // reset the import ids (to force a re-fetch) *unless* they match the candidate CheckForExisting set. + // we can ignore the case where the new ids are contained by the CheckForExisting set as it will either be used (import skipped) or deleted. + var existing = CheckForExisting(beatmapSet); + if (existing == null || existingBeatmaps.Any(b => !existing.Beatmaps.Contains(b))) + resetIds(); + } + + void resetIds() => beatmapSet.Beatmaps.ForEach(b => b.OnlineBeatmapID = null); } /// @@ -147,20 +165,9 @@ namespace osu.Game.Beatmaps if (existing != null || api == null) return false; - if (!api.LocalUser.Value.IsSupporter) - { - PostNotification?.Invoke(new SimpleNotification - { - Icon = FontAwesome.fa_superpowers, - Text = "You gotta be an osu!supporter to download for now 'yo" - }); - return false; - } - var downloadNotification = new DownloadNotification { - CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!", - Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", + Text = $"Downloading {beatmapSetInfo}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); @@ -171,26 +178,12 @@ namespace osu.Game.Beatmaps downloadNotification.Progress = progress; }; - request.Success += data => + request.Success += filename => { - downloadNotification.Text = $"Importing {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}"; - Task.Factory.StartNew(() => { - BeatmapSetInfo importedBeatmap; - // This gets scheduled back to the update thread, but we want the import to run in the background. - using (var stream = new MemoryStream(data)) - using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString())) - importedBeatmap = Import(archive); - - downloadNotification.CompletionClickAction = () => - { - PresentCompletedImport(importedBeatmap.Yield()); - return true; - }; - downloadNotification.State = ProgressNotificationState.Completed; - + Import(downloadNotification, filename); currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); }; @@ -218,17 +211,21 @@ namespace osu.Game.Beatmaps PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. - Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); + Task.Factory.StartNew(() => + { + try + { + request.Perform(api); + } + catch (Exception e) + { + // no need to handle here as exceptions will filter down to request.Failure above. + } + }, TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); return true; } - protected override void PresentCompletedImport(IEnumerable imported) - { - base.PresentCompletedImport(imported); - PresentBeatmap?.Invoke(imported.LastOrDefault()); - } - /// /// Get an existing download request if it exists. /// @@ -265,7 +262,7 @@ namespace osu.Game.Beatmaps if (beatmapInfo.Metadata == null) beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; - WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, beatmapInfo, audioManager); + WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager); previous?.TransferTo(working); @@ -279,6 +276,18 @@ namespace osu.Game.Beatmaps /// The first result for the provided query, or null if no results were found. public BeatmapSetInfo QueryBeatmapSet(Expression> query) => beatmaps.ConsumableItems.AsNoTracking().FirstOrDefault(query); + protected override bool CanUndelete(BeatmapSetInfo existing, BeatmapSetInfo import) + { + if (!base.CanUndelete(existing, import)) + return false; + + var existingIds = existing.Beatmaps.Select(b => b.OnlineBeatmapID).OrderBy(i => i); + var importIds = import.Beatmaps.Select(b => b.OnlineBeatmapID).OrderBy(i => i); + + // force re-import if we are not in a sane state. + return existing.OnlineBeatmapSetID == import.OnlineBeatmapSetID && existingIds.SequenceEqual(importIds); + } + /// /// Returns a list of all usable s. /// @@ -376,7 +385,7 @@ namespace osu.Game.Beatmaps /// The other beatmaps contained within this set. /// Whether to re-query if the provided beatmap already has populated values. /// True if population was successful. - private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, IEnumerable otherBeatmaps, bool force = false) + private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, bool force = false) { if (api?.State != APIState.Online) return false; @@ -399,13 +408,6 @@ namespace osu.Game.Beatmaps beatmap.Status = res.Status; beatmap.BeatmapSet.Status = res.BeatmapSet.Status; - - if (otherBeatmaps.Any(b => b.OnlineBeatmapID == res.OnlineBeatmapID)) - { - Logger.Log("Another beatmap in the same set already mapped to this ID. We'll skip adding it this time.", LoggingTarget.Database); - return false; - } - beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID; beatmap.OnlineBeatmapID = res.OnlineBeatmapID; diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 77ff53b893..a2e43e5a97 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -22,10 +22,11 @@ namespace osu.Game.Beatmaps private readonly IResourceStore store; private readonly AudioManager audioManager; - public BeatmapManagerWorkingBeatmap(IResourceStore store, BeatmapInfo beatmapInfo, AudioManager audioManager) + public BeatmapManagerWorkingBeatmap(IResourceStore store, TextureStore textureStore, BeatmapInfo beatmapInfo, AudioManager audioManager) : base(beatmapInfo) { this.store = store; + this.textureStore = textureStore; this.audioManager = audioManager; } @@ -44,7 +45,7 @@ namespace osu.Game.Beatmaps private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; - private LargeTextureStore textureStore; + private TextureStore textureStore; protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. @@ -55,7 +56,7 @@ namespace osu.Game.Beatmaps try { - return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); + return textureStore.Get(getPathForFile(Metadata.BackgroundFile)); } catch { diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 7e4dc4d6f5..001f319307 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -34,8 +34,8 @@ namespace osu.Game.Beatmaps [Column("Author")] public string AuthorString { - get { return Author?.Username; } - set { Author = new User { Username = value }; } + get => Author?.Username; + set => Author = new User { Username = value }; } /// @@ -48,6 +48,7 @@ namespace osu.Game.Beatmaps [JsonProperty(@"tags")] public string Tags { get; set; } + public int PreviewTime { get; set; } public string AudioFile { get; set; } public string BackgroundFile { get; set; } @@ -72,15 +73,15 @@ namespace osu.Game.Beatmaps return false; return Title == other.Title - && TitleUnicode == other.TitleUnicode - && Artist == other.Artist - && ArtistUnicode == other.ArtistUnicode - && AuthorString == other.AuthorString - && Source == other.Source - && Tags == other.Tags - && PreviewTime == other.PreviewTime - && AudioFile == other.AudioFile - && BackgroundFile == other.BackgroundFile; + && TitleUnicode == other.TitleUnicode + && Artist == other.Artist + && ArtistUnicode == other.ArtistUnicode + && AuthorString == other.AuthorString + && Source == other.Source + && Tags == other.Tags + && PreviewTime == other.PreviewTime + && AudioFile == other.AudioFile + && BackgroundFile == other.BackgroundFile; } } } diff --git a/osu.Game/Beatmaps/BeatmapMetrics.cs b/osu.Game/Beatmaps/BeatmapMetrics.cs index 427c2b50ac..95413e6d2a 100644 --- a/osu.Game/Beatmaps/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/BeatmapMetrics.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs index 3c1c2b10ce..faae74db88 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Beatmaps { diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 9db2c5f08e..7a612893c9 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs index 885fcc54f6..3a55dc1577 100644 --- a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations; using osu.Game.Database; diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index a5399ce8c7..e111f77ba1 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 8f985306e3..0ccc9a924c 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs index 4f97ee4133..5864975a2e 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineStatus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Beatmaps { diff --git a/osu.Game/Beatmaps/BeatmapStatistic.cs b/osu.Game/Beatmaps/BeatmapStatistic.cs index aebe2573d7..8c0c7c09ae 100644 --- a/osu.Game/Beatmaps/BeatmapStatistic.cs +++ b/osu.Game/Beatmaps/BeatmapStatistic.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 6817c0653d..f4b7b1d74f 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps /// /// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing /// - public class BeatmapStore : MutableDatabaseBackedStore + public class BeatmapStore : MutableDatabaseBackedStoreWithFileIncludes { public event Action BeatmapHidden; public event Action BeatmapRestored; @@ -34,6 +34,7 @@ namespace osu.Game.Beatmaps Refresh(ref beatmap, Beatmaps); if (beatmap.Hidden) return false; + beatmap.Hidden = true; } @@ -53,6 +54,7 @@ namespace osu.Game.Beatmaps Refresh(ref beatmap, Beatmaps); if (!beatmap.Hidden) return false; + beatmap.Hidden = false; } @@ -62,18 +64,17 @@ namespace osu.Game.Beatmaps protected override IQueryable AddIncludesForDeletion(IQueryable query) => base.AddIncludesForDeletion(query) - .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) - .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) .Include(s => s.Metadata) - .Include(s => s.Beatmaps).ThenInclude(b => b.Scores); + .Include(s => s.Beatmaps).ThenInclude(b => b.Scores) + .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) + .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata); protected override IQueryable AddIncludesForConsumption(IQueryable query) => base.AddIncludesForConsumption(query) .Include(s => s.Metadata) .Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset) .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) - .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) - .Include(s => s.Files).ThenInclude(f => f.FileInfo); + .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata); protected override void Purge(List items, OsuDbContext context) { diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index 34d9cd3d25..657dc06297 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -1,20 +1,20 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps { /// - /// A for the beatmap. - /// This should be used sparingly in-favour of . + /// A for the beatmap. + /// This should be used sparingly in-favour of . /// - public abstract class BindableBeatmap : NonNullableBindable, IBindableBeatmap + public abstract class BindableBeatmap : NonNullableBindable { private AudioManager audioManager; private WorkingBeatmap lastBeatmap; @@ -34,7 +34,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; - ValueChanged += registerAudioTrack; + ValueChanged += b => registerAudioTrack(b.NewValue); // If the track has changed prior to this being called, let's register it if (Value != Default) @@ -62,9 +62,6 @@ namespace osu.Game.Beatmaps lastBeatmap = beatmap; } - [NotNull] - IBindableBeatmap IBindableBeatmap.GetBoundCopy() => GetBoundCopy(); - /// /// Retrieve a new instance weakly bound to this . /// If you are further binding to events of the retrieved , ensure a local reference is held. diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 9ed476d97c..825b60ae5f 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index f064d53358..855084ad02 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index dc981cd934..013271d597 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index dd9d568133..3978b7b4b0 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Beatmaps.ControlPoints { diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 18680f9985..241ce90740 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Audio; diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index ecd7ff252c..9ec27bdfdf 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Beatmaps.Timing; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index b747857e11..0c59eec1ef 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -13,8 +13,8 @@ namespace osu.Game.Beatmaps.Drawables public BeatmapBackgroundSprite(WorkingBeatmap working) { - if (working == null) - throw new ArgumentNullException(nameof(working)); + if (working == null) + throw new ArgumentNullException(nameof(working)); this.working = working; } diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index e09da2fb72..3adfcb85ea 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs deleted file mode 100644 index baeeaf81a4..0000000000 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Online.API.Requests; - -namespace osu.Game.Beatmaps.Drawables -{ - /// - /// A component to allow downloading of a beatmap set. Automatically handles state syncing between other instances. - /// - public class BeatmapSetDownloader : Component - { - private readonly BeatmapSetInfo set; - private readonly bool noVideo; - - private BeatmapManager beatmaps; - - /// - /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. - /// - public readonly Bindable DownloadState = new Bindable(); - - public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) - { - this.set = set; - this.noVideo = noVideo; - } - - [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps) - { - this.beatmaps = beatmaps; - - beatmaps.ItemAdded += setAdded; - beatmaps.ItemRemoved += setRemoved; - beatmaps.BeatmapDownloadBegan += downloadBegan; - beatmaps.BeatmapDownloadFailed += downloadFailed; - - // initial value - if (set.OnlineBeatmapSetID != null && beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any()) - DownloadState.Value = DownloadStatus.Downloaded; - else if (beatmaps.GetExistingDownload(set) != null) - DownloadState.Value = DownloadStatus.Downloading; - else - DownloadState.Value = DownloadStatus.NotDownloaded; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (beatmaps != null) - { - beatmaps.ItemAdded -= setAdded; - beatmaps.ItemRemoved -= setRemoved; - beatmaps.BeatmapDownloadBegan -= downloadBegan; - beatmaps.BeatmapDownloadFailed -= downloadFailed; - } - } - - /// - /// Begin downloading the associated beatmap set. - /// - /// True if downloading began. False if an existing download is active or completed. - public void Download() - { - if (DownloadState.Value > DownloadStatus.NotDownloaded) - return; - - if (beatmaps.Download(set, noVideo)) - { - // Only change state if download can happen - DownloadState.Value = DownloadStatus.Downloading; - } - } - - private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.Downloaded; - }); - - private void setRemoved(BeatmapSetInfo s) => Schedule(() => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.NotDownloaded; - }); - - private void downloadBegan(DownloadBeatmapSetRequest d) - { - if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.Downloading; - } - - private void downloadFailed(DownloadBeatmapSetRequest d) - { - if (d.BeatmapSet.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - DownloadState.Value = DownloadStatus.NotDownloaded; - } - - public enum DownloadStatus - { - NotDownloaded, - Downloading, - Downloaded, - } - } -} diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index a7dff1aefc..351e5df17a 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK.Graphics; @@ -22,6 +23,7 @@ namespace osu.Game.Beatmaps.Drawables { if (status == value) return; + status = value; Alpha = value == BeatmapSetOnlineStatus.None ? 0 : 1; @@ -31,8 +33,8 @@ namespace osu.Game.Beatmaps.Drawables public float TextSize { - get => statusText.TextSize; - set => statusText.TextSize = value; + get => statusText.Font.Size; + set => statusText.Font = statusText.Font.With(size: value); } public MarginPadding TextPadding @@ -58,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold) }, }; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs index 0d421ff690..f1607ad749 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -48,11 +48,12 @@ namespace osu.Game.Beatmaps.Drawables var rating = beatmap.StarDifficulty; - if (rating < 1.5) return DifficultyRating.Easy; - if (rating < 2.25) return DifficultyRating.Normal; - if (rating < 3.75) return DifficultyRating.Hard; - if (rating < 5.25) return DifficultyRating.Insane; - if (rating < 6.75) return DifficultyRating.Expert; + if (rating < 2.0) return DifficultyRating.Easy; + if (rating < 2.7) return DifficultyRating.Normal; + if (rating < 4.0) return DifficultyRating.Hard; + if (rating < 5.3) return DifficultyRating.Insane; + if (rating < 6.5) return DifficultyRating.Expert; + return DifficultyRating.ExpertPlus; } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index fe6200472f..dd8cdb862e 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 724c6d656a..ce7811fc0d 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -1,50 +1,70 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; namespace osu.Game.Beatmaps.Drawables { /// - /// Display a baetmap background from a local source, but fallback to online source if not available. + /// Display a beatmap background from a local source, but fallback to online source if not available. /// public class UpdateableBeatmapBackgroundSprite : ModelBackedDrawable { - public readonly IBindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); [Resolved] private BeatmapManager beatmaps { get; set; } - public UpdateableBeatmapBackgroundSprite() + private readonly BeatmapSetCoverType beatmapSetCoverType; + + public UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) { - Beatmap.BindValueChanged(b => Model = b); + Beatmap.BindValueChanged(b => Model = b.NewValue); + this.beatmapSetCoverType = beatmapSetCoverType; + } + + private BeatmapInfo lastModel; + + protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad) + { + return new DelayedLoadUnloadWrapper(() => + { + // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was + // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. + if (lastModel == Beatmap.Value && Beatmap.Value != null) + return CreateDrawable(Beatmap.Value); + + // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content + lastModel = Beatmap.Value; + return content; + }, timeBeforeLoad, 10000); } protected override Drawable CreateDrawable(BeatmapInfo model) { - return new DelayedLoadUnloadWrapper(() => { - Drawable drawable; + Drawable drawable = getDrawableForModel(model); - var localBeatmap = beatmaps.GetWorkingBeatmap(model); + drawable.RelativeSizeAxes = Axes.Both; + drawable.Anchor = Anchor.Centre; + drawable.Origin = Anchor.Centre; + drawable.FillMode = FillMode.Fill; + drawable.OnLoadComplete += d => d.FadeInFromZero(400); - if (localBeatmap.BeatmapInfo.ID == 0 && model?.BeatmapSet?.OnlineInfo != null) - drawable = new BeatmapSetCover(model.BeatmapSet); - else - drawable = new BeatmapBackgroundSprite(localBeatmap); - - drawable.RelativeSizeAxes = Axes.Both; - drawable.Anchor = Anchor.Centre; - drawable.Origin = Anchor.Centre; - drawable.FillMode = FillMode.Fill; - drawable.OnLoadComplete = d => d.FadeInFromZero(400); - - return drawable; - }, 500, 10000); + return drawable; } - protected override double FadeDuration => 0; + private Drawable getDrawableForModel(BeatmapInfo model) + { + // prefer online cover where available. + if (model?.BeatmapSet?.OnlineInfo != null) + return new BeatmapSetCover(model.BeatmapSet, beatmapSetCoverType); + + return model?.ID > 0 + ? new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(model)) + : new BeatmapBackgroundSprite(beatmaps.DefaultBeatmap); + } } } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs index 9a1617b550..c7c4c1fb1e 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,12 +13,14 @@ namespace osu.Game.Beatmaps.Drawables private Drawable displayedCover; private BeatmapSetInfo beatmapSet; + public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; if (IsLoaded) @@ -27,12 +29,14 @@ namespace osu.Game.Beatmaps.Drawables } private BeatmapSetCoverType coverType = BeatmapSetCoverType.Cover; + public BeatmapSetCoverType CoverType { - get { return coverType; } + get => coverType; set { if (value == coverType) return; + coverType = value; if (IsLoaded) @@ -63,16 +67,19 @@ namespace osu.Game.Beatmaps.Drawables if (beatmapSet != null) { + BeatmapSetCover cover; + Add(displayedCover = new DelayedLoadWrapper( - new BeatmapSetCover(beatmapSet, coverType) + cover = new BeatmapSetCover(beatmapSet, coverType) { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), }) ); + + cover.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out); } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 5c129f76ec..73aa12a3db 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -26,7 +26,12 @@ namespace osu.Game.Beatmaps Title = "no beatmaps available!" }, BeatmapSet = new BeatmapSetInfo(), - BaseDifficulty = new BeatmapDifficulty(), + BaseDifficulty = new BeatmapDifficulty + { + DrainRate = 0, + CircleSize = 0, + OverallDifficulty = 0, + }, Ruleset = new DummyRulesetInfo() }) { @@ -47,7 +52,7 @@ namespace osu.Game.Beatmaps { public override IEnumerable GetModsFor(ModType type) => new Mod[] { }; - public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) + public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap) { throw new NotImplementedException(); } diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 6f45718390..a895ba3d63 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/Formats/IHasComboColours.cs b/osu.Game/Beatmaps/Formats/IHasComboColours.cs index d47377dc8d..4c15cb96d1 100644 --- a/osu.Game/Beatmaps/Formats/IHasComboColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasComboColours.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs index a319d0e48e..8f6c7dc328 100644 --- a/osu.Game/Beatmaps/Formats/IHasCustomColours.cs +++ b/osu.Game/Beatmaps/Formats/IHasCustomColours.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs index fba89b8ac1..d8482b200f 100644 --- a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using osu.Game.IO.Serialization; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 71b7a65ccb..a27126ad9c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using System.Globalization; using System.IO; using System.Linq; using osu.Framework.IO.File; +using osu.Framework.Logging; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; @@ -25,7 +25,7 @@ namespace osu.Game.Beatmaps.Formats public static void Register() { - AddDecoder(@"osu file format v", m => new LegacyBeatmapDecoder(int.Parse(m.Split('v').Last()))); + AddDecoder(@"osu file format v", m => new LegacyBeatmapDecoder(Parsing.ParseInt(m.Split('v').Last()))); } /// @@ -104,25 +104,25 @@ namespace osu.Game.Beatmaps.Formats metadata.AudioFile = FileSafety.PathStandardise(pair.Value); break; case @"AudioLeadIn": - beatmap.BeatmapInfo.AudioLeadIn = int.Parse(pair.Value); + beatmap.BeatmapInfo.AudioLeadIn = Parsing.ParseInt(pair.Value); break; case @"PreviewTime": - metadata.PreviewTime = getOffsetTime(int.Parse(pair.Value)); + metadata.PreviewTime = getOffsetTime(Parsing.ParseInt(pair.Value)); break; case @"Countdown": - beatmap.BeatmapInfo.Countdown = int.Parse(pair.Value) == 1; + beatmap.BeatmapInfo.Countdown = Parsing.ParseInt(pair.Value) == 1; break; case @"SampleSet": defaultSampleBank = (LegacySampleBank)Enum.Parse(typeof(LegacySampleBank), pair.Value); break; case @"SampleVolume": - defaultSampleVolume = int.Parse(pair.Value); + defaultSampleVolume = Parsing.ParseInt(pair.Value); break; case @"StackLeniency": - beatmap.BeatmapInfo.StackLeniency = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.StackLeniency = Parsing.ParseFloat(pair.Value); break; case @"Mode": - beatmap.BeatmapInfo.RulesetID = int.Parse(pair.Value); + beatmap.BeatmapInfo.RulesetID = Parsing.ParseInt(pair.Value); switch (beatmap.BeatmapInfo.RulesetID) { @@ -142,13 +142,13 @@ namespace osu.Game.Beatmaps.Formats break; case @"LetterboxInBreaks": - beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(pair.Value) == 1; + beatmap.BeatmapInfo.LetterboxInBreaks = Parsing.ParseInt(pair.Value) == 1; break; case @"SpecialStyle": - beatmap.BeatmapInfo.SpecialStyle = int.Parse(pair.Value) == 1; + beatmap.BeatmapInfo.SpecialStyle = Parsing.ParseInt(pair.Value) == 1; break; case @"WidescreenStoryboard": - beatmap.BeatmapInfo.WidescreenStoryboard = int.Parse(pair.Value) == 1; + beatmap.BeatmapInfo.WidescreenStoryboard = Parsing.ParseInt(pair.Value) == 1; break; } } @@ -163,16 +163,16 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StoredBookmarks = pair.Value; break; case @"DistanceSpacing": - beatmap.BeatmapInfo.DistanceSpacing = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.DistanceSpacing = Math.Max(0, Parsing.ParseDouble(pair.Value)); break; case @"BeatDivisor": - beatmap.BeatmapInfo.BeatDivisor = int.Parse(pair.Value); + beatmap.BeatmapInfo.BeatDivisor = Parsing.ParseInt(pair.Value); break; case @"GridSize": - beatmap.BeatmapInfo.GridSize = int.Parse(pair.Value); + beatmap.BeatmapInfo.GridSize = Parsing.ParseInt(pair.Value); break; case @"TimelineZoom": - beatmap.BeatmapInfo.TimelineZoom = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + beatmap.BeatmapInfo.TimelineZoom = Math.Max(0, Parsing.ParseDouble(pair.Value)); break; } } @@ -209,10 +209,10 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.Metadata.Tags = pair.Value; break; case @"BeatmapID": - beatmap.BeatmapInfo.OnlineBeatmapID = int.Parse(pair.Value); + beatmap.BeatmapInfo.OnlineBeatmapID = Parsing.ParseInt(pair.Value); break; case @"BeatmapSetID": - beatmap.BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = int.Parse(pair.Value) }; + beatmap.BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = Parsing.ParseInt(pair.Value) }; break; } } @@ -225,22 +225,22 @@ namespace osu.Game.Beatmaps.Formats switch (pair.Key) { case @"HPDrainRate": - difficulty.DrainRate = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.DrainRate = Parsing.ParseFloat(pair.Value); break; case @"CircleSize": - difficulty.CircleSize = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.CircleSize = Parsing.ParseFloat(pair.Value); break; case @"OverallDifficulty": - difficulty.OverallDifficulty = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.OverallDifficulty = Parsing.ParseFloat(pair.Value); break; case @"ApproachRate": - difficulty.ApproachRate = float.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.ApproachRate = Parsing.ParseFloat(pair.Value); break; case @"SliderMultiplier": - difficulty.SliderMultiplier = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.SliderMultiplier = Parsing.ParseDouble(pair.Value); break; case @"SliderTickRate": - difficulty.SliderTickRate = double.Parse(pair.Value, NumberFormatInfo.InvariantInfo); + difficulty.SliderTickRate = Parsing.ParseDouble(pair.Value); break; } } @@ -260,10 +260,12 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(filename); break; case EventType.Break: + double start = getOffsetTime(Parsing.ParseDouble(split[1])); + var breakEvent = new BreakPeriod { - StartTime = getOffsetTime(double.Parse(split[1], NumberFormatInfo.InvariantInfo)), - EndTime = getOffsetTime(double.Parse(split[2], NumberFormatInfo.InvariantInfo)) + StartTime = start, + EndTime = Math.Max(start, getOffsetTime(Parsing.ParseDouble(split[2]))) }; if (!breakEvent.HasEffect) @@ -280,25 +282,25 @@ namespace osu.Game.Beatmaps.Formats { string[] split = line.Split(','); - double time = getOffsetTime(double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo)); - double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); + double time = getOffsetTime(Parsing.ParseDouble(split[0].Trim())); + double beatLength = Parsing.ParseDouble(split[1].Trim()); double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; if (split.Length >= 3) - timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)int.Parse(split[2]); + timeSignature = split[2][0] == '0' ? TimeSignatures.SimpleQuadruple : (TimeSignatures)Parsing.ParseInt(split[2]); LegacySampleBank sampleSet = defaultSampleBank; if (split.Length >= 4) - sampleSet = (LegacySampleBank)int.Parse(split[3]); + sampleSet = (LegacySampleBank)Parsing.ParseInt(split[3]); int customSampleBank = 0; if (split.Length >= 5) - customSampleBank = int.Parse(split[4]); + customSampleBank = Parsing.ParseInt(split[4]); int sampleVolume = defaultSampleVolume; if (split.Length >= 6) - sampleVolume = int.Parse(split[5]); + sampleVolume = Parsing.ParseInt(split[5]); bool timingChange = true; if (split.Length >= 7) @@ -308,7 +310,7 @@ namespace osu.Game.Beatmaps.Formats bool omitFirstBarSignature = false; if (split.Length >= 8) { - EffectFlags effectFlags = (EffectFlags)int.Parse(split[7]); + EffectFlags effectFlags = (EffectFlags)Parsing.ParseInt(split[7]); kiaiMode = effectFlags.HasFlag(EffectFlags.Kiai); omitFirstBarSignature = effectFlags.HasFlag(EffectFlags.OmitFirstBarLine); } @@ -348,8 +350,13 @@ namespace osu.Game.Beatmaps.Formats CustomSampleBank = customSampleBank }); } - catch (FormatException e) + catch (FormatException) { + Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); + } + catch (OverflowException) + { + Logger.Log("A timing point could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 217f16b263..040f582e3b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -72,6 +72,7 @@ namespace osu.Game.Beatmaps.Formats var index = line.AsSpan().IndexOf("//".AsSpan()); if (index > 0) return line.Substring(0, index); + return line; } @@ -115,6 +116,7 @@ namespace osu.Game.Beatmaps.Formats else { if (!(output is IHasCustomColours tHasCustomColours)) return; + tHasCustomColours.CustomColours[pair.Key] = colour; } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs index 13a71aac3d..540f616ea9 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDifficultyCalculatorBeatmapDecoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index d30c78cb17..9584b10ef5 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/Formats/Parsing.cs b/osu.Game/Beatmaps/Formats/Parsing.cs new file mode 100644 index 0000000000..c3efb8c760 --- /dev/null +++ b/osu.Game/Beatmaps/Formats/Parsing.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Globalization; + +namespace osu.Game.Beatmaps.Formats +{ + /// + /// Helper methods to parse from string to number and perform very basic validation. + /// + public static class Parsing + { + public const int MAX_COORDINATE_VALUE = 65536; + + public const double MAX_PARSE_VALUE = int.MaxValue; + + public static float ParseFloat(string input, float parseLimit = (float)MAX_PARSE_VALUE) + { + var output = float.Parse(input, CultureInfo.InvariantCulture); + + if (output < -parseLimit) throw new OverflowException("Value is too low"); + if (output > parseLimit) throw new OverflowException("Value is too high"); + + if (float.IsNaN(output)) throw new FormatException("Not a number"); + + return output; + } + + public static double ParseDouble(string input, double parseLimit = MAX_PARSE_VALUE) + { + var output = double.Parse(input, CultureInfo.InvariantCulture); + + if (output < -parseLimit) throw new OverflowException("Value is too low"); + if (output > parseLimit) throw new OverflowException("Value is too high"); + + if (double.IsNaN(output)) throw new FormatException("Not a number"); + + return output; + } + + public static int ParseInt(string input, int parseLimit = (int)MAX_PARSE_VALUE) + { + var output = int.Parse(input, CultureInfo.InvariantCulture); + + if (output < -parseLimit) throw new OverflowException("Value is too low"); + if (output > parseLimit) throw new OverflowException("Value is too high"); + + return output; + } + } +} diff --git a/osu.Game/Beatmaps/IBeatmap.cs b/osu.Game/Beatmaps/IBeatmap.cs index 3d8b94dc46..512fe25809 100644 --- a/osu.Game/Beatmaps/IBeatmap.cs +++ b/osu.Game/Beatmaps/IBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs index a710afad16..f2213b85f1 100644 --- a/osu.Game/Beatmaps/IBeatmapConverter.cs +++ b/osu.Game/Beatmaps/IBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/IBeatmapProcessor.cs b/osu.Game/Beatmaps/IBeatmapProcessor.cs index 4d634d7912..014dccf5e3 100644 --- a/osu.Game/Beatmaps/IBeatmapProcessor.cs +++ b/osu.Game/Beatmaps/IBeatmapProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/IBindableBeatmap.cs b/osu.Game/Beatmaps/IBindableBeatmap.cs deleted file mode 100644 index 329c0b6a3c..0000000000 --- a/osu.Game/Beatmaps/IBindableBeatmap.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; - -namespace osu.Game.Beatmaps -{ - /// - /// Read-only interface for the beatmap. - /// - public interface IBindableBeatmap : IBindable - { - /// - /// Retrieve a new instance weakly bound to this . - /// If you are further binding to events of the retrieved , ensure a local reference is held. - /// - IBindableBeatmap GetBoundCopy(); - } -} diff --git a/osu.Game/Beatmaps/Legacy/LegacyMods.cs b/osu.Game/Beatmaps/Legacy/LegacyMods.cs index 0983610ba0..8e53c24e7b 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyMods.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyMods.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 0524704b8c..7cff54a058 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Beatmaps.Timing { diff --git a/osu.Game/Beatmaps/Timing/TimeSignatures.cs b/osu.Game/Beatmaps/Timing/TimeSignatures.cs index aa25c76fc5..147f6239b4 100644 --- a/osu.Game/Beatmaps/Timing/TimeSignatures.cs +++ b/osu.Game/Beatmaps/Timing/TimeSignatures.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Beatmaps.Timing { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index e65409a1d1..2e36d87024 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -1,17 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio.Track; -using osu.Framework.Configuration; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; -using System.Linq; using osu.Game.Storyboards; using osu.Framework.IO.File; using System.IO; +using System.Linq; using System.Threading; +using osu.Framework.Bindables; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - Mods.ValueChanged += mods => applyRateAdjustments(); + Mods.ValueChanged += _ => applyRateAdjustments(); beatmap = new RecyclableLazy(() => { diff --git a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs b/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs index d2e6ac1db8..cb1be82c69 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap_VirtualBeatmapTrack.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Audio.Track; diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index 334fed2b5a..f547a7d3e1 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Game.Rulesets; @@ -60,9 +61,9 @@ namespace osu.Game.Configuration databasedSettings.Add(setting); } - bindable.ValueChanged += v => + bindable.ValueChanged += b => { - setting.Value = v; + setting.Value = b.NewValue; settings.Update(setting); }; } diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs index 6c2822734b..d56ac49358 100644 --- a/osu.Game/Configuration/DatabasedSetting.cs +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 8df286ffb2..2d8cfa12ee 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; @@ -33,14 +33,14 @@ namespace osu.Game.Configuration Set(OsuSetting.Username, string.Empty); Set(OsuSetting.Token, string.Empty); - Set(OsuSetting.SavePassword, false).ValueChanged += val => + Set(OsuSetting.SavePassword, false).ValueChanged += enabled => { - if (val) Set(OsuSetting.SaveUsername, true); + if (enabled.NewValue) Set(OsuSetting.SaveUsername, true); }; - Set(OsuSetting.SaveUsername, true).ValueChanged += val => + Set(OsuSetting.SaveUsername, true).ValueChanged += enabled => { - if (!val) Set(OsuSetting.SavePassword, false); + if (!enabled.NewValue) Set(OsuSetting.SavePassword, false); }; Set(OsuSetting.ExternalLinkWarning, true); @@ -72,9 +72,6 @@ namespace osu.Game.Configuration Set(OsuSetting.MenuParallax, true); - Set(OsuSetting.SnakingInSliders, true); - Set(OsuSetting.SnakingOutSliders, true); - // Gameplay Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); @@ -105,6 +102,8 @@ namespace osu.Game.Configuration Set(OsuSetting.ScalingPositionX, 0.5f, 0f, 1f); Set(OsuSetting.ScalingPositionY, 0.5f, 0f, 1f); + + Set(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f); } public OsuConfigManager(Storage storage) @@ -148,8 +147,6 @@ namespace osu.Game.Configuration DisplayStarsMinimum, DisplayStarsMaximum, RandomSelectAlgorithm, - SnakingInSliders, - SnakingOutSliders, ShowFpsDisplay, ChatDisplayHeight, Version, @@ -167,6 +164,7 @@ namespace osu.Game.Configuration ScalingPositionX, ScalingPositionY, ScalingSizeX, - ScalingSizeY + ScalingSizeY, + UIScale } } diff --git a/osu.Game/Configuration/RandomSelectAlgorithm.cs b/osu.Game/Configuration/RandomSelectAlgorithm.cs index d994f59b34..8d0c87374f 100644 --- a/osu.Game/Configuration/RandomSelectAlgorithm.cs +++ b/osu.Game/Configuration/RandomSelectAlgorithm.cs @@ -1,14 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; namespace osu.Game.Configuration { - public enum RandomSelectAlgorithm + public enum RandomSelectAlgorithm { [Description("Never repeat")] RandomPermutation, + [Description("Random")] Random } diff --git a/osu.Game/Configuration/RankingType.cs b/osu.Game/Configuration/RankingType.cs index 32fe934100..7701e1dd1d 100644 --- a/osu.Game/Configuration/RankingType.cs +++ b/osu.Game/Configuration/RankingType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -8,8 +8,10 @@ namespace osu.Game.Configuration public enum RankingType { Local, + [Description("Global")] Top, + [Description("Selected Mods")] SelectedMod, Friends, diff --git a/osu.Game/Configuration/ReleaseStream.cs b/osu.Game/Configuration/ReleaseStream.cs index ca13d0cac3..ed0bee1dd8 100644 --- a/osu.Game/Configuration/ReleaseStream.cs +++ b/osu.Game/Configuration/ReleaseStream.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Configuration { diff --git a/osu.Game/Configuration/ScalingMode.cs b/osu.Game/Configuration/ScalingMode.cs index b907d55d82..0bcc908f71 100644 --- a/osu.Game/Configuration/ScalingMode.cs +++ b/osu.Game/Configuration/ScalingMode.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,6 +9,7 @@ namespace osu.Game.Configuration { Off, Everything, + [Description("Excluding overlays")] ExcludeOverlays, Gameplay, diff --git a/osu.Game/Configuration/ScoreMeterType.cs b/osu.Game/Configuration/ScoreMeterType.cs index 0333c3406f..21a63fb3ed 100644 --- a/osu.Game/Configuration/ScoreMeterType.cs +++ b/osu.Game/Configuration/ScoreMeterType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Configuration { diff --git a/osu.Game/Configuration/ScreenshotFormat.cs b/osu.Game/Configuration/ScreenshotFormat.cs index 43901281dc..6d4c96bfa9 100644 --- a/osu.Game/Configuration/ScreenshotFormat.cs +++ b/osu.Game/Configuration/ScreenshotFormat.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,6 +9,7 @@ namespace osu.Game.Configuration { [Description("JPG (web-friendly)")] Jpg = 1, + [Description("PNG (lossless)")] Png = 2 } diff --git a/osu.Game/Configuration/ScrollVisualisationMethod.cs b/osu.Game/Configuration/ScrollVisualisationMethod.cs index cc7dcdbc0e..5f48fe8bfd 100644 --- a/osu.Game/Configuration/ScrollVisualisationMethod.cs +++ b/osu.Game/Configuration/ScrollVisualisationMethod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,8 +9,10 @@ namespace osu.Game.Configuration { [Description("Sequential")] Sequential, + [Description("Overlapping")] Overlapping, + [Description("Constant")] Constant } diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs index 7914e34147..f15fd1f17b 100644 --- a/osu.Game/Configuration/SettingsStore.cs +++ b/osu.Game/Configuration/SettingsStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 77e92421e9..3805921ac2 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; +using osu.Framework; using osu.Framework.Extensions; using osu.Framework.IO.File; using osu.Framework.Logging; @@ -32,7 +33,7 @@ namespace osu.Game.Database where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete where TFileModel : INamedFileInfo, new() { - public delegate void ItemAddedDelegate(TModel model, bool existing, bool silent); + public delegate void ItemAddedDelegate(TModel model, bool existing); /// /// Set an endpoint for notifications to be posted to. @@ -53,6 +54,8 @@ namespace osu.Game.Database public virtual string[] HandledExtensions => new[] { ".zip" }; + public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop; + protected readonly FileStore Files; protected readonly IDatabaseContextFactory ContextFactory; @@ -105,12 +108,12 @@ namespace osu.Game.Database a.Invoke(); } - protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStore modelStore, IIpcHost importHost = null) + protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes modelStore, IIpcHost importHost = null) { ContextFactory = contextFactory; ModelStore = modelStore; - ModelStore.ItemAdded += (item, silent) => handleEvent(() => ItemAdded?.Invoke(item, false, silent)); + ModelStore.ItemAdded += item => handleEvent(() => ItemAdded?.Invoke(item, false)); ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s)); Files = new FileStore(contextFactory, storage); @@ -128,14 +131,18 @@ namespace osu.Game.Database /// One or more archive locations on disk. public void Import(params string[] paths) { - var notification = new ProgressNotification - { - Text = "Import is initialising...", - Progress = 0, - State = ProgressNotificationState.Active, - }; + var notification = new ProgressNotification { State = ProgressNotificationState.Active }; PostNotification?.Invoke(notification); + Import(notification, paths); + } + + protected void Import(ProgressNotification notification, params string[] paths) + { + notification.Progress = 0; + notification.Text = "Import is initialising..."; + + var term = $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; List imported = new List(); @@ -148,27 +155,22 @@ namespace osu.Game.Database try { - notification.Text = $"Importing ({++current} of {paths.Length})\n{Path.GetFileName(path)}"; + var text = "Importing "; - TModel import; - using (ArchiveReader reader = getReaderFrom(path)) - imported.Add(import = Import(reader)); + if (path.Length > 1) + text += $"{++current} of {paths.Length} {term}s.."; + else + text += $"{term}.."; + + // only show the filename if it isn't a temporary one (as those look ugly). + if (!path.Contains(Path.GetTempPath())) + text += $"\n{Path.GetFileName(path)}"; + + notification.Text = text; + + imported.Add(Import(path)); notification.Progress = (float)current / paths.Length; - - // We may or may not want to delete the file depending on where it is stored. - // e.g. reconstructing/repairing database with items from default storage. - // Also, not always a single file, i.e. for LegacyFilesystemReader - // TODO: Add a check to prevent files from storage to be deleted. - try - { - if (import != null && File.Exists(path)) - File.Delete(path); - } - catch (Exception e) - { - Logger.Error(e, $@"Could not delete original file after import ({Path.GetFileName(path)})"); - } } catch (Exception e) { @@ -184,21 +186,57 @@ namespace osu.Game.Database } else { - notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!"; - notification.CompletionClickAction += () => + notification.CompletionText = imported.Count == 1 + ? $"Imported {imported.First()}!" + : $"Imported {current} {term}s!"; + + if (imported.Count > 0 && PresentImport != null) { - if (imported.Count > 0) - PresentCompletedImport(imported); - return true; - }; + notification.CompletionText += " Click to view."; + notification.CompletionClickAction = () => + { + PresentImport?.Invoke(imported); + return true; + }; + } + notification.State = ProgressNotificationState.Completed; } } - protected virtual void PresentCompletedImport(IEnumerable imported) + /// + /// Import one from the filesystem and delete the file on success. + /// + /// The archive location on disk. + /// The imported model, if successful. + public TModel Import(string path) { + TModel import; + using (ArchiveReader reader = getReaderFrom(path)) + import = Import(reader); + + // We may or may not want to delete the file depending on where it is stored. + // e.g. reconstructing/repairing database with items from default storage. + // Also, not always a single file, i.e. for LegacyFilesystemReader + // TODO: Add a check to prevent files from storage to be deleted. + try + { + if (import != null && File.Exists(path)) + File.Delete(path); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete original file after import ({Path.GetFileName(path)})"); + } + + return import; } + /// + /// Fired when the user requests to view the resulting import. + /// + public Action> PresentImport; + /// /// Import an item from an . /// @@ -213,7 +251,7 @@ namespace osu.Game.Database model.Hash = computeHash(archive); - return Import(model, false, archive); + return Import(model, archive); } catch (Exception e) { @@ -247,9 +285,8 @@ namespace osu.Game.Database /// Import an item from a . /// /// The model to be imported. - /// Whether the user should be notified fo the import. /// An optional archive to use for model population. - public TModel Import(TModel item, bool silent = false, ArchiveReader archive = null) + public TModel Import(TModel item, ArchiveReader archive = null) { delayEvents(); @@ -263,23 +300,33 @@ namespace osu.Game.Database { if (!write.IsTransactionLeader) throw new InvalidOperationException($"Ensure there is no parent transaction so errors can correctly be handled by {this}"); - var existing = CheckForExisting(item); - - if (existing != null) - { - Undelete(existing); - Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); - handleEvent(() => ItemAdded?.Invoke(existing, true, silent)); - return existing; - } - if (archive != null) item.Files = createFileInfos(archive, Files); Populate(item, archive); + var existing = CheckForExisting(item); + + if (existing != null) + { + if (CanUndelete(existing, item)) + { + Undelete(existing); + Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); + handleEvent(() => ItemAdded?.Invoke(existing, true)); + return existing; + } + else + { + Delete(existing); + ModelStore.PurgeDeletable(s => s.ID == existing.ID); + } + } + + PreImport(item); + // import to store - ModelStore.Add(item, silent); + ModelStore.Add(item); } catch (Exception e) { @@ -505,12 +552,29 @@ namespace osu.Game.Database { } + /// + /// Perform any final actions before the import to database executes. + /// + /// The model prepared for import. + protected virtual void PreImport(TModel model) + { + } + /// /// Check whether an existing model already exists for a new import item. /// - /// The new model proposed for import. Note that has not yet been run on this model. + /// The new model proposed for import. /// An existing model which matches the criteria to skip importing, else null. - protected virtual TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); + protected TModel CheckForExisting(TModel model) => model.Hash == null ? null : ModelStore.ConsumableItems.FirstOrDefault(b => b.Hash == model.Hash); + + /// + /// After an existing is found during an import process, the default behaviour is to restore the existing + /// item and skip the import. This method allows changing that behaviour. + /// + /// The existing model. + /// The newly imported model. + /// Whether the existing model should be restored and used. Returning false will delete the existing a force a re-import. + protected virtual bool CanUndelete(TModel existing, TModel import) => true; private DbSet queryModel() => ContextFactory.Get().Set(); @@ -527,6 +591,7 @@ namespace osu.Game.Database return new LegacyDirectoryArchiveReader(path); if (File.Exists(path)) return new LegacyFileArchiveReader(path); + throw new InvalidFormatException($"{path} is not a valid archive"); } } diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index c6fb51c056..e6b6a0ac2f 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using Microsoft.EntityFrameworkCore; diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 2037612a09..f6250732d9 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game/Database/DatabaseWriteUsage.cs b/osu.Game/Database/DatabaseWriteUsage.cs index 64ab24e824..1fd2f23d50 100644 --- a/osu.Game/Database/DatabaseWriteUsage.cs +++ b/osu.Game/Database/DatabaseWriteUsage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -31,6 +31,7 @@ namespace osu.Game.Database protected void Dispose(bool disposing) { if (isDisposed) return; + isDisposed = true; try diff --git a/osu.Game/Database/ICanAcceptFiles.cs b/osu.Game/Database/ICanAcceptFiles.cs index a3766ef5aa..f55d0c389e 100644 --- a/osu.Game/Database/ICanAcceptFiles.cs +++ b/osu.Game/Database/ICanAcceptFiles.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Database { diff --git a/osu.Game/Database/IDatabaseContextFactory.cs b/osu.Game/Database/IDatabaseContextFactory.cs index d38d15b252..72b70a208f 100644 --- a/osu.Game/Database/IDatabaseContextFactory.cs +++ b/osu.Game/Database/IDatabaseContextFactory.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Database { diff --git a/osu.Game/Database/IHasFiles.cs b/osu.Game/Database/IHasFiles.cs index b5ac22efc9..f6aa941ec2 100644 --- a/osu.Game/Database/IHasFiles.cs +++ b/osu.Game/Database/IHasFiles.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index c62e78ea23..3c0fc94418 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; diff --git a/osu.Game/Database/INamedFileInfo.cs b/osu.Game/Database/INamedFileInfo.cs index 04dcdad285..d95f228440 100644 --- a/osu.Game/Database/INamedFileInfo.cs +++ b/osu.Game/Database/INamedFileInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.IO; diff --git a/osu.Game/Database/ISoftDelete.cs b/osu.Game/Database/ISoftDelete.cs index 38fba62421..afa42c2002 100644 --- a/osu.Game/Database/ISoftDelete.cs +++ b/osu.Game/Database/ISoftDelete.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Database { diff --git a/osu.Game/Database/MutableDatabaseBackedStore.cs b/osu.Game/Database/MutableDatabaseBackedStore.cs index dc2fe54aac..39a48b5be6 100644 --- a/osu.Game/Database/MutableDatabaseBackedStore.cs +++ b/osu.Game/Database/MutableDatabaseBackedStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -16,9 +16,7 @@ namespace osu.Game.Database public abstract class MutableDatabaseBackedStore : DatabaseBackedStore where T : class, IHasPrimaryKey, ISoftDelete { - public delegate void ItemAddedDelegate(T model, bool silent); - - public event ItemAddedDelegate ItemAdded; + public event Action ItemAdded; public event Action ItemRemoved; protected MutableDatabaseBackedStore(IDatabaseContextFactory contextFactory, Storage storage = null) @@ -35,8 +33,7 @@ namespace osu.Game.Database /// Add a to the database. /// /// The item to add. - /// Whether the user should be notified of the addition. - public void Add(T item, bool silent) + public void Add(T item) { using (var usage = ContextFactory.GetForWrite()) { @@ -44,7 +41,7 @@ namespace osu.Game.Database context.Attach(item); } - ItemAdded?.Invoke(item, silent); + ItemAdded?.Invoke(item); } /// @@ -57,7 +54,7 @@ namespace osu.Game.Database usage.Context.Update(item); ItemRemoved?.Invoke(item); - ItemAdded?.Invoke(item, true); + ItemAdded?.Invoke(item); } /// @@ -71,6 +68,7 @@ namespace osu.Game.Database Refresh(ref item); if (item.DeletePending) return false; + item.DeletePending = true; } @@ -89,10 +87,11 @@ namespace osu.Game.Database Refresh(ref item, ConsumableItems); if (!item.DeletePending) return false; + item.DeletePending = false; } - ItemAdded?.Invoke(item, true); + ItemAdded?.Invoke(item); return true; } diff --git a/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs b/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs new file mode 100644 index 0000000000..5d6ff6b09b --- /dev/null +++ b/osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs @@ -0,0 +1,27 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using Microsoft.EntityFrameworkCore; +using osu.Framework.Platform; + +namespace osu.Game.Database +{ + public abstract class MutableDatabaseBackedStoreWithFileIncludes : MutableDatabaseBackedStore + where T : class, IHasPrimaryKey, ISoftDelete, IHasFiles + where U : INamedFileInfo + { + protected MutableDatabaseBackedStoreWithFileIncludes(IDatabaseContextFactory contextFactory, Storage storage = null) + : base(contextFactory, storage) + { + } + + protected override IQueryable AddIncludesForConsumption(IQueryable query) => + base.AddIncludesForConsumption(query) + .Include(s => s.Files).ThenInclude(f => f.FileInfo); + + protected override IQueryable AddIncludesForDeletion(IQueryable query) => + base.AddIncludesForDeletion(query) + .Include(s => s.Files); // don't include FileInfo. these are handled by the FileStore itself. + } +} diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index db5a2771d4..17efe2c839 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Microsoft.EntityFrameworkCore; diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index d3d530a540..db055d15e5 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index eb8dc7243e..c67d779c37 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.MathUtils; @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.Backgrounds private readonly SortedList parts = new SortedList(Comparer.Default); - private Shader shader; + private IShader shader; private readonly Texture texture; public Triangles() @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.Backgrounds [BackgroundDependencyLoader] private void load(ShaderManager shaders) { - shader = shaders?.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); + shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); } protected override void LoadComplete() @@ -86,7 +86,7 @@ namespace osu.Game.Graphics.Backgrounds public float TriangleScale { - get { return triangleScale; } + get => triangleScale; set { float change = value / triangleScale; @@ -110,10 +110,10 @@ namespace osu.Game.Graphics.Backgrounds if (CreateNewTriangles) addTriangles(false); - float adjustedAlpha = HideAlphaDiscrepancies ? + float adjustedAlpha = HideAlphaDiscrepancies // Cubically scale alpha to make it drop off more sharply. - (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) : - 1; + ? (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) + : 1; float elapsedSeconds = (float)Time.Elapsed / 1000; // Since position is relative, the velocity needs to scale inversely with DrawHeight. @@ -180,7 +180,6 @@ namespace osu.Game.Graphics.Backgrounds protected override DrawNode CreateDrawNode() => new TrianglesDrawNode(); - private readonly TrianglesDrawNodeSharedData sharedData = new TrianglesDrawNodeSharedData(); protected override void ApplyDrawNode(DrawNode node) { base.ApplyDrawNode(node); @@ -190,27 +189,21 @@ namespace osu.Game.Graphics.Backgrounds trianglesNode.Shader = shader; trianglesNode.Texture = texture; trianglesNode.Size = DrawSize; - trianglesNode.Shared = sharedData; trianglesNode.Parts.Clear(); trianglesNode.Parts.AddRange(parts); } - private class TrianglesDrawNodeSharedData - { - public readonly LinearBatch VertexBatch = new LinearBatch(100 * 3, 10, PrimitiveType.Triangles); - } - private class TrianglesDrawNode : DrawNode { - public Shader Shader; + public IShader Shader; public Texture Texture; - public TrianglesDrawNodeSharedData Shared; - public readonly List Parts = new List(); public Vector2 Size; + private readonly LinearBatch vertexBatch = new LinearBatch(100 * 3, 10, PrimitiveType.Triangles); + public override void Draw(Action vertexAction) { base.Draw(vertexAction); @@ -238,12 +231,19 @@ namespace osu.Game.Graphics.Backgrounds triangle, colourInfo, null, - Shared.VertexBatch.AddAction, + vertexBatch.AddAction, Vector2.Divide(localInflationAmount, size)); } Shader.Unbind(); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + vertexBatch.Dispose(); + } } protected struct TriangleParticle : IComparable diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index f0d49af988..621eeea2b7 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; @@ -74,7 +74,7 @@ namespace osu.Game.Graphics.Containers } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) + private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); } diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index aae05ca767..c1811f37d5 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -15,15 +15,9 @@ namespace osu.Game.Graphics.Containers { public Drawable Icon { - get - { - return InternalChild; - } + get => InternalChild; - set - { - InternalChild = value; - } + set => InternalChild = value; } /// @@ -33,8 +27,8 @@ namespace osu.Game.Graphics.Containers /// public new EdgeEffectParameters EdgeEffect { - get { return base.EdgeEffect; } - set { base.EdgeEffect = value; } + get => base.EdgeEffect; + set => base.EdgeEffect = value; } protected override void Update() diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index adfc258f61..a5b5b7af42 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 74315d2522..37afefb7f8 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Online.Chat; using System; @@ -61,24 +61,25 @@ namespace osu.Game.Graphics.Containers AddText(text.Substring(previousLinkEnd)); } - public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) + public IEnumerable AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action creationParameters = null) => createLink(AddText(text, creationParameters), text, url, linkType, linkArgument, tooltipText); - public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + public IEnumerable AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) => createLink(AddText(text, creationParameters), text, tooltipText: tooltipText, action: action); - public void AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + public IEnumerable AddLink(IEnumerable text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) { foreach (var t in text) AddArbitraryDrawable(t); - createLink(text, null, url, linkType, linkArgument, tooltipText); + return createLink(text, null, url, linkType, linkArgument, tooltipText); } - private void createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) + private IEnumerable createLink(IEnumerable drawables, string text, string url = null, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null, Action action = null) { AddInternal(new DrawableLinkCompiler(drawables.OfType().ToList()) { + RelativeSizeAxes = Axes.Both, TooltipText = tooltipText ?? (url != text ? url : string.Empty), Action = action ?? (() => { @@ -121,6 +122,13 @@ namespace osu.Game.Graphics.Containers } }), }); + + return drawables; } + + // We want the compilers to always be visible no matter where they are, so RelativeSizeAxes is used. + // However due to https://github.com/ppy/osu-framework/issues/2073, it's possible for the compilers to be relative size in the flow's auto-size axes - an unsupported operation. + // Since the compilers don't display any content and don't affect the layout, it's simplest to exclude them from the flow. + public override IEnumerable FlowingChildren => base.FlowingChildren.Where(c => !(c is DrawableLinkCompiler)); } } diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index cf80a549a4..e4d30cebb7 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index ad46e50344..c6ee91f961 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osuTK; -using osu.Framework.Configuration; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Audio; @@ -24,7 +24,17 @@ namespace osu.Game.Graphics.Containers protected override bool BlockNonPositionalInput => true; - private PreviewTrackManager previewTrackManager; + /// + /// Temporary to allow for overlays in the main screen content to not dim theirselves. + /// Should be eventually replaced by dimming which is aware of the target dim container (traverse parent for certain interface type?). + /// + protected virtual bool DimMainContent => true; + + [Resolved(CanBeNull = true)] + private OsuGame osuGame { get; set; } + + [Resolved] + private PreviewTrackManager previewTrackManager { get; set; } protected readonly Bindable OverlayActivationMode = new Bindable(OverlayActivation.All); @@ -36,10 +46,8 @@ namespace osu.Game.Graphics.Containers } [BackgroundDependencyLoader(true)] - private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) + private void load(AudioManager audio) { - this.previewTrackManager = previewTrackManager; - if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); @@ -90,15 +98,18 @@ namespace osu.Game.Graphics.Containers switch (visibility) { case Visibility.Visible: - if (OverlayActivationMode != OverlayActivation.Disabled) + if (OverlayActivationMode.Value != OverlayActivation.Disabled) { if (PlaySamplesOnStateChange) samplePopIn?.Play(); + if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this); } else State = Visibility.Hidden; + break; case Visibility.Hidden: if (PlaySamplesOnStateChange) samplePopOut?.Play(); + if (BlockScreenWideMouse) osuGame?.RemoveBlockingOverlay(this); break; } } @@ -108,5 +119,11 @@ namespace osu.Game.Graphics.Containers base.PopOut(); previewTrackManager.StopAnyPlaying(this); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + osuGame?.RemoveBlockingOverlay(this); + } } } diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index af804735a8..276b0f9dd1 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osuTK.Graphics; diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 8aeade9265..f7d406a419 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs index e77e075fe2..56e5f411b8 100644 --- a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -11,7 +12,8 @@ namespace osu.Game.Graphics.Containers { public class OsuTextFlowContainer : TextFlowContainer { - public OsuTextFlowContainer(Action defaultCreationParameters = null) : base(defaultCreationParameters) + public OsuTextFlowContainer(Action defaultCreationParameters = null) + : base(defaultCreationParameters) { } @@ -19,6 +21,6 @@ namespace osu.Game.Graphics.Containers public void AddArbitraryDrawable(Drawable drawable) => AddInternal(drawable); - public void AddIcon(FontAwesome icon, Action creationParameters = null) => AddText(((char)icon).ToString(), creationParameters); + public IEnumerable AddIcon(FontAwesome icon, Action creationParameters = null) => AddText(((char)icon).ToString(), creationParameters); } } diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 97e12ec0f9..f65a0a469a 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Input; using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Configuration; -using osu.Framework.Configuration; using osu.Framework.MathUtils; namespace osu.Game.Graphics.Containers @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers parallaxEnabled = config.GetBindable(OsuSetting.MenuParallax); parallaxEnabled.ValueChanged += delegate { - if (!parallaxEnabled) + if (!parallaxEnabled.Value) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); @@ -65,7 +65,7 @@ namespace osu.Game.Graphics.Containers { base.Update(); - if (parallaxEnabled) + if (parallaxEnabled.Value) { Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.Position) - DrawSize / 2) * ParallaxAmount; diff --git a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs index e6dcb336e7..6360e41bef 100644 --- a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index ff7a1cdacf..8f07c3a656 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -1,12 +1,14 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; using osu.Game.Configuration; -using osu.Game.Graphics.Backgrounds; +using osu.Game.Screens; +using osu.Game.Screens.Backgrounds; using osuTK; namespace osu.Game.Graphics.Containers @@ -28,9 +30,11 @@ namespace osu.Game.Graphics.Containers private readonly Container content; protected override Container Content => content; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + private readonly Container sizableContainer; - private Drawable backgroundLayer; + private BackgroundScreenStack backgroundStack; /// /// Create a new instance. @@ -41,15 +45,44 @@ namespace osu.Game.Graphics.Containers this.targetMode = targetMode; RelativeSizeAxes = Axes.Both; - InternalChild = sizableContainer = new Container + InternalChild = sizableContainer = new AlwaysInputContainer { RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, CornerRadius = 10, - Child = content = new DrawSizePreservingFillContainer() + Child = content = new ScalingDrawSizePreservingFillContainer(targetMode != ScalingMode.Gameplay) }; } + private class ScalingDrawSizePreservingFillContainer : DrawSizePreservingFillContainer + { + private readonly bool applyUIScale; + private Bindable uiScale; + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + public ScalingDrawSizePreservingFillContainer(bool applyUIScale) + { + this.applyUIScale = applyUIScale; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager osuConfig) + { + if (applyUIScale) + { + uiScale = osuConfig.GetBindable(OsuSetting.UIScale); + uiScale.BindValueChanged(scaleChanged, true); + } + } + + private void scaleChanged(ValueChangedEvent args) + { + this.ScaleTo(new Vector2(args.NewValue), 500, Easing.Out); + this.ResizeTo(new Vector2(1 / args.NewValue), 500, Easing.Out); + } + } + [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -77,37 +110,39 @@ namespace osu.Game.Graphics.Containers sizableContainer.FinishTransforms(); } - private bool requiresBackgroundVisible => (scalingMode == ScalingMode.Everything || scalingMode == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); + private bool requiresBackgroundVisible => (scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); private void updateSize() { + const float fade_time = 500; + if (targetMode == ScalingMode.Everything) { // the top level scaling container manages the background to be displayed while scaling. if (requiresBackgroundVisible) { - if (backgroundLayer == null) - LoadComponentAsync(backgroundLayer = new Background("Menu/menu-background-1") + if (backgroundStack == null) + { + AddInternal(backgroundStack = new BackgroundScreenStack { Colour = OsuColour.Gray(0.1f), Alpha = 0, Depth = float.MaxValue - }, d => - { - AddInternal(d); - d.FadeTo(requiresBackgroundVisible ? 1 : 0, 4000, Easing.OutQuint); }); - else - backgroundLayer.FadeIn(500); + + backgroundStack.Push(new ScalingBackgroundScreen()); + } + + backgroundStack.FadeIn(fade_time); } else - backgroundLayer?.FadeOut(500); + backgroundStack?.FadeOut(fade_time); } bool scaling = targetMode == null || scalingMode.Value == targetMode; - var targetSize = scaling ? new Vector2(sizeX, sizeY) : Vector2.One; - var targetPosition = scaling ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; + var targetSize = scaling ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One; + var targetPosition = scaling ? new Vector2(posX.Value, posY.Value) * (Vector2.One - targetSize) : Vector2.Zero; bool requiresMasking = scaling && targetSize != Vector2.One; if (requiresMasking) @@ -116,5 +151,23 @@ namespace osu.Game.Graphics.Containers sizableContainer.MoveTo(targetPosition, 500, Easing.OutQuart); sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { sizableContainer.Masking = requiresMasking; }); } + + private class ScalingBackgroundScreen : BackgroundScreenDefault + { + public override void OnEntering(IScreen last) + { + this.FadeInFromZero(4000, Easing.OutQuint); + } + } + + private class AlwaysInputContainer : Container + { + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + public AlwaysInputContainer() + { + RelativeSizeAxes = Axes.Both; + } + } } } diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 36fdbe6e94..6bbab4766d 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.Containers public Drawable ExpandableHeader { - get { return expandableHeader; } + get => expandableHeader; set { if (value == expandableHeader) return; @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.Containers public Drawable FixedHeader { - get { return fixedHeader; } + get => fixedHeader; set { if (value == fixedHeader) return; @@ -56,7 +56,7 @@ namespace osu.Game.Graphics.Containers public Drawable Footer { - get { return footer; } + get => footer; set { if (value == footer) return; @@ -75,7 +75,7 @@ namespace osu.Game.Graphics.Containers public Drawable HeaderBackground { - get { return headerBackground; } + get => headerBackground; set { if (value == headerBackground) return; @@ -110,6 +110,7 @@ namespace osu.Game.Graphics.Containers private float headerHeight, footerHeight; private readonly MarginPadding originalSectionsMargin; + private void updateSectionsMargin() { if (!Children.Any()) return; @@ -142,6 +143,7 @@ namespace osu.Game.Graphics.Containers public void ScrollToTop() => scrollContainer.ScrollTo(0); private float lastKnownScroll; + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 6b7b59bbd9..e5a6bcc28e 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs new file mode 100644 index 0000000000..b078f40420 --- /dev/null +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -0,0 +1,134 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Configuration; +using osu.Game.Graphics.Backgrounds; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Graphics.Containers +{ + /// + /// A container that applies user-configured visual settings to its contents. + /// This container specifies behavior that applies to both Storyboards and Backgrounds. + /// + public class UserDimContainer : Container + { + private const float background_fade_duration = 800; + + /// + /// Whether or not user-configured dim levels should be applied to the container. + /// + public readonly Bindable EnableUserDim = new Bindable(); + + /// + /// Whether or not the storyboard loaded should completely hide the background behind it. + /// + public readonly Bindable StoryboardReplacesBackground = new Bindable(); + + /// + /// The amount of blur to be applied to the background in addition to user-specified blur. + /// + /// + /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in + /// + public readonly Bindable BlurAmount = new Bindable(); + + private Bindable userDimLevel { get; set; } + + private Bindable userBlurLevel { get; set; } + + private Bindable showStoryboard { get; set; } + + protected Container DimContainer { get; } + + protected override Container Content => DimContainer; + + private readonly bool isStoryboard; + + /// + /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs. + /// + private Vector2 blurTarget => EnableUserDim.Value + ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25) + : new Vector2(BlurAmount.Value); + + /// + /// Creates a new . + /// + /// Whether or not this instance contains a storyboard. + /// + /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via + /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred. + /// + /// + public UserDimContainer(bool isStoryboard = false) + { + this.isStoryboard = isStoryboard; + AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both }); + } + + private Background background; + + public Background Background + { + get => background; + set + { + base.Add(background = value); + background.BlurTo(blurTarget, 0, Easing.OutQuint); + } + } + + public override void Add(Drawable drawable) + { + if (drawable is Background) + throw new InvalidOperationException($"Use {nameof(Background)} to set a background."); + + base.Add(drawable); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + userDimLevel = config.GetBindable(OsuSetting.DimLevel); + userBlurLevel = config.GetBindable(OsuSetting.BlurLevel); + showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); + + EnableUserDim.ValueChanged += _ => updateVisuals(); + userDimLevel.ValueChanged += _ => updateVisuals(); + userBlurLevel.ValueChanged += _ => updateVisuals(); + showStoryboard.ValueChanged += _ => updateVisuals(); + StoryboardReplacesBackground.ValueChanged += _ => updateVisuals(); + BlurAmount.ValueChanged += _ => updateVisuals(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateVisuals(); + } + + private void updateVisuals() + { + if (isStoryboard) + { + DimContainer.FadeTo(!showStoryboard.Value || userDimLevel.Value == 1 ? 0 : 1, background_fade_duration, Easing.OutQuint); + } + else + { + // The background needs to be hidden in the case of it being replaced by the storyboard + DimContainer.FadeTo(showStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, background_fade_duration, Easing.OutQuint); + + Background?.BlurTo(blurTarget, background_fade_duration, Easing.OutQuint); + } + + DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)userDimLevel.Value) : Color4.White, background_fade_duration, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Graphics/Containers/WaveContainer.cs b/osu.Game/Graphics/Containers/WaveContainer.cs index 96a2304ed1..48131d7e86 100644 --- a/osu.Game/Graphics/Containers/WaveContainer.cs +++ b/osu.Game/Graphics/Containers/WaveContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Graphics/Cursor/IProvideCursor.cs b/osu.Game/Graphics/Cursor/IProvideCursor.cs index c7b23bbc00..3a920ba976 100644 --- a/osu.Game/Graphics/Cursor/IProvideCursor.cs +++ b/osu.Game/Graphics/Cursor/IProvideCursor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 87d97806cd..059beeca4d 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -1,9 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using System; using JetBrains.Annotations; +using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osuTK.Input; @@ -80,11 +80,12 @@ namespace osu.Game.Graphics.Cursor activeCursor.AdditiveLayer.FadeInFromZero(800, Easing.OutQuint); } - if (e.Button == MouseButton.Left && cursorRotate) + if (e.Button == MouseButton.Left && cursorRotate.Value) { dragRotationState = DragRotationState.DragStarted; positionMouseDown = e.MousePosition; } + return base.OnMouseDown(e); } @@ -102,6 +103,7 @@ namespace osu.Game.Graphics.Cursor activeCursor.RotateTo(0, 600 * (1 + Math.Abs(activeCursor.Rotation / 720)), Easing.OutElasticHalf); dragRotationState = DragRotationState.NotDragging; } + return base.OnMouseUp(e); } @@ -156,7 +158,7 @@ namespace osu.Game.Graphics.Cursor }; cursorScale = config.GetBindable(OsuSetting.MenuCursorSize); - cursorScale.ValueChanged += newScale => cursorContainer.Scale = new Vector2((float)newScale * base_scale); + cursorScale.ValueChanged += scale => cursorContainer.Scale = new Vector2((float)scale.NewValue * base_scale); cursorScale.TriggerChange(); } } diff --git a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs index 5823fad93a..92e5ba6195 100644 --- a/osu.Game/Graphics/Cursor/MenuCursorContainer.cs +++ b/osu.Game/Graphics/Cursor/MenuCursorContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Graphics; @@ -43,6 +43,7 @@ namespace osu.Game.Graphics.Cursor } private IProvideCursor currentTarget; + protected override void Update() { base.Update(); @@ -50,6 +51,7 @@ namespace osu.Game.Graphics.Cursor if (!CanShowCursor) { currentTarget?.Cursor?.Hide(); + currentTarget = null; return; } diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index 9408d63573..fbb3fa0e6c 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index e7a9aab622..4e0ce4a3e1 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -17,7 +17,8 @@ namespace osu.Game.Graphics.Cursor { protected override ITooltip CreateTooltip() => new OsuTooltip(); - public OsuTooltipContainer(CursorContainer cursor) : base(cursor) + public OsuTooltipContainer(CursorContainer cursor) + : base(cursor) { } @@ -46,8 +47,6 @@ namespace osu.Game.Graphics.Cursor } } - private const float text_size = 16; - public OsuTooltip() { AutoSizeEasing = Easing.OutQuint; @@ -69,9 +68,8 @@ namespace osu.Game.Graphics.Cursor }, text = new OsuSpriteText { - TextSize = text_size, Padding = new MarginPadding(5), - Font = @"Exo2.0-Regular", + Font = OsuFont.GetFont(weight: FontWeight.Regular) } }; } diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 87711c72c7..3ae1033f5d 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Humanizer; @@ -21,6 +21,7 @@ namespace osu.Game.Graphics { if (date == value) return; + date = value.ToLocalTime(); if (LoadState >= LoadState.Ready) @@ -30,8 +31,7 @@ namespace osu.Game.Graphics public DrawableDate(DateTimeOffset date) { - Font = "Exo2.0-RegularItalic"; - + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true); Date = date; } diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index 0718e84a34..1a66819379 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index fc627fa501..712dc4c444 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK.Graphics; diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs new file mode 100644 index 0000000000..dc660fd159 --- /dev/null +++ b/osu.Game/Graphics/OsuFont.cs @@ -0,0 +1,117 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Sprites; + +namespace osu.Game.Graphics +{ + public struct OsuFont + { + /// + /// The default font size. + /// + public const float DEFAULT_FONT_SIZE = 16; + + /// + /// The default font. + /// + public static FontUsage Default => GetFont(); + + public static FontUsage Numeric => GetFont(Typeface.Venera, weight: FontWeight.Regular); + + /// + /// Retrieves a . + /// + /// The font typeface. + /// The size of the text in local space. For a value of 16, a single line will have a height of 16px. + /// The font weight. + /// Whether the font is italic. + /// Whether all characters should be spaced the same distance apart. + /// The . + public static FontUsage GetFont(Typeface typeface = Typeface.Exo, float size = DEFAULT_FONT_SIZE, FontWeight weight = FontWeight.Medium, bool italics = false, bool fixedWidth = false) + => new FontUsage(GetFamilyString(typeface), size, GetWeightString(typeface, weight), italics, fixedWidth); + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The string representation. + public static string GetFamilyString(Typeface typeface) + { + switch (typeface) + { + case Typeface.Exo: + return "Exo2.0"; + case Typeface.FontAwesome: + return "FontAwesome"; + case Typeface.Venera: + return "Venera"; + } + + return null; + } + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The . + /// The string representation of in the specified . + public static string GetWeightString(Typeface typeface, FontWeight weight) + => GetWeightString(GetFamilyString(typeface), weight); + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The . + /// The string representation of in the specified . + public static string GetWeightString(string family, FontWeight weight) + { + string weightString = weight.ToString(); + + // Only exo has an explicit "regular" weight, other fonts do not + if (family != GetFamilyString(Typeface.Exo) && weight == FontWeight.Regular) + weightString = string.Empty; + + return weightString; + } + } + + public static class OsuFontExtensions + { + /// + /// Creates a new by applying adjustments to this . + /// + /// The font typeface. If null, the value is copied from this . + /// The text size. If null, the value is copied from this . + /// The font weight. If null, the value is copied from this . + /// Whether the font is italic. If null, the value is copied from this . + /// Whether all characters should be spaced apart the same distance. If null, the value is copied from this . + /// The resulting . + public static FontUsage With(this FontUsage usage, Typeface? typeface = null, float? size = null, FontWeight? weight = null, bool? italics = null, bool? fixedWidth = null) + { + string familyString = typeface != null ? OsuFont.GetFamilyString(typeface.Value) : usage.Family; + string weightString = weight != null ? OsuFont.GetWeightString(familyString, weight.Value) : usage.Weight; + + return usage.With(familyString, size, weightString, italics, fixedWidth); + } + } + + public enum Typeface + { + Exo, + FontAwesome, + Venera, + } + + public enum FontWeight + { + Light, + Regular, + Medium, + SemiBold, + Bold, + Black + } +} diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index be253f65c1..a2ac71de93 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -8,7 +8,7 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -127,7 +127,7 @@ namespace osu.Game.Graphics { base.Update(); - if (cursorVisibility == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) + if (cursorVisibility.Value == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) cursorVisibility.Value = true; } diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 2d63d0a52c..f7d7d21435 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -65,6 +65,7 @@ namespace osu.Game.Graphics } private FontAwesome loadedIcon; + private void updateTexture() { var loadableIcon = icon; @@ -104,9 +105,10 @@ namespace osu.Game.Graphics } private bool shadow; + public bool Shadow { - get { return shadow; } + get => shadow; set { shadow = value; @@ -119,11 +121,7 @@ namespace osu.Game.Graphics public FontAwesome Icon { - get - { - return icon; - } - + get => icon; set { if (icon == value) return; diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index 8607d51e12..ed771bb03f 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -9,12 +9,10 @@ namespace osu.Game.Graphics.Sprites { public class OsuSpriteText : SpriteText { - public const float FONT_SIZE = 16; - public OsuSpriteText() { Shadow = true; - TextSize = FONT_SIZE; + Font = OsuFont.Default; } } diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 19135b8550..16a9f367e6 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index 89bd6f6118..2a858ccbcf 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -26,10 +26,7 @@ namespace osu.Game.Graphics.UserInterface /// public float Length { - get - { - return length; - } + get => length; set { length = MathHelper.Clamp(value, 0, 1); @@ -39,35 +36,21 @@ namespace osu.Game.Graphics.UserInterface public Color4 BackgroundColour { - get - { - return background.Colour; - } - set - { - background.Colour = value; - } + get => background.Colour; + set => background.Colour = value; } public Color4 AccentColour { - get - { - return bar.Colour; - } - set - { - bar.Colour = value; - } + get => bar.Colour; + set => bar.Colour = value; } private BarDirection direction = BarDirection.LeftToRight; + public BarDirection Direction { - get - { - return direction; - } + get => direction; set { direction = value; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index f461a0f296..58058c9d4c 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -17,12 +17,10 @@ namespace osu.Game.Graphics.UserInterface public float? MaxValue { get; set; } private BarDirection direction = BarDirection.BottomToTop; + public new BarDirection Direction { - get - { - return direction; - } + get => direction; set { direction = value; @@ -69,6 +67,7 @@ namespace osu.Game.Graphics.UserInterface }); } } + //I'm using ToList() here because Where() returns an Enumerable which can change it's elements afterwards RemoveRange(Children.Where((bar, index) => index >= value.Count()).ToList()); } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index d4ef335c3e..40bc98a654 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -27,12 +27,12 @@ namespace osu.Game.Graphics.UserInterface { Height = 32; TabContainer.Spacing = new Vector2(padding, 0f); - Current.ValueChanged += tab => + Current.ValueChanged += index => { foreach (var t in TabContainer.Children.OfType()) { var tIndex = TabContainer.IndexOf(t); - var tabIndex = TabContainer.IndexOf(TabMap[tab]); + var tabIndex = TabContainer.IndexOf(TabMap[index.NewValue]); t.State = tIndex < tabIndex ? Visibility.Hidden : Visibility.Visible; t.Chevron.FadeTo(tIndex <= tabIndex ? 0f : 1f, 500, Easing.OutQuint); @@ -57,10 +57,11 @@ namespace osu.Game.Graphics.UserInterface public Visibility State { - get { return state; } + get => state; set { if (value == state) return; + state = value; const float transition_duration = 500; @@ -80,9 +81,10 @@ namespace osu.Game.Graphics.UserInterface } } - public BreadcrumbTabItem(T value) : base(value) + public BreadcrumbTabItem(T value) + : base(value) { - Text.TextSize = 18; + Text.Font = Text.Font.With(size: 18); Text.Margin = new MarginPadding { Vertical = 8 }; Padding = new MarginPadding { Right = padding + item_chevron_size }; Add(Chevron = new SpriteIcon diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 24bac05384..dbbe5b4258 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -12,7 +13,6 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; -using osu.Framework.Configuration; using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface @@ -141,8 +141,7 @@ namespace osu.Game.Graphics.UserInterface Text = Text, Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 28, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(size: 28, weight: FontWeight.Bold), Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.1f), Colour = Color4.White, @@ -155,12 +154,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 buttonColour; + public Color4 ButtonColour { - get - { - return buttonColour; - } + get => buttonColour; set { buttonColour = value; @@ -170,12 +167,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 backgroundColour = OsuColour.Gray(34); + public Color4 BackgroundColour { - get - { - return backgroundColour; - } + get => backgroundColour; set { backgroundColour = value; @@ -184,12 +179,10 @@ namespace osu.Game.Graphics.UserInterface } private string text; + public string Text { - get - { - return text; - } + get => text; set { text = value; @@ -197,18 +190,10 @@ namespace osu.Game.Graphics.UserInterface } } - private float textSize = 28; public float TextSize { - get - { - return textSize; - } - set - { - textSize = value; - spriteText.TextSize = value; - } + get => spriteText.Font.Size; + set => spriteText.Font = spriteText.Font.With(size: value); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceivePositionalInputAt(screenSpacePos); @@ -242,9 +227,9 @@ namespace osu.Game.Graphics.UserInterface Selected.Value = false; } - private void selectionChanged(bool isSelected) + private void selectionChanged(ValueChangedEvent args) { - if (isSelected) + if (args.NewValue) { spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); diff --git a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs index 8f8ba1ede8..2ed37799f6 100644 --- a/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs +++ b/osu.Game/Graphics/UserInterface/ExternalLinkButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(ClickEvent e) { - if(Link != null) + if (Link != null) host.OpenUrlExternally(Link); return true; } diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 0564d364ed..f873db0dcb 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -1,9 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using System; +using osu.Framework.Allocation; using osu.Framework.Input.Events; +using osu.Framework.Platform; using osu.Game.Input.Bindings; using osuTK.Input; @@ -14,16 +16,20 @@ namespace osu.Game.Graphics.UserInterface /// public class FocusedTextBox : OsuTextBox { - protected override Color4 BackgroundUnfocused => new Color4(10, 10, 10, 255); - protected override Color4 BackgroundFocused => new Color4(10, 10, 10, 255); - public Action Exit; private bool focus; + private bool allowImmediateFocus => host?.OnScreenKeyboardOverlapsGameWindow != true; + + public void TakeFocus() + { + if (allowImmediateFocus) GetContainingInputManager().ChangeFocus(this); + } + public bool HoldFocus { - get { return focus; } + get => allowImmediateFocus && focus; set { focus = value; @@ -32,6 +38,17 @@ namespace osu.Game.Graphics.UserInterface } } + private GameHost host; + + [BackgroundDependencyLoader] + private void load(GameHost host) + { + this.host = host; + + BackgroundUnfocused = new Color4(10, 10, 10, 255); + BackgroundFocused = new Color4(10, 10, 10, 255); + } + // We may not be focused yet, but we need to handle keyboard input to be able to request focus public override bool HandleNonPositionalInput => HoldFocus || base.HandleNonPositionalInput; diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 3641e251bc..cbbaa6d303 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; @@ -17,7 +17,8 @@ namespace osu.Game.Graphics.UserInterface { private SampleChannel sampleClick; - public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal) : base(sampleSet) + public HoverClickSounds(HoverSampleSet sampleSet = HoverSampleSet.Normal) + : base(sampleSet) { } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index 710948121e..b246092a7f 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Framework.Allocation; @@ -45,8 +45,10 @@ namespace osu.Game.Graphics.UserInterface { [Description("")] Loud, + [Description("-soft")] Normal, + [Description("-softer")] Soft } diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index c59326a256..025aa30986 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.UserInterface /// public Color4 IconColour { - get { return iconColour ?? Color4.White; } + get => iconColour ?? Color4.White; set { iconColour = value; @@ -34,8 +34,8 @@ namespace osu.Game.Graphics.UserInterface /// public Color4 IconHoverColour { - get { return iconHoverColour ?? IconColour; } - set { iconHoverColour = value; } + get => iconHoverColour ?? IconColour; + set => iconHoverColour = value; } /// @@ -43,8 +43,8 @@ namespace osu.Game.Graphics.UserInterface /// public FontAwesome Icon { - get { return icon.Icon; } - set { icon.Icon = value; } + get => icon.Icon; + set => icon.Icon = value; } /// @@ -52,8 +52,8 @@ namespace osu.Game.Graphics.UserInterface /// public Vector2 IconScale { - get { return icon.Scale; } - set { icon.Scale = value; } + get => icon.Scale; + set => icon.Scale = value; } /// diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index c84c500201..74025b71ff 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -44,7 +44,7 @@ namespace osu.Game.Graphics.UserInterface /// public IEnumerable Values { - get { return values; } + get => values; set { values = value.ToArray(); @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface { Masking = true, RelativeSizeAxes = Axes.Both, - Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathWidth = 1 } + Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathRadius = 1 } }); } @@ -102,9 +102,10 @@ namespace osu.Game.Graphics.UserInterface for (int i = 0; i < values.Length; i++) { - float x = (i + count - values.Length) / (float)(count - 1) * DrawWidth - 1; - float y = GetYPosition(values[i]) * DrawHeight - 1; - // the -1 is for inner offset in path (actually -PathWidth) + // Make sure that we are accounting for path width when calculating vertex positions + // We need to apply 2x the path radius to account for it because the full diameter of the line accounts into height + float x = (i + count - values.Length) / (float)(count - 1) * (DrawWidth - 2 * path.PathRadius); + float y = GetYPosition(values[i]) * (DrawHeight - 2 * path.PathRadius); path.AddVertex(new Vector2(x, y)); } } @@ -112,6 +113,7 @@ namespace osu.Game.Graphics.UserInterface protected float GetYPosition(float value) { if (ActualMaxValue == ActualMinValue) return 0; + return (ActualMaxValue - value) / (ActualMaxValue - ActualMinValue); } } diff --git a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs index 292a9bd088..c7c6d0462c 100644 --- a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/UserInterface/MenuItemType.cs b/osu.Game/Graphics/UserInterface/MenuItemType.cs index 42bade1439..0269f2cb57 100644 --- a/osu.Game/Graphics/UserInterface/MenuItemType.cs +++ b/osu.Game/Graphics/UserInterface/MenuItemType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Graphics.UserInterface { diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index b715c80fb6..1f5195eaf1 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -41,9 +41,9 @@ namespace osu.Game.Graphics.UserInterface }, }; - Current.ValueChanged += newValue => + Current.ValueChanged += filled => { - if (newValue) + if (filled.NewValue) fill.FadeIn(200, Easing.OutQuint); else fill.FadeTo(0.01f, 200, Easing.OutQuint); //todo: remove once we figure why containers aren't drawing at all times @@ -72,9 +72,10 @@ namespace osu.Game.Graphics.UserInterface } private bool glowing; + public bool Glowing { - get { return glowing; } + get => glowing; set { glowing = value; @@ -94,10 +95,7 @@ namespace osu.Game.Graphics.UserInterface public bool Expanded { - set - { - this.ResizeTo(new Vector2(value ? EXPANDED_SIZE : COLLAPSED_SIZE, 12), 500, Easing.OutQuint); - } + set => this.ResizeTo(new Vector2(value ? EXPANDED_SIZE : COLLAPSED_SIZE, 12), 500, Easing.OutQuint); } private readonly Bindable current = new Bindable(); @@ -116,9 +114,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; @@ -128,9 +127,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 glowingAccentColour; + public Color4 GlowingAccentColour { - get { return glowingAccentColour; } + get => glowingAccentColour; set { glowingAccentColour = value; @@ -140,9 +140,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 glowColour; + public Color4 GlowColour { - get { return glowColour; } + get => glowColour; set { glowColour = value; diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 89760a9873..d64068f74c 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - Enabled.BindValueChanged(enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); + Enabled.BindValueChanged(enabled => this.FadeColour(enabled.NewValue ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 0ff4542678..7a27f825f6 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -46,13 +47,13 @@ namespace osu.Game.Graphics.UserInterface new HoverClickSounds(HoverSampleSet.Loud), }); - Enabled.ValueChanged += enabled_ValueChanged; + Enabled.ValueChanged += enabledChanged; Enabled.TriggerChange(); } - private void enabled_ValueChanged(bool enabled) + private void enabledChanged(ValueChangedEvent e) { - this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) @@ -84,7 +85,7 @@ namespace osu.Game.Graphics.UserInterface Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold) }; } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 194e81dae1..de3d93d845 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface public string LabelText { - get { return labelSpriteText?.Text; } + get => labelSpriteText?.Text; set { if (labelSpriteText != null) @@ -43,7 +43,7 @@ namespace osu.Game.Graphics.UserInterface public MarginPadding LabelPadding { - get { return labelSpriteText?.Padding ?? new MarginPadding(); } + get => labelSpriteText?.Padding ?? new MarginPadding(); set { if (labelSpriteText != null) @@ -86,9 +86,9 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - Current.ValueChanged += newValue => + Current.ValueChanged += enabled => { - if (newValue) + if (enabled.NewValue) sampleChecked?.Play(); else sampleUnchecked?.Play(); diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index 2dd6d4fe78..c72d11b57e 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 3f15616d6c..db38067a50 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osuTK.Graphics; @@ -17,9 +17,10 @@ namespace osu.Game.Graphics.UserInterface public class OsuDropdown : Dropdown, IHasAccentColour { private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; @@ -37,11 +38,9 @@ namespace osu.Game.Graphics.UserInterface private void updateAccentColour() { - var header = Header as IHasAccentColour; - if (header != null) header.AccentColour = accentColour; + if (Header is IHasAccentColour header) header.AccentColour = accentColour; - var menu = Menu as IHasAccentColour; - if (menu != null) menu.AccentColour = accentColour; + if (Menu is IHasAccentColour menu) menu.AccentColour = accentColour; } protected override DropdownHeader CreateHeader() => new OsuDropdownHeader(); @@ -49,6 +48,7 @@ namespace osu.Game.Graphics.UserInterface protected override DropdownMenu CreateMenu() => new OsuDropdownMenu(); #region OsuDropdownMenu + protected class OsuDropdownMenu : DropdownMenu, IHasAccentColour { public override bool HandleNonPositionalInput => State == MenuState.Open; @@ -83,9 +83,10 @@ namespace osu.Game.Graphics.UserInterface } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; @@ -97,15 +98,17 @@ namespace osu.Game.Graphics.UserInterface protected override DrawableMenuItem CreateDrawableMenuItem(MenuItem item) => new DrawableOsuDropdownMenuItem(item) { AccentColour = accentColour }; #region DrawableOsuDropdownMenuItem + public class DrawableOsuDropdownMenuItem : DrawableDropdownMenuItem, IHasAccentColour { // IsHovered is used public override bool HandlePositionalInput => true; private Color4? accentColour; + public Color4 AccentColour { - get { return accentColour ?? nonAccentSelectedColour; } + get => accentColour ?? nonAccentSelectedColour; set { accentColour = value; @@ -149,8 +152,7 @@ namespace osu.Game.Graphics.UserInterface { base.UpdateForegroundColour(); - var content = Foreground.Children.FirstOrDefault() as Content; - if (content != null) content.Chevron.Alpha = IsHovered ? 1 : 0; + if (Foreground.Children.FirstOrDefault() is Content content) content.Chevron.Alpha = IsHovered ? 1 : 0; } protected override Drawable CreateContent() => new Content(); @@ -159,8 +161,8 @@ namespace osu.Game.Graphics.UserInterface { public string Text { - get { return Label.Text; } - set { Label.Text = value; } + get => Label.Text; + set => Label.Text = value; } public readonly OsuSpriteText Label; @@ -194,25 +196,29 @@ namespace osu.Game.Graphics.UserInterface } } } + #endregion } + #endregion public class OsuDropdownHeader : DropdownHeader, IHasAccentColour { protected readonly SpriteText Text; + protected override string Label { - get { return Text.Text; } - set { Text.Text = value; } + get => Text.Text; + set => Text.Text = value; } protected readonly SpriteIcon Icon; private Color4 accentColour; + public virtual Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index 5c6a2a0569..e132027787 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 570ed368d8..9b5755ea8b 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; @@ -125,7 +125,7 @@ namespace osu.Game.Graphics.UserInterface { public string Text { - get { return NormalText.Text; } + get => NormalText.Text; set { NormalText.Text = value; @@ -149,7 +149,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = text_size, + Font = OsuFont.GetFont(size: text_size), Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, }, BoldText = new OsuSpriteText @@ -158,8 +158,7 @@ namespace osu.Game.Graphics.UserInterface Alpha = 0, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, } }; diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index 02452523a8..b7aa666302 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index c8a1bf9178..aeb974681d 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -9,12 +9,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Platform; namespace osu.Game.Graphics.UserInterface { - public class OsuPasswordTextBox : OsuTextBox + public class OsuPasswordTextBox : OsuTextBox, ISuppressKeyEventLogging { protected override Drawable GetDrawableCharacter(char c) => new PasswordMaskChar(CalculatedTextSize); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 2bd84ab2b4..c558fd7c7b 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Globalization; @@ -35,9 +35,10 @@ namespace osu.Game.Graphics.UserInterface public virtual string TooltipText { get; private set; } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; @@ -79,10 +80,7 @@ namespace osu.Game.Graphics.UserInterface new HoverClickSounds() }; - Current.DisabledChanged += disabled => - { - Alpha = disabled ? 0.3f : 1; - }; + Current.DisabledChanged += disabled => { Alpha = disabled ? 0.3f : 1; }; } [BackgroundDependencyLoader] @@ -92,6 +90,12 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Pink; } + protected override void LoadComplete() + { + base.LoadComplete(); + CurrentNumber.BindValueChanged(current => updateTooltipText(current.NewValue), true); + } + protected override bool OnHover(HoverEvent e) { Nub.Glowing = true; diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 488e16b6fb..e2a4955011 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -58,14 +58,14 @@ namespace osu.Game.Graphics.UserInterface } private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; - var dropdown = Dropdown as IHasAccentColour; - if (dropdown != null) + if (Dropdown is IHasAccentColour dropdown) dropdown.AccentColour = value; foreach (var i in TabContainer.Children.OfType()) i.AccentColour = value; @@ -101,13 +101,14 @@ namespace osu.Game.Graphics.UserInterface protected readonly Box Bar; private Color4 accentColour; + public Color4 AccentColour { - get { return accentColour; } + get => accentColour; set { accentColour = value; - if (!Active) + if (!Active.Value) Text.Colour = value; } } @@ -128,14 +129,14 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - if (!Active) + if (!Active.Value) fadeActive(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - if (!Active) + if (!Active.Value) fadeInactive(); } @@ -146,7 +147,8 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Blue; } - public OsuTabItem(T value) : base(value) + public OsuTabItem(T value) + : base(value) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; @@ -159,8 +161,7 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetDescription() ?? value.ToString(), - TextSize = 14, - Font = @"Exo2.0-Bold", // Font should only turn bold when active? + Font = OsuFont.GetFont(size: 14) }, Bar = new Box { @@ -173,6 +174,8 @@ namespace osu.Game.Graphics.UserInterface }, new HoverClickSounds() }; + + Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } protected override void OnActivated() => fadeActive(); @@ -223,11 +226,7 @@ namespace osu.Game.Graphics.UserInterface { public override Color4 AccentColour { - get - { - return base.AccentColour; - } - + get => base.AccentColour; set { base.AccentColour = value; diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index cb951898da..918473ac53 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -24,14 +24,15 @@ namespace osu.Game.Graphics.UserInterface private readonly SpriteIcon icon; private Color4? accentColour; + public Color4 AccentColour { - get { return accentColour.GetValueOrDefault(); } + get => accentColour.GetValueOrDefault(); set { accentColour = value; - if (Current) + if (Current.Value) { text.Colour = AccentColour; icon.Colour = AccentColour; @@ -41,8 +42,8 @@ namespace osu.Game.Graphics.UserInterface public string Text { - get { return text.Text; } - set { text.Text = value; } + get => text.Text; + set => text.Text = value; } private const float transition_length = 500; @@ -67,7 +68,7 @@ namespace osu.Game.Graphics.UserInterface protected override void OnHoverLost(HoverLostEvent e) { - if (!Current) + if (!Current.Value) fadeOut(); base.OnHoverLost(e); @@ -94,11 +95,7 @@ namespace osu.Game.Graphics.UserInterface Direction = FillDirection.Horizontal, Children = new Drawable[] { - text = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, + text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, icon = new SpriteIcon { Size = new Vector2(14), @@ -118,9 +115,9 @@ namespace osu.Game.Graphics.UserInterface } }; - Current.ValueChanged += v => + Current.ValueChanged += selected => { - if (v) + if (selected.NewValue) { fadeIn(); icon.Icon = FontAwesome.fa_check_circle_o; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 523b60fdd2..ebe38db60a 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,15 +16,11 @@ namespace osu.Game.Graphics.UserInterface { public class OsuTextBox : TextBox, IKeyBindingHandler { - protected override Color4 BackgroundUnfocused => Color4.Black.Opacity(0.5f); - protected override Color4 BackgroundFocused => OsuColour.Gray(0.3f).Opacity(0.8f); - protected override Color4 BackgroundCommit => BorderColour; - protected override float LeftRightPadding => 10; protected override SpriteText CreatePlaceholder() => new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(italics: true), Colour = new Color4(180, 180, 180, 255), Margin = new MarginPadding { Left = 2 }, }; @@ -41,7 +37,9 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colour) { - BorderColour = colour.Yellow; + BackgroundUnfocused = Color4.Black.Opacity(0.5f); + BackgroundFocused = OsuColour.Gray(0.3f).Opacity(0.8f); + BackgroundCommit = BorderColour = colour.Yellow; } protected override void OnFocus(FocusEvent e) @@ -57,7 +55,7 @@ namespace osu.Game.Graphics.UserInterface base.OnFocusLost(e); } - protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), TextSize = CalculatedTextSize }; + protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; public virtual bool OnPressed(GlobalAction action) { diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index 50e4743028..156a556b5e 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -32,7 +32,8 @@ namespace osu.Game.Graphics.UserInterface protected readonly SpriteText Text; - public PageTabItem(T value) : base(value) + public PageTabItem(T value) + : base(value) { AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; @@ -45,8 +46,7 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = (value as Enum)?.GetDescription() ?? value.ToString(), - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14) }, box = new Box { @@ -59,6 +59,8 @@ namespace osu.Game.Graphics.UserInterface }, new HoverClickSounds() }; + + Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } [BackgroundDependencyLoader] @@ -69,14 +71,14 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - if (!Active) + if (!Active.Value) slideActive(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - if (!Active) + if (!Active.Value) slideInactive(); } diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index b1514cb8c8..8254bdda7c 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface public PercentageCounter() { - DisplayedCountSpriteText.FixedWidth = true; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(fixedWidth: true); Current.Value = DisplayedCount = 1.0f; } @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs index 0161c17ba9..8b50f4a97a 100644 --- a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index 6dca58f70d..d271cd121c 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface public Color4 FillColour { - set { fill.FadeColour(value, 150, Easing.OutQuint); } + set => fill.FadeColour(value, 150, Easing.OutQuint); } public Color4 BackgroundColour @@ -32,12 +32,12 @@ namespace osu.Game.Graphics.UserInterface public double EndTime { - set { CurrentNumber.MaxValue = value; } + set => CurrentNumber.MaxValue = value; } public double CurrentTime { - set { CurrentNumber.Value = value; } + set => CurrentNumber.Value = value; } public ProgressBar() diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 5a9dd4e05e..cd244ed7e6 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using System; using System.Collections.Generic; +using osu.Framework.Bindables; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -45,15 +45,13 @@ namespace osu.Game.Graphics.UserInterface /// public virtual T DisplayedCount { - get - { - return displayedCount; - } + get => displayedCount; set { if (EqualityComparer.Default.Equals(displayedCount, value)) return; + displayedCount = value; DisplayedCountSpriteText.Text = FormatCount(value); } @@ -61,22 +59,16 @@ namespace osu.Game.Graphics.UserInterface public abstract void Increment(T amount); - private float textSize; - public float TextSize { - get { return textSize; } - set - { - textSize = value; - DisplayedCountSpriteText.TextSize = value; - } + get => DisplayedCountSpriteText.Font.Size; + set => DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(size: value); } public Color4 AccentColour { - get { return DisplayedCountSpriteText.Colour; } - set { DisplayedCountSpriteText.Colour = value; } + get => DisplayedCountSpriteText.Colour; + set => DisplayedCountSpriteText.Colour = value; } /// @@ -86,20 +78,17 @@ namespace osu.Game.Graphics.UserInterface { Children = new Drawable[] { - DisplayedCountSpriteText = new OsuSpriteText - { - Font = @"Venera" - }, + DisplayedCountSpriteText = new OsuSpriteText { Font = OsuFont.Numeric } }; TextSize = 40; AutoSizeAxes = Axes.Both; - DisplayedCount = Current; + DisplayedCount = Current.Value; - Current.ValueChanged += newValue => + Current.ValueChanged += val => { - if (IsLoaded) TransformCount(displayedCount, newValue); + if (IsLoaded) TransformCount(displayedCount, val.NewValue); }; } @@ -107,7 +96,7 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - DisplayedCountSpriteText.Text = FormatCount(Current); + DisplayedCountSpriteText.Text = FormatCount(Current.Value); } /// @@ -126,7 +115,7 @@ namespace osu.Game.Graphics.UserInterface public virtual void StopRolling() { FinishTransforms(false, nameof(DisplayedCount)); - DisplayedCount = Current; + DisplayedCount = Current.Value; } /// diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 8bf30c32c6..63062cdc9d 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface /// How many leading zeroes the counter will have. public ScoreCounter(uint leading = 0) { - DisplayedCountSpriteText.FixedWidth = true; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(fixedWidth: true); LeadingZeroes = leading; } @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index adcf401546..f564a4b5a8 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; @@ -10,45 +10,30 @@ namespace osu.Game.Graphics.UserInterface /// /// A which follows the active screen (and allows navigation) in a stack. /// - public class ScreenBreadcrumbControl : BreadcrumbControl + public class ScreenBreadcrumbControl : BreadcrumbControl { - private Screen last; - - public ScreenBreadcrumbControl(Screen initialScreen) + public ScreenBreadcrumbControl(ScreenStack stack) { - Current.ValueChanged += newScreen => - { - if (last != newScreen && !newScreen.IsCurrentScreen) - newScreen.MakeCurrent(); - }; + stack.ScreenPushed += onPushed; + stack.ScreenExited += onExited; - onPushed(initialScreen); + onPushed(null, stack.CurrentScreen); + + Current.ValueChanged += current => current.NewValue.MakeCurrent(); } - private void screenChanged(Screen newScreen) + private void onPushed(IScreen lastScreen, IScreen newScreen) { - if (newScreen == null) return; - - if (last != null) - { - last.Exited -= screenChanged; - last.ModePushed -= onPushed; - } - - last = newScreen; - - newScreen.Exited += screenChanged; - newScreen.ModePushed += onPushed; - + AddItem(newScreen); Current.Value = newScreen; } - private void onPushed(Screen screen) + private void onExited(IScreen lastScreen, IScreen newScreen) { - Items.ToList().SkipWhile(i => i != Current.Value).Skip(1).ForEach(RemoveItem); - AddItem(screen); + if (newScreen != null) + Current.Value = newScreen; - screenChanged(screen); + Items.ToList().SkipWhile(s => s != Current.Value).Skip(1).ForEach(RemoveItem); } } } diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index 40db6677f5..54bb968d21 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game/Graphics/UserInterface/SelectionState.cs b/osu.Game/Graphics/UserInterface/SelectionState.cs index 079ae343eb..c85b2ad3ab 100644 --- a/osu.Game/Graphics/UserInterface/SelectionState.cs +++ b/osu.Game/Graphics/UserInterface/SelectionState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Graphics.UserInterface { diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index ddc48c9be7..4717401c75 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(int amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 009a2a2e1b..7dc05d174f 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -41,10 +41,7 @@ namespace osu.Game.Graphics.UserInterface /// public float CountStars { - get - { - return countStars; - } + get => countStars; set { @@ -137,6 +134,7 @@ namespace osu.Game.Graphics.UserInterface private class Star : Container { public readonly SpriteIcon Icon; + public Star() { Size = new Vector2(star_size); diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index 683b442d93..685d230a4b 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; @@ -27,14 +27,11 @@ namespace osu.Game.Graphics.UserInterface }); } - public IEnumerable FilterTerms => new[] { Text }; + public virtual IEnumerable FilterTerms => new[] { Text }; public bool MatchingFilter { - set - { - this.FadeTo(value ? 1 : 0); - } + set => this.FadeTo(value ? 1 : 0); } } } diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 16f727b783..1d8298904b 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -48,11 +48,7 @@ namespace osu.Game.Graphics.UserInterface public override Anchor Origin { - get - { - return base.Origin; - } - + get => base.Origin; set { base.Origin = value; @@ -155,18 +151,12 @@ namespace osu.Game.Graphics.UserInterface public FontAwesome Icon { - set - { - bouncingIcon.Icon = value; - } + set => bouncingIcon.Icon = value; } public string Text { - set - { - text.Text = value; - } + set => text.Text = value; } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => IconLayer.ReceivePositionalInputAt(screenSpacePos) || TextLayer.ReceivePositionalInputAt(screenSpacePos); @@ -217,7 +207,10 @@ namespace osu.Game.Graphics.UserInterface private readonly SpriteIcon icon; - public FontAwesome Icon { set { icon.Icon = value; } } + public FontAwesome Icon + { + set => icon.Icon = value; + } public BouncingIcon() { diff --git a/osu.Game/IO/Archives/ArchiveReader.cs b/osu.Game/IO/Archives/ArchiveReader.cs index 24a5094586..a561523799 100644 --- a/osu.Game/IO/Archives/ArchiveReader.cs +++ b/osu.Game/IO/Archives/ArchiveReader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs index cad056b66a..eff02ae7a5 100644 --- a/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyDirectoryArchiveReader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs index 28b5e628e4..bd5f9cbd07 100644 --- a/osu.Game/IO/Archives/LegacyFileArchiveReader.cs +++ b/osu.Game/IO/Archives/LegacyFileArchiveReader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/Archives/ZipArchiveReader.cs b/osu.Game/IO/Archives/ZipArchiveReader.cs index 2ea35835fa..d934ac54c4 100644 --- a/osu.Game/IO/Archives/ZipArchiveReader.cs +++ b/osu.Game/IO/Archives/ZipArchiveReader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.IO; diff --git a/osu.Game/IO/FileInfo.cs b/osu.Game/IO/FileInfo.cs index edd389bc65..e04bfb46cc 100644 --- a/osu.Game/IO/FileInfo.cs +++ b/osu.Game/IO/FileInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using osu.Game.Database; diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 050fccb98a..458f8964f9 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -21,7 +21,8 @@ namespace osu.Game.IO public new Storage Storage => base.Storage; - public FileStore(IDatabaseContextFactory contextFactory, Storage storage) : base(contextFactory, storage.GetStorageForDirectory(@"files")) + public FileStore(IDatabaseContextFactory contextFactory, Storage storage) + : base(contextFactory, storage.GetStorageForDirectory(@"files")) { Store = new StorageBackedResourceStore(Storage); } diff --git a/osu.Game/IO/Legacy/ILegacySerializable.cs b/osu.Game/IO/Legacy/ILegacySerializable.cs index 1bf33d8bd7..0124ea756a 100644 --- a/osu.Game/IO/Legacy/ILegacySerializable.cs +++ b/osu.Game/IO/Legacy/ILegacySerializable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.IO.Legacy { diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 8fd18b9640..95ee5aea6b 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -38,7 +38,8 @@ namespace osu.Game.IO.Legacy /// Reads a string from the buffer. Overrides the base implementation so it can cope with nulls. public override string ReadString() { - if (0 == ReadByte()) return null; + if (ReadByte() == 0) return null; + return base.ReadString(); } @@ -48,6 +49,7 @@ namespace osu.Game.IO.Legacy int len = ReadInt32(); if (len > 0) return ReadBytes(len); if (len < 0) return null; + return Array.Empty(); } @@ -57,6 +59,7 @@ namespace osu.Game.IO.Legacy int len = ReadInt32(); if (len > 0) return ReadChars(len); if (len < 0) return null; + return Array.Empty(); } @@ -65,6 +68,7 @@ namespace osu.Game.IO.Legacy { long ticks = ReadInt64(); if (ticks < 0) throw new IOException("Bad ticks count read!"); + return new DateTime(ticks, DateTimeKind.Utc); } @@ -73,6 +77,7 @@ namespace osu.Game.IO.Legacy { int count = ReadInt32(); if (count < 0) return null; + IList d = new List(count); SerializationReader sr = new SerializationReader(BaseStream); @@ -88,6 +93,7 @@ namespace osu.Game.IO.Legacy { if (skipErrors) continue; + throw; } @@ -102,6 +108,7 @@ namespace osu.Game.IO.Legacy { int count = ReadInt32(); if (count < 0) return null; + IList d = new List(count); for (int i = 0; i < count; i++) d.Add((T)ReadObject()); return d; @@ -112,6 +119,7 @@ namespace osu.Game.IO.Legacy { int count = ReadInt32(); if (count < 0) return null; + IDictionary d = new Dictionary(); for (int i = 0; i < count; i++) d[(T)ReadObject()] = (U)ReadObject(); return d; @@ -174,7 +182,7 @@ namespace osu.Game.IO.Legacy versionBinder = new VersionConfigToNamespaceAssemblyObjectBinder(); formatter = new BinaryFormatter { -// AssemblyFormat = FormatterAssemblyStyle.Simple, + // AssemblyFormat = FormatterAssemblyStyle.Simple, Binder = versionBinder }; } @@ -224,6 +232,7 @@ namespace osu.Game.IO.Legacy genType = BindToType(assemblyName, typ); } } + if (genType != null && tmpTypes.Count > 0) { return genType.MakeGenericType(tmpTypes.ToArray()); diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index 85728794af..695767c822 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,6 +8,7 @@ using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.Text; + // ReSharper disable ConditionIsAlwaysTrueOrFalse (we're allowing nulls to be passed to the writer where the underlying class doesn't). // ReSharper disable HeuristicUnreachableCode @@ -219,7 +220,7 @@ namespace osu.Game.IO.Legacy Write((byte)ObjType.otherType); BinaryFormatter b = new BinaryFormatter { -// AssemblyFormat = FormatterAssemblyStyle.Simple, + // AssemblyFormat = FormatterAssemblyStyle.Simple, TypeFormat = FormatterTypeStyle.TypesWhenNeeded }; b.Serialize(BaseStream, obj); diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index 42d47cc1fb..13be4be0c6 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/IO/Serialization/Converters/Vector2Converter.cs b/osu.Game/IO/Serialization/Converters/Vector2Converter.cs index 4b057c0f2f..bf5edeef94 100644 --- a/osu.Game/IO/Serialization/Converters/Vector2Converter.cs +++ b/osu.Game/IO/Serialization/Converters/Vector2Converter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; diff --git a/osu.Game/IO/Serialization/IJsonSerializable.cs b/osu.Game/IO/Serialization/IJsonSerializable.cs index ce6ff7c82d..ac95d47c4b 100644 --- a/osu.Game/IO/Serialization/IJsonSerializable.cs +++ b/osu.Game/IO/Serialization/IJsonSerializable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.IO.Serialization.Converters; diff --git a/osu.Game/IO/Serialization/KeyContractResolver.cs b/osu.Game/IO/Serialization/KeyContractResolver.cs index e2b470ab4a..7b6905643c 100644 --- a/osu.Game/IO/Serialization/KeyContractResolver.cs +++ b/osu.Game/IO/Serialization/KeyContractResolver.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Humanizer; using Newtonsoft.Json.Serialization; diff --git a/osu.Game/IPC/ArchiveImportIPCChannel.cs b/osu.Game/IPC/ArchiveImportIPCChannel.cs index fa8168c1de..fc747cd446 100644 --- a/osu.Game/IPC/ArchiveImportIPCChannel.cs +++ b/osu.Game/IPC/ArchiveImportIPCChannel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Diagnostics; using System.IO; diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index e69dd30822..8c0072c3da 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations.Schema; using osu.Framework.Input.Bindings; @@ -19,15 +19,15 @@ namespace osu.Game.Input.Bindings [Column("Keys")] public string KeysString { - get { return KeyCombination.ToString(); } - private set { KeyCombination = value; } + get => KeyCombination.ToString(); + private set => KeyCombination = value; } [Column("Action")] public int IntAction { - get { return (int)Action; } - set { Action = value; } + get => (int)Action; + set => Action = value; } } } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 85a8ac7aa3..f34b8f14b0 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index c58e845a6a..97f4a9771f 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.ComponentModel; @@ -62,31 +62,41 @@ namespace osu.Game.Input.Bindings { [Description("Toggle chat overlay")] ToggleChat, + [Description("Toggle social overlay")] ToggleSocial, + [Description("Reset input settings")] ResetInputSettings, + [Description("Toggle toolbar")] ToggleToolbar, + [Description("Toggle settings")] ToggleSettings, + [Description("Toggle osu!direct")] ToggleDirect, + [Description("Increase volume")] IncreaseVolume, + [Description("Decrease volume")] DecreaseVolume, + [Description("Toggle mute")] ToggleMute, // In-Game Keybindings [Description("Skip cutscene")] SkipCutscene, + [Description("Quick retry (hold)")] QuickRetry, [Description("Take screenshot")] TakeScreenshot, + [Description("Toggle gameplay mouse buttons")] ToggleGameplayMouseButtons, diff --git a/osu.Game/Input/Handlers/ReplayInputHandler.cs b/osu.Game/Input/Handlers/ReplayInputHandler.cs index c8c5657e41..93ed3ca884 100644 --- a/osu.Game/Input/Handlers/ReplayInputHandler.cs +++ b/osu.Game/Input/Handlers/ReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index d96fa8bd34..91e2456ef7 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -27,6 +27,11 @@ namespace osu.Game.Input private readonly BindableBool isIdle = new BindableBool(); + /// + /// Whether the game can currently enter an idle state. + /// + protected virtual bool AllowIdle => true; + /// /// Intstantiate a new . /// @@ -40,7 +45,7 @@ namespace osu.Game.Input protected override void Update() { base.Update(); - isIdle.Value = TimeSpentIdle > timeToIdle; + isIdle.Value = TimeSpentIdle > timeToIdle && AllowIdle; } public bool OnPressed(PlatformAction action) => updateLastInteractionTime(); diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 29fdabbbc2..caddb1ae0d 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.cs b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.cs index c38cd19b42..026442f328 100644 --- a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.cs +++ b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.cs @@ -13,7 +13,6 @@ namespace osu.Game.Migrations protected override void Down(MigrationBuilder migrationBuilder) { - } } } diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs new file mode 100644 index 0000000000..8e1e3a59f3 --- /dev/null +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs @@ -0,0 +1,487 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190225062029_AddUserIDColumn")] + partial class AddUserIDColumn + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.cs new file mode 100644 index 0000000000..0720e0eac7 --- /dev/null +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddUserIDColumn : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UserID", + table: "ScoreInfo", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UserID", + table: "ScoreInfo"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 2dafedc3ac..8430e00e4f 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687"); + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -336,7 +336,10 @@ namespace osu.Game.Migrations b.Property("StatisticsJson") .HasColumnName("Statistics"); - b.Property("TotalScore"); + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); b.Property("UserString") .HasColumnName("User"); diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 10b4e73419..c5f6ef41c2 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using System.Net; using System.Net.Http; using System.Threading; using Newtonsoft.Json.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Configuration; @@ -22,7 +22,7 @@ namespace osu.Game.Online.API private readonly OsuConfigManager config; private readonly OAuth authentication; - public string Endpoint = @"https://osu.ppy.sh"; + public string Endpoint => @"https://osu.ppy.sh"; private const string client_id = @"5"; private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; @@ -64,19 +64,21 @@ namespace osu.Game.Online.API thread.Start(); } - private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); + private void onTokenChanged(ValueChangedEvent e) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); private readonly List components = new List(); internal new void Schedule(Action action) => base.Schedule(action); + /// + /// Register a component to receive API events. + /// Fires once immediately to ensure a correct state. + /// + /// public void Register(IOnlineComponent component) { - Scheduler.Add(delegate - { - components.Add(component); - component.APIStateChanged(this, state); - }); + Scheduler.Add(delegate { components.Add(component); }); + component.APIStateChanged(this, state); } public void Unregister(IOnlineComponent component) @@ -101,6 +103,9 @@ namespace osu.Game.Online.API //todo: replace this with a ping request. log.Add(@"In a failing state, waiting a bit before we try again..."); Thread.Sleep(5000); + + if (!IsLoggedIn) goto case APIState.Connecting; + if (queue.Count == 0) { log.Add(@"Queueing a ping request"); @@ -173,6 +178,7 @@ namespace osu.Game.Online.API lock (queue) { if (queue.Count == 0) break; + req = queue.Dequeue(); } @@ -257,23 +263,21 @@ namespace osu.Game.Online.API public APIState State { - get { return state; } + get => state; private set { - APIState oldState = state; - APIState newState = value; + if (state == value) + return; + APIState oldState = state; state = value; - if (oldState != newState) + log.Add($@"We just went {state}!"); + Scheduler.Add(delegate { - log.Add($@"We just went {newState}!"); - Scheduler.Add(delegate - { - components.ForEach(c => c.APIStateChanged(this, newState)); - OnStateChange?.Invoke(oldState, newState); - }); - } + components.ForEach(c => c.APIStateChanged(this, state)); + OnStateChange?.Invoke(oldState, state); + }); } } @@ -352,11 +356,7 @@ namespace osu.Game.Online.API State = APIState.Offline; } - private static User createGuestUser() => new User - { - Username = @"Guest", - Id = 1, - }; + private static User createGuestUser() => new GuestUser(); protected override void Dispose(bool isDisposing) { @@ -367,6 +367,15 @@ namespace osu.Game.Online.API } } + internal class GuestUser : User + { + public GuestUser() + { + Username = @"Guest"; + Id = 1; + } + } + public enum APIState { /// diff --git a/osu.Game/Online/API/APIDownloadRequest.cs b/osu.Game/Online/API/APIDownloadRequest.cs index 86558faf3b..efc832a71e 100644 --- a/osu.Game/Online/API/APIDownloadRequest.cs +++ b/osu.Game/Online/API/APIDownloadRequest.cs @@ -1,20 +1,23 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.IO; using osu.Framework.IO.Network; namespace osu.Game.Online.API { public abstract class APIDownloadRequest : APIRequest { + private string filename; + protected override WebRequest CreateWebRequest() { - var request = new WebRequest(Uri); + var request = new FileWebRequest(filename = Path.GetTempFileName(), Uri); request.DownloadProgress += request_Progress; return request; } - private void request_Progress(long current, long total) => API.Schedule(() => Progress?.Invoke(current, total)); + private void request_Progress(long current, long total) => API.Schedule(() => Progressed?.Invoke(current, total)); protected APIDownloadRequest() { @@ -23,11 +26,11 @@ namespace osu.Game.Online.API private void onSuccess() { - Success?.Invoke(WebRequest.ResponseData); + Success?.Invoke(filename); } - public event APIProgressHandler Progress; + public event APIProgressHandler Progressed; - public new event APISuccessHandler Success; + public new event APISuccessHandler Success; } } diff --git a/osu.Game/Online/API/APIMessagesRequest.cs b/osu.Game/Online/API/APIMessagesRequest.cs index 991096c0af..3ad6b1d7c8 100644 --- a/osu.Game/Online/API/APIMessagesRequest.cs +++ b/osu.Game/Online/API/APIMessagesRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 9a1238b019..96f3b85272 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.IO.Network; @@ -61,9 +61,12 @@ namespace osu.Game.Online.API private Action pendingFailure; - public void Perform(APIAccess api) + public void Perform(IAPIProvider api) { - API = api; + if (!(api is APIAccess apiAccess)) + throw new NotSupportedException($"A {nameof(APIAccess)} is required to perform requests."); + + API = apiAccess; if (checkAndScheduleFailure()) return; @@ -71,7 +74,7 @@ namespace osu.Game.Online.API WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; - WebRequest.AddHeader("Authorization", $"Bearer {api.AccessToken}"); + WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); if (checkAndScheduleFailure()) return; @@ -85,7 +88,7 @@ namespace osu.Game.Online.API if (checkAndScheduleFailure()) return; - api.Schedule(delegate { Success?.Invoke(); }); + API.Schedule(delegate { Success?.Invoke(); }); } public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled")); @@ -121,7 +124,10 @@ namespace osu.Game.Online.API } public delegate void APIFailureHandler(Exception e); + public delegate void APISuccessHandler(); + public delegate void APIProgressHandler(long current, long total); + public delegate void APISuccessHandler(T content); } diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index f99f184d5c..99fde10309 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -1,23 +1,44 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using System.Collections.Generic; +using System.Threading; +using osu.Framework.Bindables; +using osu.Framework.Graphics; using osu.Game.Users; namespace osu.Game.Online.API { - public class DummyAPIAccess : IAPIProvider + public class DummyAPIAccess : Component, IAPIProvider { public Bindable LocalUser { get; } = new Bindable(new User { Username = @"Dummy", - Id = 1, + Id = 1001, }); public bool IsLoggedIn => true; - public void Update() + public string ProvidedUsername => LocalUser.Value.Username; + + public string Endpoint => "http://localhost"; + + private APIState state = APIState.Online; + + private readonly List components = new List(); + + public APIState State { + get => state; + private set + { + if (state == value) + return; + + state = value; + + Scheduler.Add(() => components.ForEach(c => c.APIStateChanged(this, value))); + } } public virtual void Queue(APIRequest request) @@ -26,6 +47,36 @@ namespace osu.Game.Online.API public void Register(IOnlineComponent component) { + Scheduler.Add(delegate { components.Add(component); }); + component.APIStateChanged(this, state); + } + + public void Unregister(IOnlineComponent component) + { + Scheduler.Add(delegate { components.Remove(component); }); + } + + public void Login(string username, string password) + { + LocalUser.Value = new User + { + Username = username, + Id = 1001, + }; + + State = APIState.Online; + } + + public void Logout() + { + LocalUser.Value = new GuestUser(); + State = APIState.Offline; + } + + public RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password) + { + Thread.Sleep(200); + return null; } } } diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index a3fc9a699c..7c1f850943 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Users; namespace osu.Game.Online.API @@ -18,6 +18,19 @@ namespace osu.Game.Online.API /// bool IsLoggedIn { get; } + /// + /// The last username provided by the end-user. + /// May not be authenticated. + /// + string ProvidedUsername { get; } + + /// + /// The URL endpoint for this API. Does not include a trailing slash. + /// + string Endpoint { get; } + + APIState State { get; } + /// /// Queue a new request. /// @@ -29,5 +42,32 @@ namespace osu.Game.Online.API /// /// The component to register. void Register(IOnlineComponent component); + + /// + /// Unregisters a component to receive state changes. + /// + /// The component to unregister. + void Unregister(IOnlineComponent component); + + /// + /// Attempt to login using the provided credentials. This is a non-blocking operation. + /// + /// The user's username. + /// The user's password. + void Login(string username, string password); + + /// + /// Log out the current user. + /// + void Logout(); + + /// + /// Create a new user account. This is a blocking operation. + /// + /// The email to create the account with. + /// The username to create the account with. + /// The password to create the account with. + /// Any errors encoutnered during account creation. + RegistrationRequest.RegistrationRequestErrors CreateAccount(string email, string username, string password); } } diff --git a/osu.Game/Online/API/IOnlineComponent.cs b/osu.Game/Online/API/IOnlineComponent.cs index 5ca6143428..da6b784759 100644 --- a/osu.Game/Online/API/IOnlineComponent.cs +++ b/osu.Game/Online/API/IOnlineComponent.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.API { public interface IOnlineComponent { - void APIStateChanged(APIAccess api, APIState state); + void APIStateChanged(IAPIProvider api, APIState state); } } diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index f60567a706..baf494ebf9 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Diagnostics; using System.Net.Http; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/OAuthToken.cs b/osu.Game/Online/API/OAuthToken.cs index b9458583f1..f103d0917d 100644 --- a/osu.Game/Online/API/OAuthToken.cs +++ b/osu.Game/Online/API/OAuthToken.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Globalization; @@ -19,15 +19,8 @@ namespace osu.Game.Online.API [JsonProperty(@"expires_in")] public long ExpiresIn { - get - { - return AccessTokenExpiry - DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - } - - set - { - AccessTokenExpiry = DateTimeOffset.Now.AddSeconds(value).ToUnixTimeSeconds(); - } + get => AccessTokenExpiry - DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + set => AccessTokenExpiry = DateTimeOffset.Now.AddSeconds(value).ToUnixTimeSeconds(); } public bool IsValid => !string.IsNullOrEmpty(AccessToken) && ExpiresIn > 30; @@ -57,6 +50,7 @@ namespace osu.Game.Online.API catch { } + return null; } } diff --git a/osu.Game/Online/API/RegistrationRequest.cs b/osu.Game/Online/API/RegistrationRequest.cs index f703927101..349cd4de0c 100644 --- a/osu.Game/Online/API/RegistrationRequest.cs +++ b/osu.Game/Online/API/RegistrationRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs index 00dab10c75..37ffc04e04 100644 --- a/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs +++ b/osu.Game/Online/API/Requests/CreateNewPrivateMessageRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs b/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs index 84f1593c31..f749b27114 100644 --- a/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs +++ b/osu.Game/Online/API/Requests/CreateNewPrivateMessageResponse.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/CreateRoomRequest.cs b/osu.Game/Online/API/Requests/CreateRoomRequest.cs index fc401be5f1..c848c55cc6 100644 --- a/osu.Game/Online/API/Requests/CreateRoomRequest.cs +++ b/osu.Game/Online/API/Requests/CreateRoomRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs index 0e99b53ec0..e6246b4f1f 100644 --- a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index c72bf8cbed..26e8acc2fc 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using System; @@ -10,7 +10,9 @@ namespace osu.Game.Online.API.Requests { public readonly BeatmapSetInfo BeatmapSet; - public Action DownloadProgressed; + public float Progress; + + public event Action DownloadProgressed; private readonly bool noVideo; @@ -19,7 +21,7 @@ namespace osu.Game.Online.API.Requests this.noVideo = noVideo; BeatmapSet = set; - Progress += (current, total) => DownloadProgressed?.Invoke((float) current / total); + Progressed += (current, total) => DownloadProgressed?.Invoke(Progress = (float)current / total); } protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; diff --git a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs index e3865be5fb..ed5efa2849 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs index 9d254ce29d..b37a6804fe 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs index d04e069cd6..8e6deeb3c6 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs index 13bdd23170..46890aa889 100644 --- a/osu.Game/Online/API/Requests/GetFriendsRequest.cs +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetMessagesRequest.cs b/osu.Game/Online/API/Requests/GetMessagesRequest.cs index 94f5a114ad..36e81a9348 100644 --- a/osu.Game/Online/API/Requests/GetMessagesRequest.cs +++ b/osu.Game/Online/API/Requests/GetMessagesRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs index 1699694878..993e49dab2 100644 --- a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetRoomsRequest.cs b/osu.Game/Online/API/Requests/GetRoomsRequest.cs index bc835b1ab4..d7c66707e4 100644 --- a/osu.Game/Online/API/Requests/GetRoomsRequest.cs +++ b/osu.Game/Online/API/Requests/GetRoomsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index ae2c7dc269..f6be849b56 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs index 950ad93396..488bb8bbf4 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using JetBrains.Annotations; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs index 474d8e1501..4ac806bedc 100644 --- a/osu.Game/Online/API/Requests/GetUpdatesResponse.cs +++ b/osu.Game/Online/API/Requests/GetUpdatesResponse.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index b847a954f6..45d751f00e 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Humanizer; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index 9a54aafa82..40e52bdaf6 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index e1cad1a532..9f80180e70 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index 607e8e5127..37ed0574f1 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 12d70ea327..c5b436f99c 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index 17dd9263c9..55df88b7e5 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.API.Requests.Responses; diff --git a/osu.Game/Online/API/Requests/JoinChannelRequest.cs b/osu.Game/Online/API/Requests/JoinChannelRequest.cs index a0a4667e98..f6ed5f22c9 100644 --- a/osu.Game/Online/API/Requests/JoinChannelRequest.cs +++ b/osu.Game/Online/API/Requests/JoinChannelRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/JoinRoomRequest.cs b/osu.Game/Online/API/Requests/JoinRoomRequest.cs index b5e162da08..36b275236c 100644 --- a/osu.Game/Online/API/Requests/JoinRoomRequest.cs +++ b/osu.Game/Online/API/Requests/JoinRoomRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs b/osu.Game/Online/API/Requests/LeaveChannelRequest.cs index 89bfa303c6..f2ae3926bd 100644 --- a/osu.Game/Online/API/Requests/LeaveChannelRequest.cs +++ b/osu.Game/Online/API/Requests/LeaveChannelRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/ListChannelsRequest.cs b/osu.Game/Online/API/Requests/ListChannelsRequest.cs index d1ee4fde01..9660695c14 100644 --- a/osu.Game/Online/API/Requests/ListChannelsRequest.cs +++ b/osu.Game/Online/API/Requests/ListChannelsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Online.Chat; diff --git a/osu.Game/Online/API/Requests/PartRoomRequest.cs b/osu.Game/Online/API/Requests/PartRoomRequest.cs index 5e4457f69f..e1550cb2e0 100644 --- a/osu.Game/Online/API/Requests/PartRoomRequest.cs +++ b/osu.Game/Online/API/Requests/PartRoomRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/PostMessageRequest.cs b/osu.Game/Online/API/Requests/PostMessageRequest.cs index 8d9ba5dd5d..84ab873acf 100644 --- a/osu.Game/Online/API/Requests/PostMessageRequest.cs +++ b/osu.Game/Online/API/Requests/PostMessageRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using osu.Framework.IO.Network; diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 7b42672c2e..edbcbed59f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs index e67c60cb91..f049b3aed4 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapMetrics.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 8446285070..1abb7c1a7d 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs index ca0daa04b6..a554101bc7 100644 --- a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs +++ b/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Online/API/Requests/Responses/APIMod.cs b/osu.Game/Online/API/Requests/Responses/APIMod.cs index af0d0c643f..d7dda07b33 100644 --- a/osu.Game/Online/API/Requests/Responses/APIMod.cs +++ b/osu.Game/Online/API/Requests/Responses/APIMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs index c38c443ec3..8695d09570 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRecentActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Humanizer; diff --git a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs index c6ef919e54..33467b59b2 100644 --- a/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIRoomScoreInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Scoring; diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index b26bc751b9..ded4ca71ee 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs b/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs index 6a0ecd37c7..1d2465bedf 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIScores.cs b/osu.Game/Online/API/Requests/Responses/APIScores.cs index ccffa3f9ed..a867d86d9b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScores.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScores.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index 54c8451456..ff422b8292 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs index 8a5aea9e97..8177f99abe 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUserMostPlayedBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index ffea7b83e1..d9d05ff285 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osu.Game.Overlays; @@ -36,11 +36,12 @@ namespace osu.Game.Online.API.Requests [Description("Ranked & Approved")] RankedApproved = 0, - Approved = 1, + Qualified = 3, Loved = 8, Favourites = 2, - Qualified = 3, - Pending = 4, + + [Description("Pending & WIP")] + PendingWIP = 4, Graveyard = 5, [Description("My Maps")] diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs index cf8b40d068..b0f4fef81a 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs index d25e35db58..1a2503f339 100644 --- a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Net.Http; using Newtonsoft.Json; diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 9dc357c403..9ec39c5cb1 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Lists; using osu.Game.Users; @@ -41,7 +41,6 @@ namespace osu.Game.Online.Chat /// private readonly List pendingMessages = new List(); - /// /// An event that fires when new messages arrived. /// diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index d5deda960c..8c6422afe3 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -55,7 +55,7 @@ namespace osu.Game.Online.Chat { CurrentChannel.ValueChanged += currentChannelChanged; - HighPollRate.BindValueChanged(high => TimeBetweenPolls = high ? 1000 : 6000, true); + HighPollRate.BindValueChanged(enabled => TimeBetweenPolls = enabled.NewValue ? 1000 : 6000, true); } /// @@ -84,7 +84,7 @@ namespace osu.Game.Online.Chat ?? new Channel(user); } - private void currentChannelChanged(Channel channel) => JoinChannel(channel); + private void currentChannelChanged(ValueChangedEvent e) => JoinChannel(e.NewValue); /// /// Ensure we run post actions in sequence, once at a time. @@ -131,7 +131,7 @@ namespace osu.Game.Online.Chat target.AddLocalEcho(message); // if this is a PM and the first message, we need to do a special request to create the PM channel - if (target.Type == ChannelType.PM && !target.Joined) + if (target.Type == ChannelType.PM && !target.Joined.Value) { var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message); @@ -331,7 +331,7 @@ namespace osu.Game.Online.Chat switch (channel.Type) { case ChannelType.Public: - var req = new JoinChannelRequest(channel, api.LocalUser); + var req = new JoinChannelRequest(channel, api.LocalUser.Value); req.Success += () => JoinChannel(channel, true); req.Failure += ex => LeaveChannel(channel); api.Queue(req); @@ -363,7 +363,7 @@ namespace osu.Game.Online.Chat if (channel.Joined.Value) { - api.Queue(new LeaveChannelRequest(channel, api.LocalUser)); + api.Queue(new LeaveChannelRequest(channel, api.LocalUser.Value)); channel.Joined.Value = false; } } diff --git a/osu.Game/Online/Chat/ChannelType.cs b/osu.Game/Online/Chat/ChannelType.cs index c8b9463ded..7d2b661164 100644 --- a/osu.Game/Online/Chat/ChannelType.cs +++ b/osu.Game/Online/Chat/ChannelType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.Chat { diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index 2b0a49cb6c..d34ec8091c 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Cursor; using System.Collections.Generic; diff --git a/osu.Game/Online/Chat/ErrorMessage.cs b/osu.Game/Online/Chat/ErrorMessage.cs index 87652c50c4..a8ff0e9a98 100644 --- a/osu.Game/Online/Chat/ErrorMessage.cs +++ b/osu.Game/Online/Chat/ErrorMessage.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.Chat { public class ErrorMessage : InfoMessage { - public ErrorMessage(string message) : base(message) + public ErrorMessage(string message) + : base(message) { Sender.Colour = @"ff0000"; } diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index d8b8adbbad..495f1ac0b0 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Configuration; @@ -27,7 +27,7 @@ namespace osu.Game.Online.Chat public void OpenUrlExternally(string url) { - if (externalLinkWarning) + if (externalLinkWarning.Value) dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url))); else host.OpenUrlExternally(url); diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index 103a999591..8dce188804 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Users; @@ -10,7 +10,8 @@ namespace osu.Game.Online.Chat { private static int infoID = -1; - public InfoMessage(string message) : base(infoID--) + public InfoMessage(string message) + : base(infoID--) { Timestamp = DateTimeOffset.Now; Content = message; diff --git a/osu.Game/Online/Chat/LocalEchoMessage.cs b/osu.Game/Online/Chat/LocalEchoMessage.cs index 7d678029aa..8a39515575 100644 --- a/osu.Game/Online/Chat/LocalEchoMessage.cs +++ b/osu.Game/Online/Chat/LocalEchoMessage.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.Chat { public class LocalEchoMessage : LocalMessage { - public LocalEchoMessage() : base(null) + public LocalEchoMessage() + : base(null) { } } diff --git a/osu.Game/Online/Chat/LocalMessage.cs b/osu.Game/Online/Chat/LocalMessage.cs index 93f1e7f9ea..027edbcca5 100644 --- a/osu.Game/Online/Chat/LocalMessage.cs +++ b/osu.Game/Online/Chat/LocalMessage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.Chat { diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 3f0f352ac7..62f20daddf 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index dd19868954..d35dc07368 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -25,19 +25,19 @@ namespace osu.Game.Online.Chat // This is in the format (, [optional]): // http[s]://.[:port][/path][?query][#fragment] private static readonly Regex advanced_link_regex = new Regex( - // protocol - @"(?[a-z]*?:\/\/" + - // domain + tld - @"(?(?:[a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*[a-z0-9-]*[a-z0-9]" + - // port (optional) - @"(?::\d+)?)" + - // path (optional) - @"(?(?:(?:\/+(?:[a-z0-9$_\.\+!\*\',;:\(\)@&~=-]|%[0-9a-f]{2})*)*" + - // query (optional) - @"(?:\?(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?" + - // fragment (optional) - @"(?:#(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?)", - RegexOptions.IgnoreCase); + // protocol + @"(?[a-z]*?:\/\/" + + // domain + tld + @"(?(?:[a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*[a-z0-9-]*[a-z0-9]" + + // port (optional) + @"(?::\d+)?)" + + // path (optional) + @"(?(?:(?:\/+(?:[a-z0-9$_\.\+!\*\',;:\(\)@&~=-]|%[0-9a-f]{2})*)*" + + // query (optional) + @"(?:\?(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?" + + // fragment (optional) + @"(?:#(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?)", + RegexOptions.IgnoreCase); // 00:00:000 (1,2,3) - test private static readonly Regex time_regex = new Regex(@"\d\d:\d\d:\d\d\d? [^-]*"); @@ -56,14 +56,14 @@ namespace osu.Game.Online.Chat var index = m.Index - captureOffset; var displayText = string.Format(display, - m.Groups[0], - m.Groups.Count > 1 ? m.Groups[1].Value : "", - m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + m.Groups[0], + m.Groups.Count > 1 ? m.Groups[1].Value : "", + m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); var linkText = string.Format(link, - m.Groups[0], - m.Groups.Count > 1 ? m.Groups[1].Value : "", - m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + m.Groups[0], + m.Groups.Count > 1 ? m.Groups[1].Value : "", + m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); if (displayText.Length == 0 || linkText.Length == 0) continue; diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 576a1d619a..438bf231c4 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -90,9 +90,9 @@ namespace osu.Game.Online.Chat return; if (text[0] == '/') - ChannelManager?.PostCommand(text.Substring(1), Channel); + ChannelManager?.PostCommand(text.Substring(1), Channel.Value); else - ChannelManager?.PostMessage(text, target: Channel); + ChannelManager?.PostMessage(text, target: Channel.Value); textbox.Text = string.Empty; } @@ -111,13 +111,13 @@ namespace osu.Game.Online.Chat protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message); - private void channelChanged(Channel channel) + private void channelChanged(ValueChangedEvent e) { drawableChannel?.Expire(); - if (channel == null) return; + if (e.NewValue == null) return; - AddInternal(drawableChannel = new StandAloneDrawableChannel(channel) + AddInternal(drawableChannel = new StandAloneDrawableChannel(e.NewValue) { CreateChatLineAction = CreateMessage, Padding = new MarginPadding { Bottom = postingTextbox ? textbox_height : 0 } @@ -126,7 +126,7 @@ namespace osu.Game.Online.Chat protected class StandAloneDrawableChannel : DrawableChannel { - public Func CreateChatLineAction; + public Func CreateChatLineAction; protected override ChatLine CreateChatLine(Message m) => CreateChatLineAction(m); @@ -144,7 +144,8 @@ namespace osu.Game.Online.Chat protected override float HorizontalPadding => 10; protected override float MessagePadding => 120; - public StandAloneMessage(Message message) : base(message) + public StandAloneMessage(Message message) + : base(message) { } } diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs index 1c68c64180..9155df69b4 100644 --- a/osu.Game/Online/Leaderboards/DrawableRank.cs +++ b/osu.Game/Online/Leaderboards/DrawableRank.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions; diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index a6748fa983..ac1666f8ed 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -39,7 +39,7 @@ namespace osu.Game.Online.Leaderboards public IEnumerable Scores { - get { return scores; } + get => scores; set { scores = value; @@ -98,7 +98,7 @@ namespace osu.Game.Online.Leaderboards public TScope Scope { - get { return scope; } + get => scope; set { if (value.Equals(scope)) @@ -117,7 +117,7 @@ namespace osu.Game.Online.Leaderboards /// protected PlaceholderState PlaceholderState { - get { return placeholderState; } + get => placeholderState; set { if (value != PlaceholderState.Successful) @@ -174,12 +174,12 @@ namespace osu.Game.Online.Leaderboards }; } - private APIAccess api; + private IAPIProvider api; private ScheduledDelegate pendingUpdateScores; [BackgroundDependencyLoader(true)] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; api?.Register(this); @@ -195,7 +195,7 @@ namespace osu.Game.Online.Leaderboards private APIRequest getScoresRequest; - public void APIStateChanged(APIAccess api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) { if (state == APIState.Online) UpdateScores(); @@ -213,12 +213,6 @@ namespace osu.Game.Online.Leaderboards pendingUpdateScores?.Cancel(); pendingUpdateScores = Schedule(() => { - if (api?.IsLoggedIn != true) - { - PlaceholderState = PlaceholderState.NotLoggedIn; - return; - } - PlaceholderState = PlaceholderState.Retrieving; loading.Show(); @@ -231,6 +225,12 @@ namespace osu.Game.Online.Leaderboards if (getScoresRequest == null) return; + if (api?.IsLoggedIn != true) + { + PlaceholderState = PlaceholderState.NotLoggedIn; + return; + } + getScoresRequest.Failure += e => Schedule(() => { if (e is OperationCanceledException) @@ -243,6 +243,11 @@ namespace osu.Game.Online.Leaderboards }); } + /// + /// Performs a fetch/refresh of scores to be displayed. + /// + /// A callback which should be called when fetching is completed. Scheduling is not required. + /// An responsible for the fetch operation. This will be queued and performed automatically. protected abstract APIRequest FetchScores(Action> scoresCallback); private Placeholder currentPlaceholder; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e60a73467b..c5602fc4ad 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -63,6 +64,8 @@ namespace osu.Game.Online.Leaderboards statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList(); + Avatar innerAvatar; + Children = new Drawable[] { new Container @@ -75,9 +78,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-MediumItalic", - TextSize = 22, - // ReSharper disable once ImpureMethodCallOnReadonlyValueField + Font = OsuFont.GetFont(size: 22, italics: true), Text = RankPosition.ToString(), }, }, @@ -110,12 +111,11 @@ namespace osu.Game.Online.Leaderboards Children = new[] { avatar = new DelayedLoadWrapper( - new Avatar(user) + innerAvatar = new Avatar(user) { RelativeSizeAxes = Axes.Both, CornerRadius = corner_radius, Masking = true, - OnLoadComplete = d => d.FadeInFromZero(200), EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -137,8 +137,7 @@ namespace osu.Game.Online.Leaderboards nameLabel = new OsuSpriteText { Text = user.Username, - Font = @"Exo2.0-BoldItalic", - TextSize = 23, + Font = OsuFont.GetFont(size: 23, weight: FontWeight.Bold, italics: true) }, new FillFlowContainer { @@ -187,7 +186,7 @@ namespace osu.Game.Online.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), OsuFont.Numeric.With(size: 23), Color4.White, OsuColour.FromHex(@"83ccfa")), RankContainer = new Container { Size = new Vector2(40f, 20f), @@ -216,6 +215,8 @@ namespace osu.Game.Online.Leaderboards }, }, }; + + innerAvatar.OnLoadComplete += d => d.FadeInFromZero(200); } public override void Show() @@ -275,7 +276,7 @@ namespace osu.Game.Online.Leaderboards private class GlowingSpriteText : Container { - public GlowingSpriteText(string text, string font, int textSize, Color4 textColour, Color4 glowColour) + public GlowingSpriteText(string text, FontUsage font, Color4 textColour, Color4 glowColour) { AutoSizeAxes = Axes.Both; @@ -296,9 +297,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - FixedWidth = true, - TextSize = textSize, + Font = font.With(fixedWidth: true), Text = text, Colour = glowColour, Shadow = false, @@ -309,9 +308,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - FixedWidth = true, - TextSize = textSize, + Font = font.With(fixedWidth: true), Text = text, Colour = textColour, Shadow = false, @@ -369,7 +366,7 @@ namespace osu.Game.Online.Leaderboards }, }, }, - new GlowingSpriteText(statistic.Value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa")) + new GlowingSpriteText(statistic.Value, OsuFont.GetFont(size: 17, weight: FontWeight.Bold), Color4.White, OsuColour.FromHex(@"83ccfa")) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs index ea92836e6e..d4256e4a9d 100644 --- a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; @@ -14,7 +14,7 @@ namespace osu.Game.Online.Leaderboards { AddIcon(FontAwesome.fa_exclamation_circle, cp => { - cp.TextSize = TEXT_SIZE; + cp.Font = cp.Font.With(size: TEXT_SIZE); cp.Padding = new MarginPadding { Right = 10 }; }); diff --git a/osu.Game/Online/Leaderboards/Placeholder.cs b/osu.Game/Online/Leaderboards/Placeholder.cs index 4994ce0e99..d38110a9d0 100644 --- a/osu.Game/Online/Leaderboards/Placeholder.cs +++ b/osu.Game/Online/Leaderboards/Placeholder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -12,7 +12,7 @@ namespace osu.Game.Online.Leaderboards protected const float TEXT_SIZE = 22; protected Placeholder() - : base(cp => cp.TextSize = TEXT_SIZE) + : base(cp => cp.Font = cp.Font.With(size: TEXT_SIZE)) { Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game/Online/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs index 504b03432f..930e1df484 100644 --- a/osu.Game/Online/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Online.Leaderboards { diff --git a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs index 7fed40ed1a..9edd578967 100644 --- a/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/RetrievalFailurePlaceholder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index e800142f9b..10381d93bb 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs index c9d16662ba..4d6a792377 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTag.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs index 952d1a39ac..350e609b83 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTagTeam.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs index 49e7cef88d..c25bce1c71 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTeamVersus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs index ab8658dfb2..8971368db1 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeTimeshift.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs index c74ce63470..4640c7b361 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/GameTypeVersus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs index b4d8279d02..b6e8e4458f 100644 --- a/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs +++ b/osu.Game/Online/Multiplayer/GameTypes/VersusRow.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Online/Multiplayer/PlaylistItem.cs b/osu.Game/Online/Multiplayer/PlaylistItem.cs index 63b5b95b9c..e47d497d94 100644 --- a/osu.Game/Online/Multiplayer/PlaylistItem.cs +++ b/osu.Game/Online/Multiplayer/PlaylistItem.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; @@ -37,10 +37,10 @@ namespace osu.Game.Online.Multiplayer public RulesetInfo Ruleset { get; set; } [JsonIgnore] - public readonly BindableList AllowedMods = new BindableList(); + public readonly List AllowedMods = new List(); [JsonIgnore] - public readonly BindableList RequiredMods = new BindableList(); + public readonly List RequiredMods = new List(); [JsonProperty("beatmap")] private APIBeatmap apiBeatmap { get; set; } diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 5273c7acfb..53089897f7 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Users; @@ -14,49 +15,78 @@ namespace osu.Game.Online.Multiplayer { public class Room { + [Cached] [JsonProperty("id")] public Bindable RoomID { get; private set; } = new Bindable(); + [Cached] [JsonProperty("name")] public Bindable Name { get; private set; } = new Bindable(); + [Cached] [JsonProperty("host")] public Bindable Host { get; private set; } = new Bindable(); + [Cached] [JsonProperty("playlist")] - public BindableList Playlist { get; set; } = new BindableList(); + public BindableList Playlist { get; private set; } = new BindableList(); + [Cached] + [JsonIgnore] + public Bindable CurrentItem { get; private set; } = new Bindable(); + + [Cached] [JsonProperty("channel_id")] public Bindable ChannelId { get; private set; } = new Bindable(); + [Cached] [JsonIgnore] public Bindable Duration { get; private set; } = new Bindable(TimeSpan.FromMinutes(30)); + [Cached] [JsonIgnore] public Bindable MaxAttempts { get; private set; } = new Bindable(); + [Cached] [JsonIgnore] public Bindable Status { get; private set; } = new Bindable(new RoomStatusOpen()); + [Cached] [JsonIgnore] public Bindable Availability { get; private set; } = new Bindable(); + [Cached] [JsonIgnore] public Bindable Type { get; private set; } = new Bindable(new GameTypeTimeshift()); + [Cached] [JsonIgnore] public Bindable MaxParticipants { get; private set; } = new Bindable(); + [Cached] [JsonIgnore] public Bindable> Participants { get; private set; } = new Bindable>(Enumerable.Empty()); + [Cached] public Bindable ParticipantCount { get; private set; } = new Bindable(); + public Room() + { + Playlist.ItemsAdded += updateCurrent; + Playlist.ItemsRemoved += updateCurrent; + updateCurrent(Playlist); + } + + private void updateCurrent(IEnumerable playlist) + { + CurrentItem.Value = playlist.FirstOrDefault(); + } + // todo: TEMPORARY [JsonProperty("participant_count")] private int? participantCount { - get => ParticipantCount; + get => ParticipantCount.Value; set => ParticipantCount.Value = value ?? 0; } @@ -68,6 +98,7 @@ namespace osu.Game.Online.Multiplayer } // Only supports retrieval for now + [Cached] [JsonProperty("ends_at")] public Bindable EndDate { get; private set; } = new Bindable(); @@ -75,7 +106,7 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts { - get => MaxAttempts; + get => MaxAttempts.Value; set => MaxAttempts.Value = value; } @@ -83,23 +114,24 @@ namespace osu.Game.Online.Multiplayer /// The position of this in the list. This is not read from or written to the API. /// [JsonIgnore] - public int Position = -1; + public Bindable Position { get; private set; } = new Bindable(-1); public void CopyFrom(Room other) { - RoomID.Value = other.RoomID; - Name.Value = other.Name; + RoomID.Value = other.RoomID.Value; + Name.Value = other.Name.Value; if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id) - Host.Value = other.Host; + Host.Value = other.Host.Value; - Status.Value = other.Status; - Availability.Value = other.Availability; - Type.Value = other.Type; - MaxParticipants.Value = other.MaxParticipants; + ChannelId.Value = other.ChannelId.Value; + Status.Value = other.Status.Value; + Availability.Value = other.Availability.Value; + Type.Value = other.Type.Value; + MaxParticipants.Value = other.MaxParticipants.Value; ParticipantCount.Value = other.ParticipantCount.Value; Participants.Value = other.Participants.Value.ToArray(); - EndDate.Value = other.EndDate; + EndDate.Value = other.EndDate.Value; if (DateTimeOffset.Now >= EndDate.Value) Status.Value = new RoomStatusEnded(); diff --git a/osu.Game/Online/Multiplayer/RoomAvailability.cs b/osu.Game/Online/Multiplayer/RoomAvailability.cs index 6c154207ff..08fa853562 100644 --- a/osu.Game/Online/Multiplayer/RoomAvailability.cs +++ b/osu.Game/Online/Multiplayer/RoomAvailability.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; diff --git a/osu.Game/Online/Multiplayer/RoomStatus.cs b/osu.Game/Online/Multiplayer/RoomStatus.cs index f5c339c71f..3ff2770ab4 100644 --- a/osu.Game/Online/Multiplayer/RoomStatus.cs +++ b/osu.Game/Online/Multiplayer/RoomStatus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs index e6ab3ab495..4177d28a99 100644 --- a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusEnded.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs index 6bc701feda..45a1cb1909 100644 --- a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusOpen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs index a725aca03a..b2cb5c4510 100644 --- a/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs +++ b/osu.Game/Online/Multiplayer/RoomStatuses/RoomStatusPlaying.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Online/PollingComponent.cs b/osu.Game/Online/PollingComponent.cs index 6296608e5d..acbb2c39f4 100644 --- a/osu.Game/Online/PollingComponent.cs +++ b/osu.Game/Online/PollingComponent.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Threading.Tasks; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index bb356ce7f0..7277990987 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; +using System.Diagnostics; using osu.Framework.Configuration; using osu.Framework.Screens; using osu.Game.Configuration; @@ -19,6 +20,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -79,27 +81,19 @@ namespace osu.Game public virtual Storage GetStorageForStableInstall() => null; - private Intro intro - { - get - { - Screen screen = screenStack; - while (screen != null && !(screen is Intro)) - screen = screen.ChildScreen; - return screen as Intro; - } - } - public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight; private IdleTracker idleTracker; public readonly Bindable OverlayActivationMode = new Bindable(); - private OsuScreen screenStack; - + private OsuScreenStack screenStack; private VolumeOverlay volume; private OnScreenDisplay onscreenDisplay; + private OsuLogo osuLogo; + + private MainMenu menuScreen; + private Intro introScreen; private Bindable configRuleset; private readonly Bindable ruleset = new Bindable(); @@ -112,6 +106,8 @@ namespace osu.Game private readonly List overlays = new List(); + private readonly List visibleBlockingOverlays = new List(); + // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] [Cached(Type = typeof(IBindable>))] @@ -130,6 +126,22 @@ namespace osu.Game public void ToggleDirect() => direct.ToggleVisibility(); + private void updateBlockingOverlayFade() => + screenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); + + public void AddBlockingOverlay(OverlayContainer overlay) + { + if (!visibleBlockingOverlays.Contains(overlay)) + visibleBlockingOverlays.Add(overlay); + updateBlockingOverlayFade(); + } + + public void RemoveBlockingOverlay(OverlayContainer overlay) + { + visibleBlockingOverlays.Remove(overlay); + updateBlockingOverlayFade(); + } + /// /// Close all game-wide overlays. /// @@ -151,8 +163,6 @@ namespace osu.Game { this.frameworkConfig = frameworkConfig; - ScoreManager.ItemAdded += (score, _, silent) => Schedule(() => LoadScore(score, silent)); - if (!Host.IsPrimaryInstance) { Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error); @@ -173,18 +183,22 @@ namespace osu.Game dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); + dependencies.Cache(osuLogo = new OsuLogo { Alpha = 0 }); + // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); - ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; + ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; // bind config int to database SkinInfo configSkin = LocalConfig.GetBindable(OsuSetting.Skin); - SkinManager.CurrentSkinInfo.ValueChanged += s => configSkin.Value = s.ID; - configSkin.ValueChanged += id => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == id) ?? SkinInfo.Default; + SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID; + configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; configSkin.TriggerChange(); LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust); + + IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); } private ExternalLinkOpener externalLinkOpener; @@ -197,55 +211,12 @@ namespace osu.Game externalLinkOpener.OpenUrlExternally(url); } - private ScheduledDelegate scoreLoad; - /// /// Show a beatmap set as an overlay. /// /// The set to display. public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId); - /// - /// Present a beatmap at song select. - /// - /// The beatmap to select. - public void PresentBeatmap(BeatmapSetInfo beatmap) - { - CloseAllOverlays(false); - - void setBeatmap() - { - if (Beatmap.Disabled) - { - Schedule(setBeatmap); - return; - } - - var databasedSet = BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID); - - // Use first beatmap available for current ruleset, else switch ruleset. - var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First(); - - ruleset.Value = first.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); - } - - switch (currentScreen) - { - case SongSelect _: - break; - default: - // navigate to song select if we are not already there. - var menu = (MainMenu)intro.ChildScreen; - - menu.MakeCurrent(); - menu.LoadToSolo(); - break; - } - - setBeatmap(); - } - /// /// Show a user's profile as an overlay. /// @@ -258,21 +229,44 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); - protected void LoadScore(ScoreInfo score, bool silent) + /// + /// Present a beatmap at song select immediately. + /// The user should have already requested this interactively. + /// + /// The beatmap to select. + public void PresentBeatmap(BeatmapSetInfo beatmap) { - if (silent) - return; + var databasedSet = beatmap.OnlineBeatmapSetID != null + ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) + : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash); - scoreLoad?.Cancel(); - - var menu = intro.ChildScreen; - - if (menu == null) + if (databasedSet == null) { - scoreLoad = Schedule(() => LoadScore(score, false)); + Logger.Log("The requested beatmap could not be loaded.", LoggingTarget.Information); return; } + performFromMainMenu(() => + { + // we might already be at song select, so a check is required before performing the load to solo. + if (menuScreen.IsCurrentScreen()) + menuScreen.LoadToSolo(); + + // Use first beatmap available for current ruleset, else switch ruleset. + var first = databasedSet.Beatmaps.Find(b => b.Ruleset == ruleset.Value) ?? databasedSet.Beatmaps.First(); + + ruleset.Value = first.Ruleset; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); + }, $"load {beatmap}", bypassScreenAllowChecks: true, targetScreen: typeof(PlaySongSelect)); + } + + /// + /// Present a score's replay immediately. + /// The user should have already requested this interactively. + /// + /// The beatmap to select. + public void PresentScore(ScoreInfo score) + { var databasedScore = ScoreManager.GetScore(score); var databasedScoreInfo = databasedScore.ScoreInfo; if (databasedScore.Replay == null) @@ -288,14 +282,40 @@ namespace osu.Game return; } - if (!currentScreen.AllowExternalScreenChange) + performFromMainMenu(() => + { + ruleset.Value = databasedScoreInfo.Ruleset; + + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); + Beatmap.Value.Mods.Value = databasedScoreInfo.Mods; + + menuScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); + }, $"watch {databasedScoreInfo}", bypassScreenAllowChecks: true); + } + + private ScheduledDelegate performFromMainMenuTask; + + /// + /// Perform an action only after returning to the main menu. + /// Eagerly tries to exit the current screen until it succeeds. + /// + /// The action to perform once we are in the correct state. + /// The task name to display in a notification (if we can't immediately reach the main menu state). + /// An optional target screen type. If this screen is already current we can immediately perform the action without returning to the menu. + /// Whether checking should be bypassed. + private void performFromMainMenu(Action action, string taskName, Type targetScreen = null, bool bypassScreenAllowChecks = false) + { + performFromMainMenuTask?.Cancel(); + + // if the current screen does not allow screen changing, give the user an option to try again later. + if (!bypassScreenAllowChecks && (screenStack.CurrentScreen as IOsuScreen)?.AllowExternalScreenChange == false) { notifications.Post(new SimpleNotification { - Text = $"Click here to watch {databasedScoreInfo.User.Username} on {databasedScoreInfo.Beatmap}", + Text = $"Click here to {taskName}", Activated = () => { - loadScore(); + performFromMainMenu(action, taskName, targetScreen, true); return true; } }); @@ -303,24 +323,26 @@ namespace osu.Game return; } - loadScore(); + CloseAllOverlays(false); - void loadScore() + // we may already be at the target screen type. + if (targetScreen != null && screenStack.CurrentScreen?.GetType() == targetScreen) { - if (!menu.IsCurrentScreen) - { - menu.MakeCurrent(); - this.Delay(500).Schedule(loadScore, out scoreLoad); - return; - } - - ruleset.Value = databasedScoreInfo.Ruleset; - - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap); - Beatmap.Value.Mods.Value = databasedScoreInfo.Mods; - - currentScreen.Push(new PlayerLoader(() => new ReplayPlayer(databasedScore))); + action(); + return; } + + // all conditions have been met to continue with the action. + if (menuScreen?.IsCurrentScreen() == true && !Beatmap.Disabled) + { + action(); + return; + } + + // menuScreen may not be initialised yet (null check required). + menuScreen?.MakeCurrent(); + + performFromMainMenuTask = Schedule(() => performFromMainMenu(action, taskName)); } protected override void Dispose(bool isDisposing) @@ -336,7 +358,7 @@ namespace osu.Game // The next time this is updated is in UpdateAfterChildren, which occurs too late and results // in the cursor being shown for a few frames during the intro. // This prevents the cursor from showing until we have a screen with CursorVisible = true - MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false; // todo: all archive managers should be able to be looped here. SkinManager.PostNotification = n => notifications?.Post(n); @@ -344,8 +366,12 @@ namespace osu.Game BeatmapManager.PostNotification = n => notifications?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; + BeatmapManager.PresentImport = items => PresentBeatmap(items.First()); - BeatmapManager.PresentBeatmap = PresentBeatmap; + ScoreManager.PostNotification = n => notifications?.Post(n); + ScoreManager.PresentImport = items => PresentScore(items.First()); + + Container logoContainer; AddRange(new Drawable[] { @@ -358,17 +384,32 @@ namespace osu.Game screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays) { RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }, + logoContainer = new Container { RelativeSizeAxes = Axes.Both }, + } }, - mainContent = new DrawSizePreservingFillContainer(), - overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue }, - idleTracker = new IdleTracker(6000) + overlayContent = new Container + { + RelativeSizeAxes = Axes.Both, + }, + floatingOverlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue }, + idleTracker = new GameIdleTracker(6000) }); - loadComponentSingleFile(screenStack = new Loader(), d => + screenStack.ScreenPushed += screenPushed; + screenStack.ScreenExited += screenExited; + + loadComponentSingleFile(osuLogo, logo => { - screenStack.ModePushed += screenAdded; - screenStack.Exited += screenRemoved; - screenContainer.Add(screenStack); + logoContainer.Add(logo); + + // Loader has to be created after the logo has finished loading as Loader performs logo transformations on entering. + screenStack.Push(new Loader + { + RelativeSizeAxes = Axes.Both + }); }); loadComponentSingleFile(Toolbar = new Toolbar @@ -377,34 +418,34 @@ namespace osu.Game OnHome = delegate { CloseAllOverlays(false); - intro?.ChildScreen?.MakeCurrent(); + menuScreen?.MakeCurrent(); }, - }, overlayContent.Add); + }, floatingOverlayContent.Add); - loadComponentSingleFile(volume = new VolumeOverlay(), overlayContent.Add); + loadComponentSingleFile(volume = new VolumeOverlay(), floatingOverlayContent.Add); loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); loadComponentSingleFile(screenshotManager, Add); //overlay elements - loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); - loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, overlayContent.Add); + loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, overlayContent.Add); loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal); - loadComponentSingleFile(chatOverlay = new ChatOverlay { Depth = -1 }, mainContent.Add); + loadComponentSingleFile(chatOverlay = new ChatOverlay { Depth = -1 }, overlayContent.Add); loadComponentSingleFile(settings = new MainSettings { GetToolbarHeight = () => ToolbarOffset, Depth = -1 - }, overlayContent.Add); - loadComponentSingleFile(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); - loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -3 }, mainContent.Add); + }, floatingOverlayContent.Add); + loadComponentSingleFile(userProfile = new UserProfileOverlay { Depth = -2 }, overlayContent.Add); + loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -3 }, overlayContent.Add); loadComponentSingleFile(musicController = new MusicController { Depth = -5, Position = new Vector2(0, Toolbar.HEIGHT), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, overlayContent.Add); + }, floatingOverlayContent.Add); loadComponentSingleFile(notifications = new NotificationOverlay { @@ -412,24 +453,24 @@ namespace osu.Game Depth = -4, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - }, overlayContent.Add); + }, floatingOverlayContent.Add); loadComponentSingleFile(accountCreation = new AccountCreationOverlay { Depth = -6, - }, overlayContent.Add); + }, floatingOverlayContent.Add); loadComponentSingleFile(dialogOverlay = new DialogOverlay { Depth = -7, - }, overlayContent.Add); + }, floatingOverlayContent.Add); loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener { Depth = -8, - }, overlayContent.Add); + }, floatingOverlayContent.Add); - dependencies.Cache(idleTracker); + dependencies.CacheAs(idleTracker); dependencies.Cache(settings); dependencies.Cache(onscreenDisplay); dependencies.Cache(social); @@ -455,6 +496,7 @@ namespace osu.Game overlay.StateChanged += state => { if (state == Visibility.Hidden) return; + singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; } @@ -468,6 +510,7 @@ namespace osu.Game overlay.StateChanged += state => { if (state == Visibility.Hidden) return; + informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); }; } @@ -489,9 +532,9 @@ namespace osu.Game }; } - OverlayActivationMode.ValueChanged += v => + OverlayActivationMode.ValueChanged += mode => { - if (v != OverlayActivation.All) CloseAllOverlays(); + if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); }; void updateScreenOffset() @@ -510,6 +553,24 @@ namespace osu.Game notifications.StateChanged += _ => updateScreenOffset(); } + public class GameIdleTracker : IdleTracker + { + private InputManager inputManager; + + public GameIdleTracker(int time) + : base(time) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + inputManager = GetContainingInputManager(); + } + + protected override bool AllowIdle => inputManager.FocusedDrawable == null; + } + private void forwardLoggedErrorsToNotifications() { int recentLogCount = 0; @@ -550,21 +611,10 @@ namespace osu.Game } private Task asyncLoadStream; - private int visibleOverlayCount; private void loadComponentSingleFile(T d, Action add) where T : Drawable { - var focused = d as FocusedOverlayContainer; - if (focused != null) - { - focused.StateChanged += s => - { - visibleOverlayCount += s == Visibility.Visible ? 1 : -1; - screenContainer.FadeColour(visibleOverlayCount > 0 ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint); - }; - } - // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. @@ -581,7 +631,25 @@ namespace osu.Game try { Logger.Log($"Loading {d}...", level: LogLevel.Debug); - await LoadComponentAsync(d, add); + + // Since this is running in a separate thread, it is possible for OsuGame to be disposed after LoadComponentAsync has been called + // throwing an exception. To avoid this, the call is scheduled on the update thread, which does not run if IsDisposed = true + Task task = null; + var del = new ScheduledDelegate(() => task = LoadComponentAsync(d, add)); + Scheduler.Add(del); + + // The delegate won't complete if OsuGame has been disposed in the meantime + while (!IsDisposed && !del.Completed) + await Task.Delay(10); + + // Either we're disposed or the load process has started successfully + if (IsDisposed) + return; + + Debug.Assert(task != null); + + await task; + Logger.Log($"Loaded {d}!", level: LogLevel.Debug); } catch (OperationCanceledException) @@ -593,7 +661,7 @@ namespace osu.Game public bool OnPressed(GlobalAction action) { - if (intro == null) return false; + if (introScreen == null) return false; switch (action) { @@ -632,37 +700,34 @@ namespace osu.Game private readonly BindableDouble inactiveVolumeAdjust = new BindableDouble(); - protected override void OnDeactivated() + private void updateActiveState(bool isActive) { - base.OnDeactivated(); - Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); - } - - protected override void OnActivated() - { - base.OnActivated(); - Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + if (isActive) + Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + else + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); } public bool OnReleased(GlobalAction action) => false; - private Container mainContent; - private Container overlayContent; - private OsuScreen currentScreen; + private Container floatingOverlayContent; + private FrameworkConfigManager frameworkConfig; private ScalingContainer screenContainer; protected override bool OnExiting() { - if (screenStack.ChildScreen == null) return false; + if (screenStack.CurrentScreen is Loader) + return false; - if (intro == null) return true; + if (introScreen == null) + return true; - if (!intro.DidLoadMenu || intro.ChildScreen != null) + if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is Intro)) { - Scheduler.Add(intro.MakeCurrent); + Scheduler.Add(introScreen.MakeCurrent); return true; } @@ -685,62 +750,45 @@ namespace osu.Game { base.UpdateAfterChildren(); - // we only want to apply these restrictions when we are inside a screen stack. - // the use case for not applying is in visual/unit tests. - bool applyBeatmapRulesetRestrictions = !currentScreen?.AllowBeatmapRulesetChange ?? false; - - ruleset.Disabled = applyBeatmapRulesetRestrictions; - Beatmap.Disabled = applyBeatmapRulesetRestrictions; - screenContainer.Padding = new MarginPadding { Top = ToolbarOffset }; + overlayContent.Padding = new MarginPadding { Top = ToolbarOffset }; - MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + MenuCursorContainer.CanShowCursor = (screenStack.CurrentScreen as IOsuScreen)?.CursorVisible ?? false; } - /// - /// Sets while ignoring any beatmap. - /// - /// The beatmap to set. - public void ForcefullySetBeatmap(WorkingBeatmap beatmap) + protected virtual void ScreenChanged(IScreen current, IScreen newScreen) { - var beatmapDisabled = Beatmap.Disabled; + switch (newScreen) + { + case Intro intro: + introScreen = intro; + break; + case MainMenu menu: + menuScreen = menu; + break; + } - Beatmap.Disabled = false; - Beatmap.Value = beatmap; - Beatmap.Disabled = beatmapDisabled; + if (newScreen is IOsuScreen newOsuScreen) + { + OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode; + + if (newOsuScreen.HideOverlaysOnEnter) + CloseAllOverlays(); + else + Toolbar.State = Visibility.Visible; + } } - /// - /// Sets while ignoring any ruleset restrictions. - /// - /// The beatmap to set. - public void ForcefullySetRuleset(RulesetInfo ruleset) + private void screenPushed(IScreen lastScreen, IScreen newScreen) { - var rulesetDisabled = this.ruleset.Disabled; - - this.ruleset.Disabled = false; - this.ruleset.Value = ruleset; - this.ruleset.Disabled = rulesetDisabled; - } - - protected virtual void ScreenChanged(OsuScreen current, Screen newScreen) - { - currentScreen = (OsuScreen)newScreen; - } - - private void screenAdded(Screen newScreen) - { - ScreenChanged(currentScreen, newScreen); + ScreenChanged(lastScreen, newScreen); Logger.Log($"Screen changed → {newScreen}"); - - newScreen.ModePushed += screenAdded; - newScreen.Exited += screenRemoved; } - private void screenRemoved(Screen newScreen) + private void screenExited(IScreen lastScreen, IScreen newScreen) { - ScreenChanged(currentScreen, newScreen); - Logger.Log($"Screen changed ← {currentScreen}"); + ScreenChanged(lastScreen, newScreen); + Logger.Log($"Screen changed ← {newScreen}"); if (newScreen == null) Exit(); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index b6c642c9dc..7d55d19e50 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using System.Linq; using System.Reflection; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; @@ -69,14 +69,15 @@ namespace osu.Game protected override Container Content => content; - private OsuBindableBeatmap beatmap; - protected BindableBeatmap Beatmap => beatmap; + private Bindable beatmap; + + protected Bindable Beatmap => beatmap; private Bindable fpsDisplayVisible; - protected AssemblyName AssemblyName => Assembly.GetEntryAssembly()?.GetName() ?? new AssemblyName { Version = new Version() }; + public virtual Version AssemblyVersion => Assembly.GetEntryAssembly()?.GetName().Version ?? new Version(); - public bool IsDeployedBuild => AssemblyName.Version.Major > 0; + public bool IsDeployedBuild => AssemblyVersion.Major > 0; public string Version { @@ -85,8 +86,8 @@ namespace osu.Game if (!IsDeployedBuild) return @"local " + (DebugUtils.IsDebug ? @"debug" : @"release"); - var assembly = AssemblyName; - return $@"{assembly.Version.Major}.{assembly.Version.Minor}.{assembly.Version.Build}"; + var version = AssemblyVersion; + return $@"{version.Major}.{version.Minor}.{version.Build}"; } } @@ -111,8 +112,8 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - var largeStore = new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); - largeStore.AddStore(new TextureLoaderStore(new OnlineStore())); + var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); + largeStore.AddStore(Host.CreateTextureLoaderStore(new OnlineStore())); dependencies.Cache(largeStore); dependencies.CacheAs(this); @@ -151,11 +152,9 @@ namespace osu.Game API = new APIAccess(LocalConfig); - dependencies.Cache(API); dependencies.CacheAs(API); var defaultBeatmap = new DummyWorkingBeatmap(this); - beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); @@ -174,8 +173,10 @@ namespace osu.Game // this adds a global reduction of track volume for the time being. Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8)); - dependencies.CacheAs(beatmap); - dependencies.CacheAs(beatmap); + beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); + + dependencies.CacheAs>(beatmap); + dependencies.CacheAs(beatmap); FileStore.Cleanup(); @@ -207,7 +208,7 @@ namespace osu.Game // TODO: This is temporary until we reimplement the local FPS display. // It's just to allow end-users to access the framework FPS display without knowing the shortcut key. fpsDisplayVisible = LocalConfig.GetBindable(OsuSetting.ShowFpsDisplay); - fpsDisplayVisible.ValueChanged += val => { FrameStatisticsMode = val ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; + fpsDisplayVisible.ValueChanged += visible => { FrameStatisticsMode = visible.NewValue ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; fpsDisplayVisible.TriggerChange(); } diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs index d1686912c5..2e52ca74f3 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationBackground.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs index 371428d988..7e2ae405cb 100644 --- a/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs +++ b/osu.Game/Overlays/AccountCreation/AccountCreationScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Screens; @@ -8,22 +8,22 @@ namespace osu.Game.Overlays.AccountCreation { public abstract class AccountCreationScreen : Screen { - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - Content.FadeOut().Delay(200).FadeIn(200); + this.FadeOut().Delay(200).FadeIn(200); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { base.OnResuming(last); - Content.FadeIn(200); + this.FadeIn(200); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); - Content.FadeOut(200); + this.FadeOut(200); } } } diff --git a/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs index 9ff6a5a7ef..87ff4dd398 100644 --- a/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs +++ b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Graphics; @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.AccountCreation private readonly List errorDrawables = new List(); public ErrorTextFlowContainer() - : base(cp => { cp.TextSize = 12; }) + : base(cp => cp.Font = cp.Font.With(size: 12)) { } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index bfc437f763..13d8df098f 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -10,6 +10,7 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; +using osu.Framework.Platform; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -32,19 +33,21 @@ namespace osu.Game.Overlays.AccountCreation private OsuTextBox emailTextBox; private OsuPasswordTextBox passwordTextBox; - private APIAccess api; + private IAPIProvider api; private ShakeContainer registerShake; private IEnumerable characterCheckText; private OsuTextBox[] textboxes; private ProcessingOverlay processingOverlay; + private GameHost host; [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api) + private void load(OsuColour colours, IAPIProvider api, GameHost host) { this.api = api; + this.host = host; - Children = new Drawable[] + InternalChildren = new Drawable[] { new FillFlowContainer { @@ -58,10 +61,10 @@ namespace osu.Game.Overlays.AccountCreation { new OsuSpriteText { - TextSize = 20, Margin = new MarginPadding { Vertical = 10 }, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 20), Text = "Let's create an account!", }, usernameTextBox = new OsuTextBox @@ -126,24 +129,24 @@ namespace osu.Game.Overlays.AccountCreation usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); - emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); + emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = cp.Font.With(Typeface.Exo, weight: FontWeight.Bold)); passwordDescription.AddText("At least "); characterCheckText = passwordDescription.AddText("8 characters long"); passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); - passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; + passwordTextBox.Current.ValueChanged += password => { characterCheckText.ForEach(s => s.Colour = password.NewValue.Length == 0 ? Color4.White : Interpolation.ValueAt(password.NewValue.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; } protected override void Update() { base.Update(); - if (!textboxes.Any(t => t.HasFocus)) + if (host?.OnScreenKeyboardOverlapsGameWindow != true && !textboxes.Any(t => t.HasFocus)) focusNextTextbox(); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); processingOverlay.Hide(); diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 082eb8a51f..be417f4aac 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -22,16 +22,16 @@ namespace osu.Game.Overlays.AccountCreation { private OsuTextFlowContainer multiAccountExplanationText; private LinkFlowContainer furtherAssistance; - private APIAccess api; + private IAPIProvider api; private const string help_centre_url = "/help/wiki/Help_Centre#login"; - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { if (string.IsNullOrEmpty(api.ProvidedUsername)) { - Content.FadeOut(); - Push(new ScreenEntry()); + this.FadeOut(); + this.Push(new ScreenEntry()); return; } @@ -39,14 +39,14 @@ namespace osu.Game.Overlays.AccountCreation } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, APIAccess api, OsuGame game, TextureStore textures) + private void load(OsuColour colours, IAPIProvider api, OsuGame game, TextureStore textures) { this.api = api; if (string.IsNullOrEmpty(api.ProvidedUsername)) return; - Children = new Drawable[] + InternalChildren = new Drawable[] { new Sprite { @@ -83,14 +83,13 @@ namespace osu.Game.Overlays.AccountCreation }, new OsuSpriteText { - TextSize = 28, - Font = "Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = Color4.Red, + Font = OsuFont.GetFont(size: 28, weight: FontWeight.Light), Text = "Warning! 注意!", }, - multiAccountExplanationText = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + multiAccountExplanationText = new OsuTextFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y @@ -104,9 +103,9 @@ namespace osu.Game.Overlays.AccountCreation new DangerousSettingsButton { Text = "I understand. This account isn't for me.", - Action = () => Push(new ScreenEntry()) + Action = () => this.Push(new ScreenEntry()) }, - furtherAssistance = new LinkFlowContainer(cp => { cp.TextSize = 12; }) + furtherAssistance = new LinkFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) { Margin = new MarginPadding { Top = 20 }, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index 5b7dc21be8..f6ddb135ec 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -1,9 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Screens; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Settings; using osu.Game.Screens.Menu; @@ -16,7 +18,7 @@ namespace osu.Game.Overlays.AccountCreation [BackgroundDependencyLoader] private void load() { - Child = new FillFlowContainer + InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, @@ -39,24 +41,23 @@ namespace osu.Game.Overlays.AccountCreation }, new OsuSpriteText { - TextSize = 24, - Font = "Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Text = "New Player Registration", }, new OsuSpriteText { - TextSize = 12, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 12), Text = "let's get you started", }, new SettingsButton { Text = "Let's create an account!", Margin = new MarginPadding { Vertical = 120 }, - Action = () => Push(new ScreenWarning()) + Action = () => this.Push(new ScreenWarning()) } } }; diff --git a/osu.Game/Overlays/AccountCreationOverlay.cs b/osu.Game/Overlays/AccountCreationOverlay.cs index 9bc4119716..e8e44c206e 100644 --- a/osu.Game/Overlays/AccountCreationOverlay.cs +++ b/osu.Game/Overlays/AccountCreationOverlay.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.API; @@ -29,7 +30,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api) + private void load(OsuColour colours, IAPIProvider api) { api.Register(this); @@ -69,7 +70,10 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.9f, }, - welcomeScreen = new ScreenWelcome(), + new ScreenStack(welcomeScreen = new ScreenWelcome()) + { + RelativeSizeAxes = Axes.Both, + }, } } } @@ -82,7 +86,7 @@ namespace osu.Game.Overlays base.PopIn(); this.FadeIn(transition_time, Easing.OutQuint); - if (welcomeScreen.ChildScreen != null) + if (welcomeScreen.GetChildScreen() != null) welcomeScreen.MakeCurrent(); } @@ -92,7 +96,7 @@ namespace osu.Game.Overlays this.FadeOut(100); } - public void APIStateChanged(APIAccess api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 0b260d4f39..18de87e7b4 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -11,6 +11,8 @@ using osuTK; using osuTK.Graphics; using osu.Game.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; namespace osu.Game.Overlays.BeatmapSet { @@ -25,10 +27,11 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; updateDisplay(); @@ -47,8 +50,8 @@ namespace osu.Game.Overlays.BeatmapSet fields.Children = new Drawable[] { - new Field("mapped by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"), - new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold") + new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), + new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold)) { Margin = new MarginPadding { Top = 5 }, }, @@ -56,11 +59,11 @@ namespace osu.Game.Overlays.BeatmapSet if (online.Ranked.HasValue) { - fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold")); + fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); } else if (online.LastUpdated.HasValue) { - fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold")); + fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); } } @@ -105,7 +108,7 @@ namespace osu.Game.Overlays.BeatmapSet private class Field : FillFlowContainer { - public Field(string first, string second, string secondFont) + public Field(string first, string second, FontUsage secondFont) { AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; @@ -115,13 +118,12 @@ namespace osu.Game.Overlays.BeatmapSet new OsuSpriteText { Text = $"{first} ", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, new OsuSpriteText { Text = second, - TextSize = 13, - Font = secondFont, + Font = secondFont.With(size: 13) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 26402b6e37..9ed9875be9 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -21,10 +21,11 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; updateDisplay(); @@ -35,10 +36,11 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (value == beatmap) return; + beatmap = value; updateDisplay(); @@ -95,8 +97,8 @@ namespace osu.Game.Overlays.BeatmapSet public string Value { - get { return value.Text; } - set { this.value.Text = value; } + get => value.Text; + set => this.value.Text = value; } public Statistic(FontAwesome icon, string name) @@ -136,9 +138,8 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 13, - Font = @"Exo2.0-Bold", Margin = new MarginPadding { Left = 10 }, + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), }, }, }, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 64a8a1062c..55dee904b4 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -33,12 +33,14 @@ namespace osu.Game.Overlays.BeatmapSet public readonly Bindable Beatmap = new Bindable(); private BeatmapSetInfo beatmapSet; + public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; updateDisplay(); @@ -107,15 +109,13 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 20, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) }, starRating = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 13, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), Text = "Star Difficulty", Alpha = 0, Margin = new MarginPadding { Bottom = 1 }, @@ -140,7 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet Beatmap.ValueChanged += b => { - showBeatmap(b); + showBeatmap(b.NewValue); updateDifficultyButtons(); }; } @@ -196,12 +196,14 @@ namespace osu.Game.Overlays.BeatmapSet public event Action StateChanged; private DifficultySelectorState state; + public DifficultySelectorState State { - get { return state; } + get => state; set { if (value == state) return; + state = value; StateChanged?.Invoke(State); @@ -279,9 +281,10 @@ namespace osu.Game.Overlays.BeatmapSet private readonly OsuSpriteText text; private int value; + public int Value { - get { return value; } + get => value; set { this.value = value; @@ -309,8 +312,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-SemiBoldItalic", - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 8406dada44..bbbcff0558 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -1,112 +1,162 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; +using osu.Game.Overlays.Direct; using osu.Game.Users; using osuTK; using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet.Buttons { - public class DownloadButton : HeaderButton, IHasTooltip + public class DownloadButton : DownloadTrackingComposite, IHasTooltip { - public string TooltipText => Enabled ? null : "You gotta be an osu!supporter to download for now 'yo"; + private readonly bool noVideo; + + public string TooltipText => button.Enabled.Value ? "Download this beatmap" : "Login to download"; private readonly IBindable localUser = new Bindable(); - public DownloadButton(BeatmapSetInfo set, bool noVideo = false) - { - Width = 120; + private ShakeContainer shakeContainer; + private HeaderButton button; - BeatmapSetDownloader downloader; - Add(new Container + public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + : base(beatmapSet) + { + this.noVideo = noVideo; + + Width = 120; + RelativeSizeAxes = Axes.Y; + } + + [BackgroundDependencyLoader] + private void load(IAPIProvider api, BeatmapManager beatmaps) + { + FillFlowContainer textSprites; + + AddRangeInternal(new Drawable[] { - Depth = -1, - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 10 }, - Children = new Drawable[] + shakeContainer = new ShakeContainer { - downloader = new BeatmapSetDownloader(set, noVideo), - new FillFlowContainer + Depth = -1, + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new[] + button = new HeaderButton { RelativeSizeAxes = Axes.Both }, + new Container { - new OsuSpriteText + // cannot nest inside here due to the structure of button (putting things in its own content). + // requires framework fix. + Padding = new MarginPadding { Horizontal = 10 }, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Text = "Download", - TextSize = 13, - Font = @"Exo2.0-Bold", - }, - new OsuSpriteText - { - Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, - TextSize = 11, - Font = @"Exo2.0-Bold", - }, + textSprites = new FillFlowContainer + { + Depth = -1, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + AutoSizeDuration = 500, + AutoSizeEasing = Easing.OutQuint, + Direction = FillDirection.Vertical, + }, + new SpriteIcon + { + Depth = -1, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Icon = FontAwesome.fa_download, + Size = new Vector2(16), + Margin = new MarginPadding { Right = 5 }, + }, + } + }, + new DownloadProgressBar(BeatmapSet.Value) + { + Depth = -2, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, }, - }, - new SpriteIcon - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Icon = FontAwesome.fa_download, - Size = new Vector2(16), - Margin = new MarginPadding { Right = 5 }, }, }, }); - Action = () => + button.Action = () => { - if (downloader.DownloadState.Value == BeatmapSetDownloader.DownloadStatus.Downloading) + if (State.Value != DownloadState.NotDownloaded) { - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); + shakeContainer.Shake(); return; } - downloader.Download(); + beatmaps.Download(BeatmapSet.Value, noVideo); }; - downloader.DownloadState.ValueChanged += state => + localUser.BindTo(api.LocalUser); + localUser.BindValueChanged(userChanged, true); + button.Enabled.BindValueChanged(enabledChanged, true); + + State.BindValueChanged(state => { - switch (state) + switch (state.NewValue) { - case BeatmapSetDownloader.DownloadStatus.Downloaded: + case DownloadState.Downloading: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Downloading...", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + }, + }; + break; + case DownloadState.Downloaded: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Importing...", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + }, + }; + break; + case DownloadState.LocallyAvailable: this.FadeOut(200); break; - case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + case DownloadState.NotDownloaded: + textSprites.Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Download", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + }, + new OsuSpriteText + { + Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold) + }, + }; this.FadeIn(200); break; } - }; + }, true); } - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - localUser.BindTo(api.LocalUser); - localUser.BindValueChanged(userChanged, true); - Enabled.BindValueChanged(enabledChanged, true); - } + private void userChanged(ValueChangedEvent e) => button.Enabled.Value = !(e.NewValue is GuestUser); - private void userChanged(User user) => Enabled.Value = user.IsSupporter; - - private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + private void enabledChanged(ValueChangedEvent e) => this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index 929f89482c..7824a78a14 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -53,9 +53,9 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }); - Favourited.ValueChanged += value => + Favourited.ValueChanged += favourited => { - if (value) + if (favourited.NewValue) { pink.FadeIn(200); icon.Icon = FontAwesome.fa_heart; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs index b46b5d2a0e..6de1d3fca7 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index b971403443..8c884e0950 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -30,8 +30,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons public BeatmapSetInfo BeatmapSet { - get { return playButton.BeatmapSet; } - set { playButton.BeatmapSet = value; } + get => playButton.BeatmapSet; + set => playButton.BeatmapSet = value; } public PreviewButton() @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }; Action = () => playButton.Click(); - Playing.ValueChanged += newValue => progress.FadeTo(newValue ? 1 : 0, 100); + Playing.ValueChanged += playing => progress.FadeTo(playing.NewValue ? 1 : 0, 100); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 709d163eaa..fad5c973b7 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -25,10 +25,11 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; basic.BeatmapSet = preview.BeatmapSet = BeatmapSet; @@ -39,7 +40,7 @@ namespace osu.Game.Overlays.BeatmapSet public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (value == beatmap) return; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index d353522d8d..95cf9e9d04 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -13,12 +13,14 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.BeatmapSet.Buttons; +using osu.Game.Overlays.Direct; using osuTK; using osuTK.Graphics; +using DownloadButton = osu.Game.Overlays.BeatmapSet.Buttons.DownloadButton; namespace osu.Game.Overlays.BeatmapSet { - public class Header : Container + public class Header : DownloadTrackingComposite { private const float transition_duration = 200; private const float tabs_height = 50; @@ -28,76 +30,23 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Box tabsBg; private readonly UpdateableBeatmapSetCover cover; private readonly OsuSpriteText title, artist; - private readonly Container noVideoButtons; - private readonly FillFlowContainer videoButtons; private readonly AuthorInfo author; - private readonly Container downloadButtonsContainer; + private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; public Details Details; public readonly BeatmapPicker Picker; - private BeatmapSetInfo beatmapSet; private readonly FavouriteButton favouriteButton; - public BeatmapSetInfo BeatmapSet - { - get { return beatmapSet; } - set - { - if (value == beatmapSet) return; - beatmapSet = value; - - Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = BeatmapSet; - - updateDisplay(); - } - } - - private void updateDisplay() - { - title.Text = BeatmapSet?.Metadata.Title ?? string.Empty; - artist.Text = BeatmapSet?.Metadata.Artist ?? string.Empty; - onlineStatusPill.Status = BeatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; - cover.BeatmapSet = BeatmapSet; - - if (BeatmapSet != null) - { - downloadButtonsContainer.FadeIn(transition_duration); - favouriteButton.FadeIn(transition_duration); - - if (BeatmapSet.OnlineInfo.HasVideo) - { - videoButtons.Children = new[] - { - new DownloadButton(BeatmapSet), - new DownloadButton(BeatmapSet, true), - }; - - videoButtons.FadeIn(transition_duration); - noVideoButtons.FadeOut(transition_duration); - } - else - { - noVideoButtons.Child = new DownloadButton(BeatmapSet); - - noVideoButtons.FadeIn(transition_duration); - videoButtons.FadeOut(transition_duration); - } - } - else - { - downloadButtonsContainer.FadeOut(transition_duration); - favouriteButton.FadeOut(transition_duration); - } - } - public Header() { ExternalLinkButton externalLink; + RelativeSizeAxes = Axes.X; Height = 400; Masking = true; + EdgeEffect = new EdgeEffectParameters { Colour = Color4.Black.Opacity(0.25f), @@ -105,7 +54,8 @@ namespace osu.Game.Overlays.BeatmapSet Radius = 3, Offset = new Vector2(0f, 1f), }; - Children = new Drawable[] + + InternalChildren = new Drawable[] { new Container { @@ -165,8 +115,7 @@ namespace osu.Game.Overlays.BeatmapSet { title = new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", - TextSize = 37, + Font = OsuFont.GetFont(size: 37, weight: FontWeight.Bold, italics: true) }, externalLink = new ExternalLinkButton { @@ -176,11 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet }, } }, - artist = new OsuSpriteText - { - Font = @"Exo2.0-SemiBoldItalic", - TextSize = 25, - }, + artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.SemiBold, italics: true) }, new Container { RelativeSizeAxes = Axes.X, @@ -196,24 +141,11 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { favouriteButton = new FavouriteButton(), - downloadButtonsContainer = new Container + downloadButtonsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, - Children = new Drawable[] - { - noVideoButtons = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0f, - }, - videoButtons = new FillFlowContainer - { - RelativeSizeAxes = Axes.Both, - Spacing = new Vector2(buttons_spacing), - Alpha = 0f, - }, - }, + Spacing = new Vector2(buttons_spacing), }, }, }, @@ -244,15 +176,66 @@ namespace osu.Game.Overlays.BeatmapSet }, }; - Picker.Beatmap.ValueChanged += b => Details.Beatmap = b; - Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; + Picker.Beatmap.ValueChanged += b => Details.Beatmap = b.NewValue; + Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b.NewValue?.Ruleset.ShortName}/{b.NewValue?.OnlineBeatmapID}"; } [BackgroundDependencyLoader] private void load(OsuColour colours) { tabsBg.Colour = colours.Gray3; - updateDisplay(); + + State.BindValueChanged(_ => updateDownloadButtons()); + + BeatmapSet.BindValueChanged(setInfo => + { + Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; + + title.Text = setInfo.NewValue?.Metadata.Title ?? string.Empty; + artist.Text = setInfo.NewValue?.Metadata.Artist ?? string.Empty; + onlineStatusPill.Status = setInfo.NewValue?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; + cover.BeatmapSet = setInfo.NewValue; + + if (setInfo.NewValue != null) + { + downloadButtonsContainer.FadeIn(transition_duration); + favouriteButton.FadeIn(transition_duration); + } + else + { + downloadButtonsContainer.FadeOut(transition_duration); + favouriteButton.FadeOut(transition_duration); + } + + updateDownloadButtons(); + }, true); + } + + private void updateDownloadButtons() + { + if (BeatmapSet.Value == null) return; + + switch (State.Value) + { + case DownloadState.LocallyAvailable: + // temporary for UX until new design is implemented. + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) + { + Width = 50, + RelativeSizeAxes = Axes.Y + }; + break; + case DownloadState.Downloading: + case DownloadState.Downloaded: + // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + break; + default: + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); + if (BeatmapSet.Value.OnlineInfo.HasVideo) + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); + break; + } } } } diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index e985da0eb7..4d974a0b63 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -21,37 +22,20 @@ namespace osu.Game.Overlays.BeatmapSet private const float metadata_width = 225; private const float spacing = 20; - private readonly MetadataSection source, tags; private readonly Box successRateBackground; private readonly SuccessRate successRate; - private BeatmapSetInfo beatmapSet; - public BeatmapSetInfo BeatmapSet - { - get { return beatmapSet; } - set - { - if (value == beatmapSet) return; - beatmapSet = value; - - updateDisplay(); - } - } - - private void updateDisplay() - { - source.Text = BeatmapSet?.Metadata.Source ?? string.Empty; - tags.Text = BeatmapSet?.Metadata.Tags ?? string.Empty; - } + public readonly Bindable BeatmapSet = new Bindable(); public BeatmapInfo Beatmap { - get { return successRate.Beatmap; } - set { successRate.Beatmap = value; } + get => successRate.Beatmap; + set => successRate.Beatmap = value; } public Info() { + MetadataSection source, tags; RelativeSizeAxes = Axes.X; Height = 220; Masking = true; @@ -129,14 +113,18 @@ namespace osu.Game.Overlays.BeatmapSet }, }, }; + + BeatmapSet.ValueChanged += b => + { + source.Text = b.NewValue?.Metadata.Source ?? string.Empty; + tags.Text = b.NewValue?.Metadata.Tags ?? string.Empty; + }; } [BackgroundDependencyLoader] private void load(OsuColour colours) { successRateBackground.Colour = colours.GrayE; - - updateDisplay(); } private class MetadataSection : FillFlowContainer @@ -156,14 +144,14 @@ namespace osu.Game.Overlays.BeatmapSet this.FadeIn(transition_duration); textFlow.Clear(); - textFlow.AddText(value, s => s.TextSize = 14); + textFlow.AddText(value, s => s.Font = s.Font.With(size: 14)); } } public Color4 TextColour { - get { return textFlow.Colour; } - set { textFlow.Colour = value; } + get => textFlow.Colour; + set => textFlow.Colour = value; } public MetadataSection(string title) @@ -177,8 +165,7 @@ namespace osu.Game.Overlays.BeatmapSet header = new OsuSpriteText { Text = title, - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Shadow = false, Margin = new MarginPadding { Top = 20 }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs index 0be83db39e..31af251877 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; @@ -16,12 +17,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private UserProfileOverlay profile; private User user; + public User User { - get { return user; } + get => user; set { if (user == value) return; + user = value; text.Text = user.Username; @@ -30,21 +33,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public float TextSize { - set - { - if (text.TextSize == value) return; - text.TextSize = value; - } - get { return text.TextSize; } + get => text.Font.Size; + set => text.Font = text.Font.With(size: value); } public ClickableUsername() { AutoSizeAxes = Axes.Both; - Child = text = new OsuSpriteText - { - Font = @"Exo2.0-BoldItalic", - }; + Child = text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }; } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 89416c1098..c6c8315aeb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Text = $"#{index + 1}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Left = side_margin } }, new DrawableFlag(score.User.Country) @@ -87,17 +87,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, Text = $@"{score.TotalScore:N0}", - Font = @"Venera", + Font = OsuFont.Numeric.With(fixedWidth: true), RelativePositionAxes = Axes.X, X = 0.75f, - FixedWidth = true, }, new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, Text = $@"{score.Accuracy:P2}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), RelativePositionAxes = Axes.X, X = 0.85f }, @@ -106,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Right = side_margin } }, }; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index 6259d85bee..78e560cdbe 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -44,12 +44,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly ScoreModsContainer modsContainer; private APIScoreInfo score; + public APIScoreInfo Score { - get { return score; } + get => score; set { if (score == value) return; + score = value; avatar.User = username.User = score.User; @@ -117,8 +119,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.TopRight, Origin = Anchor.BottomRight, Text = "#1", - TextSize = 40, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 40, weight: FontWeight.Bold, italics: true), Y = height / 4, Margin = new MarginPadding { Right = margin } }, @@ -208,9 +209,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { if (valueText.Text == value) return; + valueText.Text = value; } - get { return valueText.Text; } + get => valueText.Text; } public InfoColumn(string header) @@ -222,15 +224,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { headerText = new OsuSpriteText { - TextSize = 14, Text = header, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, - valueText = new OsuSpriteText - { - TextSize = 25, - Font = @"Exo2.0-RegularItalic", - } + valueText = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.Regular, italics: true) } }; } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index e338d2f90f..3dd03fcea6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public IEnumerable Scores { - get { return scores; } + get => scores; set { getScoresRequest?.Cancel(); @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } private GetScoresRequest getScoresRequest; - private APIAccess api; + private IAPIProvider api; public BeatmapInfo Beatmap { @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; updateDisplay(); diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 6572e520bd..c89bddca63 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -21,12 +21,14 @@ namespace osu.Game.Overlays.BeatmapSet private readonly FailRetryGraph graph; private BeatmapInfo beatmap; + public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (value == beatmap) return; + beatmap = value; updateDisplay(); @@ -62,7 +64,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Success Rate", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, successRate = new Bar { @@ -79,7 +81,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopRight, Origin = Anchor.TopCentre, - TextSize = 13, + Font = OsuFont.GetFont(size: 13), }, }, graphLabel = new OsuSpriteText @@ -87,7 +89,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Points of Failure", - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Margin = new MarginPadding { Vertical = 20 }, }, }, diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 6294851415..c49268bc16 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -29,32 +30,20 @@ namespace osu.Game.Overlays public const float RIGHT_WIDTH = 275; private readonly Header header; - private readonly Info info; - private APIAccess api; + private IAPIProvider api; private RulesetStore rulesets; private readonly ScrollContainer scroll; - private BeatmapSetInfo beatmapSet; - - public BeatmapSetInfo BeatmapSet - { - get => beatmapSet; - set - { - if (value == beatmapSet) - return; - - header.BeatmapSet = info.BeatmapSet = beatmapSet = value; - } - } + private readonly Bindable beatmapSet = new Bindable(); // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; public BeatmapSetOverlay() { + Info info; ScoresContainer scores; Waves.FirstWaveColour = OsuColour.Gray(0.4f); Waves.SecondWaveColour = OsuColour.Gray(0.3f); @@ -101,15 +90,18 @@ namespace osu.Game.Overlays }, }; + header.BeatmapSet.BindTo(beatmapSet); + info.BeatmapSet.BindTo(beatmapSet); + header.Picker.Beatmap.ValueChanged += b => { - info.Beatmap = b; - scores.Beatmap = b; + info.Beatmap = b.NewValue; + scores.Beatmap = b.NewValue; }; } [BackgroundDependencyLoader] - private void load(APIAccess api, RulesetStore rulesets) + private void load(IAPIProvider api, RulesetStore rulesets) { this.api = api; this.rulesets = rulesets; @@ -124,7 +116,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => BeatmapSet = null); + FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out).OnComplete(_ => beatmapSet.Value = null); } protected override bool OnClick(ClickEvent e) @@ -135,12 +127,12 @@ namespace osu.Game.Overlays public void FetchAndShowBeatmap(int beatmapId) { - BeatmapSet = null; + beatmapSet.Value = null; var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId); req.Success += res => { - BeatmapSet = res.ToBeatmapSet(rulesets); - header.Picker.Beatmap.Value = header.BeatmapSet.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); + beatmapSet.Value = res.ToBeatmapSet(rulesets); + header.Picker.Beatmap.Value = header.BeatmapSet.Value.Beatmaps.First(b => b.OnlineBeatmapID == beatmapId); }; api.Queue(req); Show(); @@ -148,16 +140,16 @@ namespace osu.Game.Overlays public void FetchAndShowBeatmapSet(int beatmapSetId) { - BeatmapSet = null; + beatmapSet.Value = null; var req = new GetBeatmapSetRequest(beatmapSetId); - req.Success += res => BeatmapSet = res.ToBeatmapSet(rulesets); + req.Success += res => beatmapSet.Value = res.ToBeatmapSet(rulesets); api.Queue(req); Show(); } public void ShowBeatmapSet(BeatmapSetInfo set) { - BeatmapSet = set; + beatmapSet.Value = set; Show(); scroll.ScrollTo(0); } diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 29579056bf..908ec5f026 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -87,9 +87,8 @@ namespace osu.Game.Overlays.Chat Drawable effectedUsername = username = new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) }; if (hasBackground) @@ -138,9 +137,7 @@ namespace osu.Game.Overlays.Chat { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-SemiBold", - FixedWidth = true, - TextSize = TextSize * 0.75f, + Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true) }, new MessageSender(message.Sender) { @@ -162,13 +159,13 @@ namespace osu.Game.Overlays.Chat { if (Message.IsAction) { - t.Font = @"Exo2.0-MediumItalic"; + t.Font = OsuFont.GetFont(italics: true); if (senderHasBackground) t.Colour = OsuColour.FromHex(message.Sender.Colour); } - t.TextSize = TextSize; + t.Font = t.Font.With(size: TextSize); }) { AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index c8fc15a0bc..e3df81e455 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs index b3f7b282a9..6c3fb4e6f6 100644 --- a/osu.Game/Overlays/Chat/ExternalLinkDialog.cs +++ b/osu.Game/Overlays/Chat/ExternalLinkDialog.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs index 5a96465520..a36abc4f99 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -36,12 +36,10 @@ namespace osu.Game.Overlays.Chat.Selection private Color4 hoverColour; public IEnumerable FilterTerms => new[] { channel.Name }; + public bool MatchingFilter { - set - { - this.FadeTo(value ? 1f : 0f, 100); - } + set => this.FadeTo(value ? 1f : 0f, 100); } public Action OnRequestJoin; @@ -54,7 +52,7 @@ namespace osu.Game.Overlays.Chat.Selection RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Action = () => { (channel.Joined ? OnRequestLeave : OnRequestJoin)?.Invoke(channel); }; + Action = () => { (channel.Joined.Value ? OnRequestLeave : OnRequestJoin)?.Invoke(channel); }; Children = new Drawable[] { @@ -89,8 +87,7 @@ namespace osu.Game.Overlays.Chat.Selection name = new OsuSpriteText { Text = channel.ToString(), - TextSize = text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), Shadow = false, }, }, @@ -106,8 +103,7 @@ namespace osu.Game.Overlays.Chat.Selection topic = new OsuSpriteText { Text = channel.Topic, - TextSize = text_size, - Font = @"Exo2.0-SemiBold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.SemiBold), Shadow = false, }, }, @@ -130,8 +126,7 @@ namespace osu.Game.Overlays.Chat.Selection new OsuSpriteText { Text = @"0", - TextSize = text_size, - Font = @"Exo2.0-SemiBold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.SemiBold), Shadow = false, }, }, @@ -148,7 +143,7 @@ namespace osu.Game.Overlays.Chat.Selection joinedColour = colours.Blue; hoverColour = colours.Yellow; - joinedBind.ValueChanged += updateColour; + joinedBind.ValueChanged += joined => updateColour(joined.NewValue); joinedBind.BindTo(channel.Joined); joinedBind.TriggerChange(); diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs index c02215d690..3f979b6309 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -7,6 +7,7 @@ using System.Linq; using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; @@ -20,23 +21,21 @@ namespace osu.Game.Overlays.Chat.Selection public IEnumerable FilterableChildren => ChannelFlow.Children; public IEnumerable FilterTerms => Array.Empty(); + public bool MatchingFilter { - set - { - this.FadeTo(value ? 1f : 0f, 100); - } + set => this.FadeTo(value ? 1f : 0f, 100); } public string Header { - get { return header.Text; } - set { header.Text = value.ToUpperInvariant(); } + get => header.Text; + set => header.Text = value.ToUpperInvariant(); } public IEnumerable Channels { - set { ChannelFlow.ChildrenEnumerable = value.Select(c => new ChannelListItem(c)); } + set => ChannelFlow.ChildrenEnumerable = value.Select(c => new ChannelListItem(c)); } public ChannelSection() @@ -48,8 +47,7 @@ namespace osu.Game.Overlays.Chat.Selection { header = new OsuSpriteText { - TextSize = 15, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, ChannelFlow = new FillFlowContainer { diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 0cc0076903..71e9e4bdf3 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Chat.Selection new OsuSpriteText { Text = @"Chat Channels", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Shadow = false, }, search = new HeaderSearchTextBox @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Chat.Selection }, }; - search.Current.ValueChanged += newValue => sectionsFlow.SearchTerm = newValue; + search.Current.ValueChanged += term => sectionsFlow.SearchTerm = term.NewValue; } public void UpdateAvailableChannels(IEnumerable channels) @@ -164,7 +164,7 @@ namespace osu.Game.Overlays.Chat.Selection protected override void OnFocus(FocusEvent e) { - GetContainingInputManager().ChangeFocus(search); + search.TakeFocus(); base.OnFocus(e); } @@ -190,8 +190,12 @@ namespace osu.Game.Overlays.Chat.Selection private class HeaderSearchTextBox : SearchTextBox { - protected override Color4 BackgroundFocused => Color4.Black.Opacity(0.2f); - protected override Color4 BackgroundUnfocused => Color4.Black.Opacity(0.2f); + [BackgroundDependencyLoader] + private void load() + { + BackgroundFocused = Color4.Black.Opacity(0.2f); + BackgroundUnfocused = Color4.Black.Opacity(0.2f); + } } } } diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index b370d8f3c5..52260506fe 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; @@ -13,15 +13,16 @@ namespace osu.Game.Overlays.Chat.Tabs public override bool IsSwitchable => false; - public ChannelSelectorTabItem(Channel value) : base(value) + public ChannelSelectorTabItem(Channel value) + : base(value) { Depth = float.MaxValue; Width = 45; Icon.Alpha = 0; - Text.TextSize = 45; - TextBold.TextSize = 45; + Text.Font = Text.Font.With(size: 45); + TextBold.Font = Text.Font.With(size: 45); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index dc72c8053a..7a43ca4b8c 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; @@ -7,9 +7,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Chat; using osuTK; -using osu.Framework.Configuration; using System; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Chat.Tabs { @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Chat.Tabs if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last SelectTab(TabContainer[currentIndex == totalTabs ? currentIndex - 1 : currentIndex + 1]); - else if (totalTabs == 1 && !selectorTab.Active) + else if (totalTabs == 1 && !selectorTab.Active.Value) // Open channel selection overlay if all channel tabs will be closed after removing this tab SelectTab(selectorTab); diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index e98eac0aa2..95c5fbf8fa 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Chat.Tabs Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), - TextSize = 18, + Font = OsuFont.GetFont(size: 18) }, TextBold = new OsuSpriteText { @@ -99,8 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), - Font = @"Exo2.0-Bold", - TextSize = 18, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold) }, CloseButton = new TabCloseButton { @@ -127,7 +126,7 @@ namespace osu.Game.Overlays.Chat.Tabs if (IsRemovable && ShowCloseOnHover) CloseButton.FadeIn(200, Easing.OutQuint); - if (!Active) + if (!Active.Value) box.FadeColour(backgroundHover, TRANSITION_LENGTH, Easing.OutQuint); return true; } @@ -158,7 +157,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void updateState() { - if (Active) + if (Active.Value) FadeActive(); else FadeInactive(); diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 804ddeabb4..8111ac7394 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -28,6 +28,8 @@ namespace osu.Game.Overlays.Chat.Tabs if (value.Type != ChannelType.PM) throw new ArgumentException("Argument value needs to have the targettype user!"); + Avatar avatar; + AddRange(new Drawable[] { new Container @@ -49,11 +51,10 @@ namespace osu.Game.Overlays.Chat.Tabs Anchor = Anchor.Centre, Origin = Anchor.Centre, Masking = true, - Child = new DelayedLoadWrapper(new Avatar(value.Users.First()) + Child = new DelayedLoadWrapper(avatar = new Avatar(value.Users.First()) { RelativeSizeAxes = Axes.Both, OpenOnClick = { Value = false }, - OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), }) { RelativeSizeAxes = Axes.Both, @@ -63,6 +64,8 @@ namespace osu.Game.Overlays.Chat.Tabs }, }); + avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint); + Text.X = ChatOverlay.TAB_AREA_HEIGHT; TextBold.X = ChatOverlay.TAB_AREA_HEIGHT; } @@ -77,7 +80,6 @@ namespace osu.Game.Overlays.Chat.Tabs CloseButton.FadeIn(TRANSITION_LENGTH, Easing.OutQuint); } - protected override void FadeInactive() { base.FadeInactive(); diff --git a/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs b/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs index d7d9b3f95c..e8217fa9f6 100644 --- a/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs +++ b/osu.Game/Overlays/Chat/Tabs/TabCloseButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 680e7ac416..77f88ab4e7 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -162,8 +162,8 @@ namespace osu.Game.Overlays }, }; - channelTabControl.Current.ValueChanged += chat => channelManager.CurrentChannel.Value = chat; - channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelectionOverlay.State = value ? Visibility.Visible : Visibility.Hidden; + channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; + channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State = active.NewValue ? Visibility.Visible : Visibility.Hidden; channelSelectionOverlay.StateChanged += state => { if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) @@ -189,9 +189,9 @@ namespace osu.Game.Overlays channelSelectionOverlay.OnRequestLeave = channel => channelManager.LeaveChannel(channel); } - private void currentChannelChanged(Channel channel) + private void currentChannelChanged(ValueChangedEvent e) { - if (channel == null) + if (e.NewValue == null) { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); @@ -199,18 +199,18 @@ namespace osu.Game.Overlays return; } - textbox.Current.Disabled = channel.ReadOnly; + textbox.Current.Disabled = e.NewValue.ReadOnly; - if (channelTabControl.Current.Value != channel) - Scheduler.Add(() => channelTabControl.Current.Value = channel); + if (channelTabControl.Current.Value != e.NewValue) + Scheduler.Add(() => channelTabControl.Current.Value = e.NewValue); - var loaded = loadedChannels.Find(d => d.Channel == channel); + var loaded = loadedChannels.Find(d => d.Channel == e.NewValue); if (loaded == null) { currentChannelContainer.FadeOut(500, Easing.OutQuint); loading.Show(); - loaded = new DrawableChannel(channel); + loaded = new DrawableChannel(e.NewValue); loadedChannels.Add(loaded); LoadComponentAsync(loaded, l => { @@ -302,7 +302,7 @@ namespace osu.Game.Overlays protected override void OnFocus(FocusEvent e) { //this is necessary as textbox is masked away and therefore can't get focus :( - GetContainingInputManager().ChangeFocus(textbox); + textbox.TakeFocus(); base.OnFocus(e); } @@ -320,6 +320,8 @@ namespace osu.Game.Overlays this.MoveToY(Height, transition_length, Easing.InSine); this.FadeOut(transition_length, Easing.InSine); + channelSelectionOverlay.State = Visibility.Hidden; + textbox.HoldFocus = false; base.PopOut(); } @@ -328,11 +330,11 @@ namespace osu.Game.Overlays private void load(OsuConfigManager config, OsuColour colours, ChannelManager channelManager) { ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); - ChatHeight.ValueChanged += h => + ChatHeight.ValueChanged += height => { - chatContainer.Height = (float)h; - channelSelectionContainer.Height = 1f - (float)h; - tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200); + chatContainer.Height = (float)height.NewValue; + channelSelectionContainer.Height = 1f - (float)height.NewValue; + tabBackground.FadeTo(height.NewValue == 1 ? 1 : 0.8f, 200); }; ChatHeight.TriggerChange(); diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index ca921b7882..72e3cc4f6a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -53,6 +53,7 @@ namespace osu.Game.Overlays.Dialog { if (text == value) return; + text = value; header.Text = value; @@ -171,7 +172,7 @@ namespace osu.Game.Overlays.Dialog }, }, }, - header = new OsuTextFlowContainer(t => t.TextSize = 25) + header = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 25)) { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, @@ -180,7 +181,7 @@ namespace osu.Game.Overlays.Dialog Padding = new MarginPadding(15), TextAnchor = Anchor.TopCentre, }, - body = new OsuTextFlowContainer(t => t.TextSize = 18) + body = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 18)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs index 8c382c6f56..75bae25b73 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs index 45a8dfd29e..754003c1c1 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs index 6c5abbe161..6c2bf6f1e6 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index dae502dbd9..2cc1c20a10 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 006e3a034b..b35dbde639 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -29,7 +29,8 @@ namespace osu.Game.Overlays.Direct protected override PlayButton PlayButton => playButton; protected override Box PreviewBar => progressBar; - public DirectGridPanel(BeatmapSetInfo beatmap) : base(beatmap) + public DirectGridPanel(BeatmapSetInfo beatmap) + : base(beatmap) { Width = 380; Height = 140 + vertical_padding; //full height of all the elements plus vertical padding (autosize uses the image) @@ -75,13 +76,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - TextSize = 18, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)), - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }, }, }, @@ -127,15 +127,14 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = "mapped by ", - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Shadow = false, Colour = colours.Gray5, }, new OsuSpriteText { Text = SetInfo.Metadata.Author.Username, - TextSize = 14, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true), Shadow = false, Colour = colours.BlueDark, }, @@ -150,7 +149,7 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = SetInfo.Metadata.Source, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Shadow = false, Colour = colours.Gray5, Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, @@ -186,10 +185,7 @@ namespace osu.Game.Overlays.Direct Margin = new MarginPadding { Top = vertical_padding, Right = vertical_padding }, Children = new[] { - new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) - { - Margin = new MarginPadding { Right = 1 }, - }, + new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0), new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), }, }, @@ -239,6 +235,6 @@ namespace osu.Game.Overlays.Direct updateStatusContainer(); } - private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying ? 0 : 1, 120, Easing.InOutQuint); + private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying.Value ? 0 : 1, 120, Easing.InOutQuint); } } diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index a922ceb484..d857a0f042 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -13,6 +13,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; namespace osu.Game.Overlays.Direct { @@ -23,6 +24,7 @@ namespace osu.Game.Overlays.Direct private const float vertical_padding = 5; private const float height = 70; + private FillFlowContainer statusContainer; private PlayButton playButton; private Box progressBar; @@ -95,13 +97,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - TextSize = 18, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)), - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }, } }, @@ -109,10 +110,24 @@ namespace osu.Game.Overlays.Direct }, new FillFlowContainer { - AutoSizeAxes = Axes.X, - Height = 20, - Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, - Children = GetDifficultyIcons(), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + statusContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Vertical = vertical_padding, Horizontal = 5 }, + Spacing = new Vector2(5), + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.X, + Height = 20, + Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding }, + Children = GetDifficultyIcons(), + }, + }, }, }, }, @@ -145,10 +160,7 @@ namespace osu.Game.Overlays.Direct Direction = FillDirection.Vertical, Children = new Drawable[] { - new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) - { - Margin = new MarginPadding { Right = 1 }, - }, + new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0), new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), new FillFlowContainer { @@ -161,13 +173,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = "mapped by ", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, new OsuSpriteText { Text = SetInfo.Metadata.Author.Username, - TextSize = 14, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) }, }, }, @@ -176,7 +187,7 @@ namespace osu.Game.Overlays.Direct Text = SetInfo.Metadata.Source, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, }, }, @@ -196,6 +207,23 @@ namespace osu.Game.Overlays.Direct Colour = colours.Yellow, }, }); + + if (SetInfo.OnlineInfo?.HasVideo ?? false) + { + statusContainer.Add(new IconPill(FontAwesome.fa_film) { IconSize = new Vector2(20) }); + } + + if (SetInfo.OnlineInfo?.HasStoryboard ?? false) + { + statusContainer.Add(new IconPill(FontAwesome.fa_image) { IconSize = new Vector2(20) }); + } + + statusContainer.Add(new BeatmapSetOnlineStatusPill + { + TextSize = 12, + TextPadding = new MarginPadding { Horizontal = 10, Vertical = 4 }, + Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None, + }); } } } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 44556a6360..3867886f6d 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -16,8 +16,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API.Requests; using osuTK; using osuTK.Graphics; @@ -31,8 +29,6 @@ namespace osu.Game.Overlays.Direct private Container content; - private ProgressBar progressBar; - private BeatmapManager beatmaps; private BeatmapSetOverlay beatmapSetOverlay; public PreviewTrack Preview => PlayButton.Preview; @@ -65,14 +61,10 @@ namespace osu.Game.Overlays.Direct Colour = Color4.Black.Opacity(0.3f), }; - private OsuColour colours; - [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { - this.beatmaps = beatmaps; this.beatmapSetOverlay = beatmapSetOverlay; - this.colours = colours; AddInternal(content = new Container { @@ -82,40 +74,21 @@ namespace osu.Game.Overlays.Direct Children = new[] { CreateBackground(), - progressBar = new ProgressBar + new DownloadProgressBar(SetInfo) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Height = 0, - Alpha = 0, - BackgroundColour = Color4.Black.Opacity(0.7f), - FillColour = colours.Blue, Depth = -1, }, } }); - - var downloadRequest = beatmaps.GetExistingDownload(SetInfo); - - if (downloadRequest != null) - attachDownload(downloadRequest); - - beatmaps.BeatmapDownloadBegan += attachDownload; - beatmaps.ItemAdded += setAdded; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - beatmaps.BeatmapDownloadBegan -= attachDownload; - beatmaps.ItemAdded -= setAdded; } protected override void Update() { base.Update(); - if (PreviewPlaying && Preview != null && Preview.TrackLoaded) + if (PreviewPlaying.Value && Preview != null && Preview.TrackLoaded) { PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length); } @@ -135,7 +108,7 @@ namespace osu.Game.Overlays.Direct { content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); content.MoveToY(0, hover_transition_time, Easing.OutQuint); - if (FadePlayButton && !PreviewPlaying) + if (FadePlayButton && !PreviewPlaying.Value) PlayButton.FadeOut(120, Easing.InOutQuint); base.OnHoverLost(e); @@ -149,44 +122,16 @@ namespace osu.Game.Overlays.Direct protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo); - private void attachDownload(DownloadBeatmapSetRequest request) - { - if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID) - return; - - progressBar.FadeIn(400, Easing.OutQuint); - progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); - - progressBar.Current.Value = 0; - - request.Failure += e => - { - progressBar.Current.Value = 0; - progressBar.FadeOut(500); - }; - - request.DownloadProgressed += progress => Schedule(() => progressBar.Current.Value = progress); - - request.Success += data => - { - progressBar.Current.Value = 1; - progressBar.FillColour = colours.Yellow; - }; - } - - private void setAdded(BeatmapSetInfo s, bool existing, bool silent) => Schedule(() => - { - if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) - progressBar.FadeOut(500); - }); - protected override void LoadComplete() { base.LoadComplete(); this.FadeInFromZero(200, Easing.Out); - PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); - PreviewPlaying.ValueChanged += newValue => PreviewBar.FadeTo(newValue ? 1 : 0, 120, Easing.InOutQuint); + PreviewPlaying.ValueChanged += playing => + { + PlayButton.FadeTo(playing.NewValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); + PreviewBar.FadeTo(playing.NewValue ? 1 : 0, 120, Easing.InOutQuint); + }; } protected List GetDifficultyIcons() @@ -213,7 +158,7 @@ namespace osu.Game.Overlays.Direct public int Value { - get { return value; } + get => value; set { this.value = value; @@ -231,10 +176,7 @@ namespace osu.Game.Overlays.Direct Children = new Drawable[] { - text = new OsuSpriteText - { - Font = @"Exo2.0-SemiBoldItalic", - }, + text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.SemiBold, italics: true) }, new SpriteIcon { Icon = icon, diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index e326f5e592..f15413d522 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -1,107 +1,118 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osuTK; namespace osu.Game.Overlays.Direct { - public class DownloadButton : OsuAnimatedButton + public class DownloadButton : DownloadTrackingComposite { - private readonly BeatmapSetInfo beatmapSet; + private readonly bool noVideo; private readonly SpriteIcon icon; private readonly SpriteIcon checkmark; - private readonly BeatmapSetDownloader downloader; private readonly Box background; private OsuColour colours; - public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) - { - this.beatmapSet = beatmapSet; + private readonly ShakeContainer shakeContainer; - AddRange(new Drawable[] + private readonly OsuAnimatedButton button; + + public DownloadButton(BeatmapSetInfo beatmapSet, bool noVideo = false) + : base(beatmapSet) + { + this.noVideo = noVideo; + + InternalChild = shakeContainer = new ShakeContainer { - downloader = new BeatmapSetDownloader(beatmapSet, noVideo), - background = new Box + RelativeSizeAxes = Axes.Both, + Child = button = new OsuAnimatedButton { RelativeSizeAxes = Axes.Both, - Depth = float.MaxValue - }, - icon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(13), - Icon = FontAwesome.fa_download, - }, - checkmark = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - X = 8, - Size = Vector2.Zero, - Icon = FontAwesome.fa_check, + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Depth = float.MaxValue + }, + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(13), + Icon = FontAwesome.fa_download, + }, + checkmark = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + X = 8, + Size = Vector2.Zero, + Icon = FontAwesome.fa_check, + } + } } - }); + }; } protected override void LoadComplete() { base.LoadComplete(); - downloader.DownloadState.BindValueChanged(updateState, true); + + State.BindValueChanged(state => updateState(state.NewValue), true); FinishTransforms(true); } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame game) + private void load(OsuColour colours, OsuGame game, BeatmapManager beatmaps) { this.colours = colours; - Action = () => + button.Action = () => { - switch (downloader.DownloadState.Value) + switch (State.Value) { - case BeatmapSetDownloader.DownloadStatus.Downloading: - // todo: replace with ShakeContainer after https://github.com/ppy/osu/pull/2909 is merged. - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); + case DownloadState.Downloading: + case DownloadState.Downloaded: + shakeContainer.Shake(); break; - case BeatmapSetDownloader.DownloadStatus.Downloaded: - game.PresentBeatmap(beatmapSet); + case DownloadState.LocallyAvailable: + game.PresentBeatmap(BeatmapSet.Value); break; default: - downloader.Download(); + beatmaps.Download(BeatmapSet.Value, noVideo); break; } }; } - private void updateState(BeatmapSetDownloader.DownloadStatus state) + private void updateState(DownloadState state) { switch (state) { - case BeatmapSetDownloader.DownloadStatus.NotDownloaded: + case DownloadState.NotDownloaded: background.FadeColour(colours.Gray4, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); break; - case BeatmapSetDownloader.DownloadStatus.Downloading: + case DownloadState.Downloading: background.FadeColour(colours.Blue, 500, Easing.InOutExpo); icon.MoveToX(0, 500, Easing.InOutExpo); checkmark.ScaleTo(Vector2.Zero, 500, Easing.InOutExpo); break; - - case BeatmapSetDownloader.DownloadStatus.Downloaded: + case DownloadState.Downloaded: + background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); + break; + case DownloadState.LocallyAvailable: background.FadeColour(colours.Green, 500, Easing.InOutExpo); icon.MoveToX(-8, 500, Easing.InOutExpo); checkmark.ScaleTo(new Vector2(13), 500, Easing.InOutExpo); diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs new file mode 100644 index 0000000000..9c2b1e5b63 --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Direct +{ + public class DownloadProgressBar : DownloadTrackingComposite + { + private readonly ProgressBar progressBar; + + public DownloadProgressBar(BeatmapSetInfo beatmapSet) + : base(beatmapSet) + { + AddInternal(progressBar = new ProgressBar + { + Height = 0, + Alpha = 0, + }); + + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours) + { + progressBar.FillColour = colours.Blue; + progressBar.BackgroundColour = Color4.Black.Opacity(0.7f); + progressBar.Current = Progress; + + State.BindValueChanged(state => + { + switch (state.NewValue) + { + case DownloadState.NotDownloaded: + progressBar.Current.Value = 0; + progressBar.FadeOut(500); + break; + case DownloadState.Downloading: + progressBar.FadeIn(400, Easing.OutQuint); + progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); + break; + case DownloadState.Downloaded: + progressBar.FadeIn(400, Easing.OutQuint); + progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); + + progressBar.Current.Value = 1; + progressBar.FillColour = colours.Yellow; + break; + case DownloadState.LocallyAvailable: + progressBar.FadeOut(500); + break; + } + }, true); + } + } +} diff --git a/osu.Game/Overlays/Direct/DownloadState.cs b/osu.Game/Overlays/Direct/DownloadState.cs new file mode 100644 index 0000000000..a301c6a3bd --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadState.cs @@ -0,0 +1,13 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Overlays.Direct +{ + public enum DownloadState + { + NotDownloaded, + Downloading, + Downloaded, + LocallyAvailable + } +} diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs new file mode 100644 index 0000000000..37f13aefc8 --- /dev/null +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -0,0 +1,133 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests; + +namespace osu.Game.Overlays.Direct +{ + /// + /// A component which tracks a beatmap through potential download/import/deletion. + /// + public abstract class DownloadTrackingComposite : CompositeDrawable + { + public readonly Bindable BeatmapSet = new Bindable(); + + private BeatmapManager beatmaps; + + /// + /// Holds the current download state of the beatmap, whether is has already been downloaded, is in progress, or is not downloaded. + /// + protected readonly Bindable State = new Bindable(); + + protected readonly Bindable Progress = new Bindable(); + + protected DownloadTrackingComposite(BeatmapSetInfo beatmapSet = null) + { + BeatmapSet.Value = beatmapSet; + } + + [BackgroundDependencyLoader(true)] + private void load(BeatmapManager beatmaps) + { + this.beatmaps = beatmaps; + + BeatmapSet.BindValueChanged(setInfo => + { + if (setInfo.NewValue == null) + attachDownload(null); + else if (beatmaps.GetAllUsableBeatmapSetsEnumerable().Any(s => s.OnlineBeatmapSetID == setInfo.NewValue.OnlineBeatmapSetID)) + State.Value = DownloadState.LocallyAvailable; + else + attachDownload(beatmaps.GetExistingDownload(setInfo.NewValue)); + }, true); + + beatmaps.BeatmapDownloadBegan += download => + { + if (download.BeatmapSet.OnlineBeatmapSetID == BeatmapSet.Value?.OnlineBeatmapSetID) + attachDownload(download); + }; + + beatmaps.ItemAdded += setAdded; + beatmaps.ItemRemoved += setRemoved; + } + + #region Disposal + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmaps != null) + { + beatmaps.BeatmapDownloadBegan -= attachDownload; + beatmaps.ItemAdded -= setAdded; + } + + State.UnbindAll(); + + attachDownload(null); + } + + #endregion + + private DownloadBeatmapSetRequest attachedRequest; + + private void attachDownload(DownloadBeatmapSetRequest request) + { + if (attachedRequest != null) + { + attachedRequest.Failure -= onRequestFailure; + attachedRequest.DownloadProgressed -= onRequestProgress; + attachedRequest.Success -= onRequestSuccess; + } + + attachedRequest = request; + + if (attachedRequest != null) + { + if (attachedRequest.Progress == 1) + { + State.Value = DownloadState.Downloaded; + Progress.Value = 1; + } + else + { + State.Value = DownloadState.Downloading; + Progress.Value = attachedRequest.Progress; + + attachedRequest.Failure += onRequestFailure; + attachedRequest.DownloadProgressed += onRequestProgress; + attachedRequest.Success += onRequestSuccess; + } + } + else + { + State.Value = DownloadState.NotDownloaded; + } + } + + private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Downloaded); + + private void onRequestProgress(float progress) => Schedule(() => Progress.Value = progress); + + private void onRequestFailure(Exception e) => Schedule(() => attachDownload(null)); + + private void setAdded(BeatmapSetInfo s, bool existing) => setDownloadStateFromManager(s, DownloadState.LocallyAvailable); + + private void setRemoved(BeatmapSetInfo s) => setDownloadStateFromManager(s, DownloadState.NotDownloaded); + + private void setDownloadStateFromManager(BeatmapSetInfo s, DownloadState state) => Schedule(() => + { + if (s.OnlineBeatmapSetID != BeatmapSet.Value?.OnlineBeatmapSetID) + return; + + State.Value = state; + }); + } +} diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 3f2c3a4fbf..d7e0760fc6 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Direct { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; - Ruleset.Value = ruleset ?? rulesets.GetRuleset(0); + Ruleset.Value = ruleset.Value ?? rulesets.GetRuleset(0); foreach (var r in rulesets.AvailableRulesets) modeButtons.Add(new RulesetToggleButton(Ruleset, r)); } @@ -68,9 +68,9 @@ namespace osu.Game.Overlays.Direct private readonly ConstrainedIconContainer iconContainer; - private void Bindable_ValueChanged(RulesetInfo obj) + private void Bindable_ValueChanged(ValueChangedEvent e) { - iconContainer.FadeTo(Ruleset.ID == obj?.ID ? 1f : 0.5f, 100); + iconContainer.FadeTo(Ruleset.ID == e.NewValue?.ID ? 1f : 0.5f, 100); } public override bool HandleNonPositionalInput => !bindable.Disabled && base.HandleNonPositionalInput; @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Direct Ruleset = ruleset; bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(bindable.Value); + Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); Action = () => bindable.Value = Ruleset; } diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs index 2ca7b558ba..e85cb3b4ac 100644 --- a/osu.Game/Overlays/Direct/Header.cs +++ b/osu.Game/Overlays/Direct/Header.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; using osuTK.Graphics; @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Direct protected override Color4 BackgroundColour => OsuColour.FromHex(@"252f3a"); protected override DirectTab DefaultTab => DirectTab.Search; - protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", TextSize = 25 }; + protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", Font = OsuFont.GetFont(size: 25) }; protected override FontAwesome Icon => FontAwesome.fa_osu_chevron_down_o; public Header() @@ -28,10 +28,13 @@ namespace osu.Game.Overlays.Direct public enum DirectTab { Search, + [Description("Newest Maps")] NewestMaps = DirectSortCriteria.Ranked, + [Description("Top Rated")] TopRated = DirectSortCriteria.Rating, + [Description("Most Played")] MostPlayed = DirectSortCriteria.Plays, } diff --git a/osu.Game/Overlays/Direct/IconPill.cs b/osu.Game/Overlays/Direct/IconPill.cs index 9ac544ea78..e7f516f449 100644 --- a/osu.Game/Overlays/Direct/IconPill.cs +++ b/osu.Game/Overlays/Direct/IconPill.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,6 +12,14 @@ namespace osu.Game.Overlays.Direct { public class IconPill : CircularContainer { + public Vector2 IconSize + { + get => iconContainer.Size; + set => iconContainer.Size = value; + } + + private readonly Container iconContainer; + public IconPill(FontAwesome icon) { AutoSizeAxes = Axes.Both; @@ -25,16 +33,16 @@ namespace osu.Game.Overlays.Direct Colour = Color4.Black, Alpha = 0.5f, }, - new Container + iconContainer = new Container { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding(5), + Size = new Vector2(22), + Padding = new MarginPadding(5), Child = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, Icon = icon, - Size = new Vector2(12), }, }, }; diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index d9b36e2367..3c5508ba00 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -24,10 +24,11 @@ namespace osu.Game.Overlays.Direct public BeatmapSetInfo BeatmapSet { - get { return beatmapSet; } + get => beatmapSet; set { if (value == beatmapSet) return; + beatmapSet = value; Preview?.Stop(); @@ -112,12 +113,12 @@ namespace osu.Game.Overlays.Direct base.OnHoverLost(e); } - private void playingStateChanged(bool playing) + private void playingStateChanged(ValueChangedEvent e) { - icon.Icon = playing ? FontAwesome.fa_stop : FontAwesome.fa_play; - icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); + icon.Icon = e.NewValue ? FontAwesome.fa_stop : FontAwesome.fa_play; + icon.FadeColour(e.NewValue || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); - if (playing) + if (e.NewValue) { if (BeatmapSet == null) { @@ -144,7 +145,7 @@ namespace osu.Game.Overlays.Direct preview.Stopped += () => Playing.Value = false; // user may have changed their mind. - if (Playing) + if (Playing.Value) preview.Start(); }); } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 765c86e6ad..34edbbcc8b 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; @@ -27,7 +28,7 @@ namespace osu.Game.Overlays { private const float panel_padding = 10f; - private APIAccess api; + private IAPIProvider api; private RulesetStore rulesets; private readonly FillFlowContainer resultCountsContainer; @@ -45,7 +46,7 @@ namespace osu.Game.Overlays public IEnumerable BeatmapSets { - get { return beatmapSets; } + get => beatmapSets; set { if (beatmapSets?.Equals(value) ?? false) return; @@ -72,10 +73,11 @@ namespace osu.Game.Overlays public ResultCounts ResultAmounts { - get { return resultAmounts; } + get => resultAmounts; set { if (value == ResultAmounts) return; + resultAmounts = value; updateResultCounts(); @@ -105,12 +107,11 @@ namespace osu.Game.Overlays new OsuSpriteText { Text = "Found ", - TextSize = 15, + Font = OsuFont.GetFont(size: 15) }, resultCountsText = new OsuSpriteText { - TextSize = 15, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) }, } }, @@ -118,7 +119,7 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (text != string.Empty) + if (text.NewValue != string.Empty) { Header.Tabs.Current.Value = DirectTab.Search; @@ -133,50 +134,37 @@ namespace osu.Game.Overlays Filter.Tabs.Current.Value = DirectSortCriteria.Ranked; } }; - ((FilterControl)Filter).Ruleset.ValueChanged += ruleset => Scheduler.AddOnce(updateSearch); - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + ((FilterControl)Filter).Ruleset.ValueChanged += _ => queueUpdateSearch(); + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => queueUpdateSearch(); Header.Tabs.Current.ValueChanged += tab => { - if (tab != DirectTab.Search) + if (tab.NewValue != DirectTab.Search) { currentQuery.Value = string.Empty; Filter.Tabs.Current.Value = (DirectSortCriteria)Header.Tabs.Current.Value; - Scheduler.AddOnce(updateSearch); + queueUpdateSearch(); } }; - currentQuery.ValueChanged += v => - { - queryChangedDebounce?.Cancel(); - - if (string.IsNullOrEmpty(v)) - Scheduler.AddOnce(updateSearch); - else - { - BeatmapSets = null; - ResultAmounts = null; - - queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - } - }; + currentQuery.ValueChanged += text => queueUpdateSearch(!string.IsNullOrEmpty(text.NewValue)); currentQuery.BindTo(Filter.Search.Current); - Filter.Tabs.Current.ValueChanged += sortCriteria => + Filter.Tabs.Current.ValueChanged += tab => { - if (Header.Tabs.Current.Value != DirectTab.Search && sortCriteria != (DirectSortCriteria)Header.Tabs.Current.Value) + if (Header.Tabs.Current.Value != DirectTab.Search && tab.NewValue != (DirectSortCriteria)Header.Tabs.Current.Value) Header.Tabs.Current.Value = DirectTab.Search; - Scheduler.AddOnce(updateSearch); + queueUpdateSearch(); }; updateResultCounts(); } [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api, RulesetStore rulesets, PreviewTrackManager previewTrackManager) + private void load(OsuColour colours, IAPIProvider api, RulesetStore rulesets, PreviewTrackManager previewTrackManager) { this.api = api; this.rulesets = rulesets; @@ -190,14 +178,9 @@ namespace osu.Game.Overlays resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, Easing.OutQuint); if (ResultAmounts == null) return; - resultCountsText.Text = pluralize("Artist", ResultAmounts.Artists) + ", " + - pluralize("Song", ResultAmounts.Songs) + ", " + - pluralize("Tag", ResultAmounts.Tags); - } - - private string pluralize(string prefix, int value) - { - return $@"{value} {prefix}" + (value == 1 ? string.Empty : @"s"); + resultCountsText.Text = "Artist".ToQuantity(ResultAmounts.Artists) + ", " + + "Song".ToQuantity(ResultAmounts.Songs) + ", " + + "Tag".ToQuantity(ResultAmounts.Tags); } private void recreatePanels(PanelDisplayStyle displayStyle) @@ -246,40 +229,42 @@ namespace osu.Game.Overlays // Queries are allowed to be run only on the first pop-in if (getSetsRequest == null) - Scheduler.AddOnce(updateSearch); + queueUpdateSearch(); } private SearchBeatmapSetsRequest getSetsRequest; - private readonly Bindable currentQuery = new Bindable(); + private readonly Bindable currentQuery = new Bindable(string.Empty); private ScheduledDelegate queryChangedDebounce; private PreviewTrackManager previewTrackManager; + private void queueUpdateSearch(bool queryTextChanged = false) + { + BeatmapSets = null; + ResultAmounts = null; + + getSetsRequest?.Cancel(); + + queryChangedDebounce?.Cancel(); + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100); + } + private void updateSearch() { - queryChangedDebounce?.Cancel(); - if (!IsLoaded) return; if (State == Visibility.Hidden) return; - BeatmapSets = null; - ResultAmounts = null; - - getSetsRequest?.Cancel(); - if (api == null) return; - if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) - return; - previewTrackManager.StopAnyPlaying(this); - getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, + getSetsRequest = new SearchBeatmapSetsRequest( + currentQuery.Value, ((FilterControl)Filter).Ruleset.Value, Filter.DisplayStyleControl.Dropdown.Current.Value, Filter.Tabs.Current.Value); //todo: sort direction (?) diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index b2c1ad20be..154aff605a 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -33,7 +33,7 @@ namespace osu.Game.Overlays } }; - Progress.ValueChanged += v => overlay.Alpha = (float)v; + Progress.ValueChanged += p => overlay.Alpha = (float)p.NewValue; } } } diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index b939483cd8..82e24f550b 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osu.Game.Input.Bindings; @@ -9,7 +9,7 @@ namespace osu.Game.Overlays.KeyBinding { public class GlobalKeyBindingsSection : SettingsSection { - public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override FontAwesome Icon => FontAwesome.fa_globe; public override string Header => "Global"; public GlobalKeyBindingsSection(GlobalActionContainer manager) @@ -18,7 +18,6 @@ namespace osu.Game.Overlays.KeyBinding Add(new InGameKeyBindingsSubsection(manager)); } - private class DefaultBindingsSubsection : KeyBindingsSubsection { protected override string Header => string.Empty; @@ -34,7 +33,8 @@ namespace osu.Game.Overlays.KeyBinding { protected override string Header => "In Game"; - public InGameKeyBindingsSubsection(GlobalActionContainer manager) : base(null) + public InGameKeyBindingsSubsection(GlobalActionContainer manager) + : base(null) { Defaults = manager.InGameKeyBindings; } diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index fe2903d393..ef16c81dfc 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.KeyBinding public bool MatchingFilter { - get { return matchingFilter; } + get => matchingFilter; set { matchingFilter = value; @@ -309,10 +309,11 @@ namespace osu.Game.Overlays.KeyBinding public bool IsBinding { - get { return isBinding; } + get => isBinding; set { if (value == isBinding) return; + isBinding = value; updateHoverState(); @@ -349,8 +350,7 @@ namespace osu.Game.Overlays.KeyBinding }, Text = new OsuSpriteText { - Font = "Venera", - TextSize = 10, + Font = OsuFont.Numeric.With(size: 10), Margin = new MarginPadding(5), Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 9e57b9eefa..53cb3edeca 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs index c4405216e3..7b3bef90c0 100644 --- a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osu.Game.Overlays.Settings; @@ -9,7 +9,7 @@ namespace osu.Game.Overlays.KeyBinding { public class RulesetBindingsSection : SettingsSection { - public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override FontAwesome Icon => (ruleset.CreateInstance().CreateIcon() as SpriteIcon)?.Icon ?? FontAwesome.fa_osu_hot; public override string Header => ruleset.Name; private readonly RulesetInfo ruleset; diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs index 4f33695e5d..07af657686 100644 --- a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 06432cfcea..300563dc59 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -1,12 +1,19 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; +using osu.Framework.Input.Events; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Input.Bindings; using osu.Game.Overlays.KeyBinding; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; +using osu.Game.Screens.Ranking; +using osuTK; namespace osu.Game.Overlays { @@ -21,11 +28,84 @@ namespace osu.Game.Overlays foreach (var ruleset in rulesets.AvailableRulesets) AddSection(new RulesetBindingsSection(ruleset)); + + AddInternal(new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = Hide + }); } public KeyBindingOverlay() - : base(false) + : base(true) { } + + private class BackButton : OsuClickableContainer, IKeyBindingHandler + { + private AspectContainer aspect; + + [BackgroundDependencyLoader] + private void load() + { + Size = new Vector2(Sidebar.DEFAULT_WIDTH); + Children = new Drawable[] + { + aspect = new AspectContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = -15, + Size = new Vector2(15), + Shadow = true, + Icon = FontAwesome.fa_chevron_left + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 15, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = @"back", + }, + } + } + }; + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); + return base.OnMouseDown(e); + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + aspect.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(e); + } + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + Click(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => false; + } } } diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index e094f8ef48..e7caaa3aca 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index cd9cf8d50e..61dd51d16f 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -1,28 +1,19 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input.Bindings; -using osu.Framework.Input.Events; -using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Input.Bindings; using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; -using osu.Game.Screens.Ranking; -using osuTK; using osuTK.Graphics; +using System.Collections.Generic; namespace osu.Game.Overlays { public class MainSettings : SettingsOverlay { private readonly KeyBindingOverlay keyBindingOverlay; - private BackButton backButton; protected override IEnumerable CreateSections() => new SettingsSection[] { @@ -53,8 +44,6 @@ namespace osu.Game.Overlays public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible; - private const float hidden_width = 120; - private void keyBindingOverlay_StateChanged(Visibility visibility) { switch (visibility) @@ -64,9 +53,7 @@ namespace osu.Game.Overlays Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); SectionsContainer.FadeOut(300, Easing.OutQuint); - ContentContainer.MoveToX(hidden_width - WIDTH, 500, Easing.OutQuint); - - backButton.Delay(100).FadeIn(100); + ContentContainer.MoveToX(-WIDTH, 500, Easing.OutQuint); break; case Visibility.Hidden: Background.FadeTo(0.6f, 500, Easing.OutQuint); @@ -74,94 +61,16 @@ namespace osu.Game.Overlays SectionsContainer.FadeIn(500, Easing.OutQuint); ContentContainer.MoveToX(0, 500, Easing.OutQuint); - - backButton.FadeOut(100); break; } } - protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? hidden_width - WIDTH : base.ExpandedPosition; + protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? -WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() { ContentContainer.Add(keyBindingOverlay); - - ContentContainer.Add(backButton = new BackButton - { - Alpha = 0, - Width = hidden_width, - RelativeSizeAxes = Axes.Y, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Action = () => keyBindingOverlay.Hide() - }); - } - - private class BackButton : OsuClickableContainer, IKeyBindingHandler - { - private AspectContainer aspect; - - [BackgroundDependencyLoader] - private void load() - { - Children = new Drawable[] - { - aspect = new AspectContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = -15, - Size = new Vector2(15), - Shadow = true, - Icon = FontAwesome.fa_chevron_left - }, - new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = 15, - TextSize = 12, - Font = @"Exo2.0-Bold", - Text = @"back", - }, - } - } - }; - } - - protected override bool OnMouseDown(MouseDownEvent e) - { - aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); - return base.OnMouseDown(e); - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - aspect.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(e); - } - - public bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - Click(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) => false; } } } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 85875d2052..a5703eba92 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -219,13 +219,11 @@ namespace osu.Game.Overlays { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.Icon; - }) - .Delay(step_duration).Schedule(() => + }).Delay(step_duration).Schedule(() => { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.MedalUnlocked; - }) - .Delay(step_duration).Schedule(() => + }).Delay(step_duration).Schedule(() => { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.Full; diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 87d5724d24..431ae98c2c 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; @@ -29,6 +29,7 @@ namespace osu.Game.Overlays.MedalSplash private readonly OsuSpriteText unlocked, name; private readonly TextFlowContainer description; private DisplayState state; + public DrawableMedal(Medal medal) { this.medal = medal; @@ -63,8 +64,7 @@ namespace osu.Game.Overlays.MedalSplash Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Medal Unlocked".ToUpperInvariant(), - TextSize = 24, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Alpha = 0f, Scale = new Vector2(1f / scale_when_unlocked), }, @@ -84,8 +84,7 @@ namespace osu.Game.Overlays.MedalSplash Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = medal.Name, - TextSize = 20, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), Alpha = 0f, Scale = new Vector2(1f / scale_when_full), }, @@ -107,10 +106,10 @@ namespace osu.Game.Overlays.MedalSplash { s.Anchor = Anchor.TopCentre; s.Origin = Anchor.TopCentre; - s.TextSize = 16; + s.Font = s.Font.With(size: 16); }); - medalContainer.OnLoadComplete = d => + medalContainer.OnLoadComplete += d => { unlocked.Position = new Vector2(0f, medalContainer.DrawSize.Y / 2 + 10); infoFlow.Position = new Vector2(0f, unlocked.Position.Y + 90); @@ -134,7 +133,7 @@ namespace osu.Game.Overlays.MedalSplash public DisplayState State { - get { return state; } + get => state; set { if (state == value) return; diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 239688e284..23b75caedc 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -14,6 +14,7 @@ using System; using System.Linq; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Mods @@ -106,10 +107,11 @@ namespace osu.Game.Overlays.Mods public Color4 SelectedColour { - get { return selectedColour; } + get => selectedColour; set { if (value == selectedColour) return; + selectedColour = value; if (Selected) foregroundIcon.Colour = value; } @@ -120,7 +122,7 @@ namespace osu.Game.Overlays.Mods public Mod Mod { - get { return mod; } + get => mod; set { mod = value; @@ -275,7 +277,7 @@ namespace osu.Game.Overlays.Mods Y = 75, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - TextSize = 18, + Font = OsuFont.GetFont(size: 18) }, new HoverClickSounds() }; diff --git a/osu.Game/Overlays/Mods/ModButtonEmpty.cs b/osu.Game/Overlays/Mods/ModButtonEmpty.cs index dfe14e066e..03afe5adba 100644 --- a/osu.Game/Overlays/Mods/ModButtonEmpty.cs +++ b/osu.Game/Overlays/Mods/ModButtonEmpty.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 8ac98ddff6..a118357f21 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Input; @@ -11,6 +11,7 @@ using System; using System.Linq; using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Graphics; namespace osu.Game.Overlays.Mods { @@ -80,6 +81,7 @@ namespace osu.Game.Overlays.Mods { Mod selected = button.SelectedMod; if (selected == null) continue; + foreach (var type in modTypes) if (type.IsInstanceOfType(selected)) { @@ -123,7 +125,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, Position = new Vector2(0f, 0f), - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold) }, ButtonsContainer = new FillFlowContainer { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 742a3830b4..aa41723ca6 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,21 +16,18 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods.Sections; +using osu.Game.Screens; namespace osu.Game.Overlays.Mods { public class ModSelectOverlay : WaveOverlayContainer { - /// - /// How much this container should overflow the sides of the screen to account for parallax shifting. - /// - private const float overflow_padding = 50; - private const float content_width = 0.8f; protected Color4 LowMultiplierColour, HighMultiplierColour; @@ -42,6 +38,8 @@ namespace osu.Game.Overlays.Mods protected override bool BlockNonPositionalInput => false; + protected override bool DimMainContent => false; + protected readonly FillFlowContainer ModSectionsContainer; protected readonly Bindable> SelectedMods = new Bindable>(new Mod[] { }); @@ -78,28 +76,28 @@ namespace osu.Game.Overlays.Mods SelectedMods.UnbindAll(); } - private void rulesetChanged(RulesetInfo newRuleset) + private void rulesetChanged(ValueChangedEvent e) { - if (newRuleset == null) return; + if (e.NewValue == null) return; - var instance = newRuleset.CreateInstance(); + var instance = e.NewValue.CreateInstance(); foreach (ModSection section in ModSectionsContainer.Children) section.Mods = instance.GetModsFor(section.ModType); // attempt to re-select any already selected mods. // this may be the first time we are receiving the ruleset, in which case they will still match. - selectedModsChanged(SelectedMods.Value); + selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); // write the mods back to the SelectedMods bindable in the case a change was not applicable. // this generally isn't required as the previous line will perform deselection; just here for safety. refreshSelectedMods(); } - private void selectedModsChanged(IEnumerable obj) + private void selectedModsChanged(ValueChangedEvent> e) { foreach (ModSection section in ModSectionsContainer.Children) - section.SelectTypes(obj.Select(m => m.GetType()).ToList()); + section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); updateMods(); } @@ -172,11 +170,11 @@ namespace osu.Game.Overlays.Mods public void DeselectTypes(Type[] modTypes, bool immediate = false) { if (modTypes.Length == 0) return; + foreach (ModSection section in ModSectionsContainer.Children) section.DeselectTypes(modTypes, immediate); } - private SampleChannel sampleOn, sampleOff; private void modButtonPressed(Mod selectedMod) @@ -204,11 +202,7 @@ namespace osu.Game.Overlays.Mods Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); Height = 510; - Padding = new MarginPadding - { - Left = -overflow_padding, - Right = -overflow_padding - }; + Padding = new MarginPadding { Horizontal = -OsuScreen.HORIZONTAL_OVERFLOW_PADDING }; Children = new Drawable[] { @@ -268,18 +262,13 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Width = content_width, - Padding = new MarginPadding - { - Left = overflow_padding, - Right = overflow_padding - }, + Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { new OsuSpriteText { - Font = @"Exo2.0-Bold", Text = @"Gameplay Mods", - TextSize = 22, + Font = OsuFont.GetFont(size: 22, weight: FontWeight.Bold), Shadow = true, Margin = new MarginPadding { @@ -288,7 +277,7 @@ namespace osu.Game.Overlays.Mods }, new OsuTextFlowContainer(text => { - text.TextSize = 18; + text.Font = text.Font.With(size: 18); text.Shadow = true; }) { @@ -313,8 +302,7 @@ namespace osu.Game.Overlays.Mods Padding = new MarginPadding { Vertical = 10, - Left = overflow_padding, - Right = overflow_padding + Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Child = ModSectionsContainer = new FillFlowContainer { @@ -362,8 +350,7 @@ namespace osu.Game.Overlays.Mods Padding = new MarginPadding { Vertical = 15, - Left = overflow_padding, - Right = overflow_padding + Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { @@ -380,7 +367,7 @@ namespace osu.Game.Overlays.Mods new OsuSpriteText { Text = @"Score Multiplier:", - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Margin = new MarginPadding { Top = 5, @@ -389,8 +376,7 @@ namespace osu.Game.Overlays.Mods }, MultiplierLabel = new OsuSpriteText { - Font = @"Exo2.0-Bold", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5 @@ -398,9 +384,8 @@ namespace osu.Game.Overlays.Mods }, UnrankedLabel = new OsuSpriteText { - Font = @"Exo2.0-Bold", Text = @"(Unranked)", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5, diff --git a/osu.Game/Overlays/Mods/Sections/AutomationSection.cs b/osu.Game/Overlays/Mods/Sections/AutomationSection.cs index c14ed270f7..a2d7fec15f 100644 --- a/osu.Game/Overlays/Mods/Sections/AutomationSection.cs +++ b/osu.Game/Overlays/Mods/Sections/AutomationSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; using osuTK.Input; diff --git a/osu.Game/Overlays/Mods/Sections/ConversionSection.cs b/osu.Game/Overlays/Mods/Sections/ConversionSection.cs index 90ff879265..24fd8c30dd 100644 --- a/osu.Game/Overlays/Mods/Sections/ConversionSection.cs +++ b/osu.Game/Overlays/Mods/Sections/ConversionSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; using osuTK.Input; diff --git a/osu.Game/Overlays/Mods/Sections/DifficultyIncreaseSection.cs b/osu.Game/Overlays/Mods/Sections/DifficultyIncreaseSection.cs index f1b7edf98b..0b7ccd1f25 100644 --- a/osu.Game/Overlays/Mods/Sections/DifficultyIncreaseSection.cs +++ b/osu.Game/Overlays/Mods/Sections/DifficultyIncreaseSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; using osuTK.Input; diff --git a/osu.Game/Overlays/Mods/Sections/DifficultyReductionSection.cs b/osu.Game/Overlays/Mods/Sections/DifficultyReductionSection.cs index 8ab9251431..508e92508b 100644 --- a/osu.Game/Overlays/Mods/Sections/DifficultyReductionSection.cs +++ b/osu.Game/Overlays/Mods/Sections/DifficultyReductionSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; using osuTK.Input; diff --git a/osu.Game/Overlays/Mods/Sections/FunSection.cs b/osu.Game/Overlays/Mods/Sections/FunSection.cs index 29329f9c1d..af1f5836b1 100644 --- a/osu.Game/Overlays/Mods/Sections/FunSection.cs +++ b/osu.Game/Overlays/Mods/Sections/FunSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; using osuTK.Input; diff --git a/osu.Game/Overlays/Music/CollectionsDropdown.cs b/osu.Game/Overlays/Music/CollectionsDropdown.cs index 7b2f81b60c..aa93e349e8 100644 --- a/osu.Game/Overlays/Music/CollectionsDropdown.cs +++ b/osu.Game/Overlays/Music/CollectionsDropdown.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index 598b99b9a6..99017579a2 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -1,14 +1,14 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osuTK; -using osuTK.Graphics; using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Music { @@ -45,7 +45,7 @@ namespace osu.Game.Overlays.Music Search.Current.ValueChanged += current_ValueChanged; } - private void current_ValueChanged(string newValue) => FilterChanged?.Invoke(newValue); + private void current_ValueChanged(ValueChangedEvent e) => FilterChanged?.Invoke(e.NewValue); public Action ExitRequested; @@ -53,22 +53,16 @@ namespace osu.Game.Overlays.Music public class FilterTextBox : SearchTextBox { - private Color4 backgroundColour; - - protected override Color4 BackgroundUnfocused => backgroundColour; - protected override Color4 BackgroundFocused => backgroundColour; protected override bool AllowCommit => true; - public FilterTextBox() + [BackgroundDependencyLoader] + private void load() { Masking = true; CornerRadius = 5; - } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - backgroundColour = colours.Gray2; + BackgroundUnfocused = OsuColour.Gray(0.06f); + BackgroundFocused = OsuColour.Gray(0.12f); } } } diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 9368bee81c..886a202c2a 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -50,12 +50,14 @@ namespace osu.Game.Overlays.Music } private bool selected; + public bool Selected { - get { return selected; } + get => selected; set { if (value == selected) return; + selected = value; FinishTransforms(true); @@ -100,7 +102,7 @@ namespace osu.Game.Overlays.Music titleBind = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title))); artistBind = localisation.GetLocalisedString(new LocalisedString((metadata.ArtistUnicode, metadata.Artist))); - artistBind.BindValueChanged(newText => recreateText(), true); + artistBind.BindValueChanged(_ => recreateText(), true); } private void recreateText() @@ -108,16 +110,11 @@ namespace osu.Game.Overlays.Music text.Clear(); //space after the title to put a space between the title and artist - titleSprites = text.AddText(titleBind.Value + @" ", sprite => - { - sprite.TextSize = 16; - sprite.Font = @"Exo2.0-Regular"; - }).OfType(); + titleSprites = text.AddText(titleBind.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)).OfType(); text.AddText(artistBind.Value, sprite => { - sprite.TextSize = 14; - sprite.Font = @"Exo2.0-Bold"; + sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); sprite.Colour = artistColour; sprite.Padding = new MarginPadding { Top = 1 }; }); @@ -147,7 +144,7 @@ namespace osu.Game.Overlays.Music public bool MatchingFilter { - get { return matching; } + get => matching; set { if (matching == value) return; @@ -169,6 +166,8 @@ namespace osu.Game.Overlays.Music Alpha = 0f; Margin = new MarginPadding { Left = 5, Top = 2 }; } + + public override bool HandlePositionalInput => IsPresent; } } diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index b619abbc2f..7846e31725 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -34,8 +34,8 @@ namespace osu.Game.Overlays.Music public new MarginPadding Padding { - get { return base.Padding; } - set { base.Padding = value; } + get => base.Padding; + set => base.Padding = value; } public BeatmapSetInfo FirstVisibleSet => items.FirstVisibleSet; @@ -73,9 +73,9 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap) + private void load(BeatmapManager beatmaps, IBindable beatmap) { - beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false, false)); + beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false)); beatmaps.ItemAdded += addBeatmapSet; beatmaps.ItemRemoved += removeBeatmapSet; @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj, bool existing, bool silent) => Schedule(() => + private void addBeatmapSet(BeatmapSetInfo obj, bool existing) => Schedule(() => { if (existing) return; @@ -109,8 +109,8 @@ namespace osu.Game.Overlays.Music public string SearchTerm { - get { return search.SearchTerm; } - set { search.SearchTerm = value; } + get => search.SearchTerm; + set => search.SearchTerm = value; } public BeatmapSetInfo FirstVisibleSet => items.FirstOrDefault(i => i.MatchingFilter)?.BeatmapSetInfo; @@ -130,6 +130,7 @@ namespace osu.Game.Overlays.Music nativeDragPosition = e.ScreenSpaceMousePosition; if (draggedItem == null) return base.OnDrag(e); + return true; } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 6c45c63145..8cbea63fe3 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Music private PlaylistList list; [BackgroundDependencyLoader] - private void load(OsuColour colours, BindableBeatmap beatmap, BeatmapManager beatmaps) + private void load(OsuColour colours, Bindable beatmap, BeatmapManager beatmaps) { this.beatmap.BindTo(beatmap); this.beatmaps = beatmaps; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Music protected override void PopIn() { filter.Search.HoldFocus = true; - Schedule(() => GetContainingInputManager().ChangeFocus(filter.Search)); + Schedule(() => filter.Search.TakeFocus()); this.ResizeTo(new Vector2(1, playlist_height), transition_duration, Easing.OutQuint); this.FadeIn(transition_duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 2dc997d5ed..c1b742e4e5 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -66,7 +66,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(BindableBeatmap beatmap, BeatmapManager beatmaps, OsuColour colours) + private void load(Bindable beatmap, BeatmapManager beatmaps, OsuColour colours) { this.beatmap.BindTo(beatmap); this.beatmaps = beatmaps; @@ -107,20 +107,18 @@ namespace osu.Game.Overlays Origin = Anchor.BottomCentre, Anchor = Anchor.TopCentre, Position = new Vector2(0, 40), - TextSize = 25, + Font = OsuFont.GetFont(size: 25, italics: true), Colour = Color4.White, Text = @"Nothing to play", - Font = @"Exo2.0-MediumItalic" }, artist = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Position = new Vector2(0, 45), - TextSize = 15, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold, italics: true), Colour = Color4.White, Text = @"Nothing to play", - Font = @"Exo2.0-BoldItalic" }, new Container { @@ -214,7 +212,7 @@ namespace osu.Game.Overlays beatmapSets.Insert(index, beatmapSetInfo); } - private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing, bool silent) + private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing) { if (existing) return; @@ -260,9 +258,6 @@ namespace osu.Game.Overlays progressBar.CurrentTime = track.CurrentTime; playButton.Icon = track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o; - - if (track.HasCompleted && !track.Looping && !beatmap.Disabled && beatmapSets.Any()) - next(); } else { @@ -317,13 +312,13 @@ namespace osu.Game.Overlays private WorkingBeatmap current; private TransformDirection? queuedDirection; - private void beatmapChanged(WorkingBeatmap beatmap) + private void beatmapChanged(ValueChangedEvent beatmap) { TransformDirection direction = TransformDirection.None; if (current != null) { - bool audioEquals = beatmap?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; + bool audioEquals = beatmap.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; if (audioEquals) direction = TransformDirection.None; @@ -336,13 +331,18 @@ namespace osu.Game.Overlays { //figure out the best direction based on order in playlist. var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count(); + var next = beatmap.NewValue == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } + + current.Track.Completed -= currentTrackCompleted; } - current = beatmap; + current = beatmap.NewValue; + + if (current != null) + current.Track.Completed += currentTrackCompleted; progressBar.CurrentTime = 0; @@ -351,6 +351,12 @@ namespace osu.Game.Overlays queuedDirection = null; } + private void currentTrackCompleted() => Schedule(() => + { + if (!current.Track.Looping && !beatmap.Disabled && beatmapSets.Any()) + next(); + }); + private ScheduledDelegate pendingBeatmapSwitch; private void updateDisplay(WorkingBeatmap beatmap, TransformDirection direction) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index b9c5151e26..8f75d3ebf0 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Threading; namespace osu.Game.Overlays @@ -78,9 +78,10 @@ namespace osu.Game.Overlays } private ScheduledDelegate notificationsEnabler; + private void updateProcessingMode() { - bool enabled = OverlayActivationMode == OverlayActivation.All || State == Visibility.Visible; + bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State == Visibility.Visible; notificationsEnabler?.Cancel(); @@ -118,8 +119,7 @@ namespace osu.Game.Overlays notification.Closed += notificationClosed; - var hasCompletionTarget = notification as IHasCompletionTarget; - if (hasCompletionTarget != null) + if (notification is IHasCompletionTarget hasCompletionTarget) hasCompletionTarget.CompletionTarget = Post; var ourType = notification.GetType(); diff --git a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs index 6b91f50aa0..603f53cb53 100644 --- a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs +++ b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index ad20e6cd01..ea6e250556 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -151,6 +151,7 @@ namespace osu.Game.Overlays.Notifications public virtual void Close() { if (WasClosed) return; + WasClosed = true; Closed?.Invoke(); @@ -205,7 +206,7 @@ namespace osu.Game.Overlays.Notifications public bool Pulsate { - get { return pulsate; } + get => pulsate; set { if (pulsate == value) return; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 6958835f03..4608d78324 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Notifications public string ClearText { - get { return clearText; } + get => clearText; set { clearText = value; @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Notifications public string Title { - get { return title; } + get => title; set { title = value; @@ -102,13 +102,13 @@ namespace osu.Game.Overlays.Notifications titleText = new OsuSpriteText { Text = title.ToUpperInvariant(), - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black) }, countText = new OsuSpriteText { Text = "3", Colour = colours.Yellow, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black) }, } }, @@ -153,8 +153,8 @@ namespace osu.Game.Overlays.Notifications public string Text { - get { return text.Text; } - set { text.Text = value.ToUpperInvariant(); } + get => text.Text; + set => text.Text = value.ToUpperInvariant(); } } diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index 0711e49608..f4807b00a8 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 56342ea4c4..75e70b18ea 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -17,18 +17,15 @@ namespace osu.Game.Overlays.Notifications { public string Text { - set - { - Schedule(() => textDrawable.Text = value); - } + set => Schedule(() => textDrawable.Text = value); } public string CompletionText { get; set; } = "Task has completed!"; public float Progress { - get { return progressBar.Progress; } - set { Schedule(() => progressBar.Progress = value); } + get => progressBar.Progress; + set => Schedule(() => progressBar.Progress = value); } protected override void LoadComplete() @@ -41,9 +38,8 @@ namespace osu.Game.Overlays.Notifications public virtual ProgressNotificationState State { - get { return state; } - set - { + get => state; + set => Schedule(() => { bool stateChanged = state != value; @@ -82,7 +78,6 @@ namespace osu.Game.Overlays.Notifications } } }); - } } private ProgressNotificationState state; @@ -115,10 +110,7 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.Both, }); - Content.Add(textDrawable = new OsuTextFlowContainer(t => - { - t.TextSize = 16; - }) + Content.Add(textDrawable = new OsuTextFlowContainer { Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, @@ -181,9 +173,10 @@ namespace osu.Game.Overlays.Notifications private Color4 colourInactive; private float progress; + public float Progress { - get { return progress; } + get => progress; set { if (progress == value) return; @@ -197,7 +190,7 @@ namespace osu.Game.Overlays.Notifications public bool Active { - get { return active; } + get => active; set { active = value; diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index d0f49a74c0..aee056b63d 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -15,9 +15,10 @@ namespace osu.Game.Overlays.Notifications public class SimpleNotification : Notification { private string text = string.Empty; + public string Text { - get { return text; } + get => text; set { text = value; @@ -26,9 +27,10 @@ namespace osu.Game.Overlays.Notifications } private FontAwesome icon = FontAwesome.fa_info_circle; + public FontAwesome Icon { - get { return icon; } + get => icon; set { icon = value; @@ -59,7 +61,7 @@ namespace osu.Game.Overlays.Notifications } }); - Content.Add(textDrawable = new OsuTextFlowContainer(t => t.TextSize = 14) + Content.Add(textDrawable = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 14)) { Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, @@ -76,11 +78,7 @@ namespace osu.Game.Overlays.Notifications public override bool Read { - get - { - return base.Read; - } - + get => base.Read; set { if (value == base.Read) return; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 9cf42c3a29..5e45fbf081 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -69,16 +69,14 @@ namespace osu.Game.Overlays textLine1 = new OsuSpriteText { Padding = new MarginPadding(10), - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), Spacing = new Vector2(1, 0), - TextSize = 14, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, textLine2 = new OsuSpriteText { - TextSize = 24, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Padding = new MarginPadding { Left = 10, Right = 10 }, Anchor = Anchor.Centre, Origin = Anchor.BottomCentre, @@ -105,8 +103,7 @@ namespace osu.Game.Overlays Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Bottom = 15 }, - Font = @"Exo2.0-Bold", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Alpha = 0.3f, }, } @@ -161,7 +158,7 @@ namespace osu.Game.Overlays if (configManager == null) throw new ArgumentNullException(nameof(configManager)); if (!trackedConfigManagers.TryGetValue((source, configManager), out var existing)) - throw new InvalidOperationException($"{nameof(configManager)} is not registered."); + return; existing.Unload(); existing.SettingChanged -= display; diff --git a/osu.Game/Overlays/OverlayActivation.cs b/osu.Game/Overlays/OverlayActivation.cs index da4e153ce9..68d7ee8ea9 100644 --- a/osu.Game/Overlays/OverlayActivation.cs +++ b/osu.Game/Overlays/OverlayActivation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Overlays { diff --git a/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs b/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs index 11ee329f33..93f08768f7 100644 --- a/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs +++ b/osu.Game/Overlays/Profile/Components/DrawableJoinDate.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Profile/Components/GradeBadge.cs b/osu.Game/Overlays/Profile/Components/GradeBadge.cs index 14a47e8d03..ca56780663 100644 --- a/osu.Game/Overlays/Profile/Components/GradeBadge.cs +++ b/osu.Game/Overlays/Profile/Components/GradeBadge.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Profile.Components @@ -36,8 +37,7 @@ namespace osu.Game.Overlays.Profile.Components { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - TextSize = 14, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }); } diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index 06fef22309..ff4d7a10dc 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -53,11 +53,10 @@ namespace osu.Game.Overlays.Profile.Header { badgeCountText = new OsuSpriteText { - Alpha = 0, - TextSize = 12, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Font = "Exo2.0-Regular" + Alpha = 0, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular) }, new Container { diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index f74c8b5069..3df0677576 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -44,30 +44,26 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "No recent plays", - TextSize = 14, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Regular, italics: true) }, rankText = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = primary_textsize + Font = OsuFont.GetFont(size: primary_textsize, weight: FontWeight.Regular, italics: true), }, relativeText = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: secondary_textsize, weight: FontWeight.Regular, italics: true), Y = 25, - TextSize = secondary_textsize }, performanceText = new OsuSpriteText { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = secondary_textsize + Font = OsuFont.GetFont(size: secondary_textsize, weight: FontWeight.Regular, italics: true) }, graph = new RankChartLineGraph { @@ -91,11 +87,11 @@ namespace osu.Game.Overlays.Profile.Header graph.Colour = colours.Yellow; } - private void userChanged(User user) + private void userChanged(ValueChangedEvent e) { placeholder.FadeIn(fade_duration, Easing.Out); - if (user?.Statistics?.Ranks.Global == null) + if (e.NewValue?.Statistics?.Ranks.Global == null) { rankText.Text = string.Empty; performanceText.Text = string.Empty; @@ -105,7 +101,7 @@ namespace osu.Game.Overlays.Profile.Header return; } - int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Ranks.Global.Value }; + int[] userRanks = e.NewValue.RankHistory?.Data ?? new[] { e.NewValue.Statistics.Ranks.Global.Value }; ranks = userRanks.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray(); if (ranks.Length > 1) @@ -144,6 +140,7 @@ namespace osu.Game.Overlays.Profile.Header graph.UpdateBallPosition(e.MousePosition.X); graph.ShowBall(); } + return base.OnHover(e); } diff --git a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs index 1325ea4e9a..722c9c9af2 100644 --- a/osu.Game/Overlays/Profile/Header/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/SupporterIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -23,35 +23,35 @@ namespace osu.Game.Overlays.Profile.Header Masking = true; Children = new Drawable[] { - new Box { RelativeSizeAxes = Axes.Both }, - new CircularContainer + new Box { RelativeSizeAxes = Axes.Both }, + new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Scale = new Vector2(0.8f), + Masking = true, + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0.8f), - Masking = true, - Children = new Drawable[] + background = new Box { RelativeSizeAxes = Axes.Both }, + new Triangles { - background = new Box { RelativeSizeAxes = Axes.Both }, - new Triangles - { - TriangleScale = 0.2f, - ColourLight = OsuColour.FromHex(@"ff7db7"), - ColourDark = OsuColour.FromHex(@"de5b95"), - RelativeSizeAxes = Axes.Both, - Velocity = 0.3f, - }, - } - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.fa_heart, - Scale = new Vector2(0.45f), + TriangleScale = 0.2f, + ColourLight = OsuColour.FromHex(@"ff7db7"), + ColourDark = OsuColour.FromHex(@"de5b95"), + RelativeSizeAxes = Axes.Both, + Velocity = 0.3f, + }, } + }, + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.fa_heart, + Scale = new Vector2(0.45f), + } }; } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 90f4e5851d..c41d977701 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -19,6 +19,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Profile.Components; using osu.Game.Overlays.Profile.Header; using osu.Game.Users; +using Humanizer; namespace osu.Game.Overlays.Profile { @@ -118,8 +119,7 @@ namespace osu.Game.Overlays.Profile usernameText = new OsuSpriteText { Text = user.Username, - Font = @"Exo2.0-RegularItalic", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, italics: true) }, new ExternalLinkButton($@"https://osu.ppy.sh/users/{user.Id}") { @@ -166,7 +166,7 @@ namespace osu.Game.Overlays.Profile Y = cover_height, Colour = OsuColour.Gray(34), }, - infoTextLeft = new LinkFlowContainer(t => t.TextSize = 14) + infoTextLeft = new LinkFlowContainer(t => t.Font = t.Font.With(size: 14)) { X = UserProfileOverlay.CONTENT_X_MARGIN, Y = cover_height + 20, @@ -175,11 +175,7 @@ namespace osu.Game.Overlays.Profile ParagraphSpacing = 0.8f, LineSpacing = 0.2f }, - infoTextRight = new LinkFlowContainer(t => - { - t.TextSize = 14; - t.Font = @"Exo2.0-RegularItalic"; - }) + infoTextRight = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Regular, italics: true)) { X = UserProfileOverlay.CONTENT_X_MARGIN + info_width + 20, Y = cover_height + 20, @@ -222,7 +218,7 @@ namespace osu.Game.Overlays.Profile Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Y = 11, - TextSize = 20 + Font = OsuFont.GetFont(size: 20) } } }, @@ -323,7 +319,7 @@ namespace osu.Game.Overlays.Profile public User User { - get { return user; } + get => user; set { user = value; @@ -339,9 +335,12 @@ namespace osu.Game.Overlays.Profile Anchor = Anchor.Centre, Origin = Anchor.Centre, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(200), Depth = float.MaxValue, - }, coverContainer.Add); + }, background => + { + coverContainer.Add(background); + background.FadeInFromZero(200); + }); if (user.IsSupporter) SupporterTag.Show(); @@ -354,19 +353,18 @@ namespace osu.Game.Overlays.Profile colourBar.Show(); } - void boldItalic(SpriteText t) => t.Font = @"Exo2.0-BoldItalic"; + void boldItalic(SpriteText t) => t.Font = t.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true); void lightText(SpriteText t) => t.Alpha = 0.8f; OsuSpriteText createScoreText(string text) => new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = text }; OsuSpriteText createScoreNumberText(string text) => new OsuSpriteText { - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Text = text @@ -407,7 +405,7 @@ namespace osu.Game.Overlays.Profile infoTextLeft.NewLine(); infoTextLeft.AddText("Contributed ", lightText); - infoTextLeft.AddLink($@"{user.PostCount} forum posts", url: $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: boldItalic); + infoTextLeft.AddLink("forum post".ToQuantity(user.PostCount), url: $"https://osu.ppy.sh/users/{user.Id}/posts", creationParameters: boldItalic); string websiteWithoutProtcol = user.Website; if (!string.IsNullOrEmpty(websiteWithoutProtcol)) diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 1aa43feb8c..6da736432f 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,7 +10,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK.Graphics; -using osu.Framework.Configuration; namespace osu.Game.Overlays.Profile { @@ -35,8 +35,7 @@ namespace osu.Game.Overlays.Profile new OsuSpriteText { Text = Title, - TextSize = 20, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, @@ -67,8 +66,6 @@ namespace osu.Game.Overlays.Profile Add(new OsuSpriteText { Text = @"coming soon!", - TextSize = 16, - Font = @"Exo2.0-Medium", Colour = Color4.Gray, Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Profile/Sections/AboutSection.cs b/osu.Game/Overlays/Profile/Sections/AboutSection.cs index ba3ab80a0c..1bc01cfd9e 100644 --- a/osu.Game/Overlays/Profile/Sections/AboutSection.cs +++ b/osu.Game/Overlays/Profile/Sections/AboutSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Overlays.Profile.Sections { diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 4278598bf5..bb55816880 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -46,17 +47,16 @@ namespace osu.Game.Overlays.Profile.Sections { new OsuSpriteText { - Text = new LocalisedString(($"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", - $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), - TextSize = 15, - Font = "Exo2.0-SemiBoldItalic", + Text = new LocalisedString(( + $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", + $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), + Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - TextSize = 12, Padding = new MarginPadding { Top = 3 }, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) }, }, }; diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 195269d427..0fc1398f5d 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 367d096c16..ae91837d29 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Online.API.Requests; using osu.Game.Overlays.Profile.Sections.Beatmaps; diff --git a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs index 3aefce39dc..a93fefdd75 100644 --- a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs +++ b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs index bc0f22f4d0..b0609e685e 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; @@ -47,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical new OsuSpriteText { Text = @"mapped by ", - TextSize = 12, + Font = OsuFont.GetFont(size: 12) }, mapperContainer = new OsuHoverContainer { @@ -57,8 +58,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical new OsuSpriteText { Text = beatmap.Metadata.AuthorString, - TextSize = 12, - Font = @"Exo2.0-MediumItalic" + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Medium, italics: true) } } }, @@ -78,16 +78,14 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Text = playCount.ToString(), - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic" + Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold, italics: true) }, new OsuSpriteText { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Text = @"times played ", - TextSize = 12, - Font = @"Exo2.0-RegularItalic" + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) }, } }); diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index ad886c363b..f2eb32c53b 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical private GetUserMostPlayedBeatmapsRequest request; public PaginatedMostPlayedBeatmapContainer(Bindable user) - :base(user, "Most Played Beatmaps", "No records. :(") + : base(user, "Most Played Beatmaps", "No records. :(") { ItemsPerPage = 5; @@ -49,7 +49,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Api.Queue(request); } - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs index 924b27a86d..4bdd25ee66 100644 --- a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs +++ b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 5207aa6528..3c69082e9d 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -63,10 +63,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } }; - this.user.ValueChanged += newUser => + this.user.ValueChanged += u => { - total.Count = newUser?.Kudosu.Total ?? 0; - avaliable.Count = newUser?.Kudosu.Available ?? 0; + total.Count = u.NewValue?.Kudosu.Total ?? 0; + avaliable.Count = u.NewValue?.Kudosu.Available ?? 0; }; } @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu public new int Count { - set { valueText.Text = value.ToString(); } + set => valueText.Text = value.ToString(); } public CountSection(string header, string description) @@ -107,21 +107,19 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Text = header + ":", - TextSize = 20, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true) }, valueText = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Text = "0", - TextSize = 40, + Font = OsuFont.GetFont(size: 40, weight: FontWeight.Regular, italics: true), UseFullGlyphHeight = false, - Font = @"Exo2.0-RegularItalic" } } }, - new OsuTextFlowContainer(t => { t.TextSize = 19; }) + new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 19)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index 1490a4bda7..a17b68933c 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Overlays.Profile.Sections.Kudosu; diff --git a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs index 45be08b292..575a2f2c19 100644 --- a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Overlays.Profile.Sections { diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 40da95c30b..46c65b9db7 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -27,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections protected readonly Bindable User = new Bindable(); - protected APIAccess Api; + protected IAPIProvider Api; protected APIRequest RetrievalRequest; protected RulesetStore Rulesets; @@ -43,9 +44,8 @@ namespace osu.Game.Overlays.Profile.Sections { new OsuSpriteText { - TextSize = 15, Text = header, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Top = 10, Bottom = 10 }, }, ItemsContainer = new FillFlowContainer @@ -63,9 +63,9 @@ namespace osu.Game.Overlays.Profile.Sections Origin = Anchor.TopCentre, Child = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = "show more", - Padding = new MarginPadding {Vertical = 10, Horizontal = 15 }, + Padding = new MarginPadding { Vertical = 10, Horizontal = 15 }, } }, ShowMoreLoading = new LoadingAnimation @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Profile.Sections }, MissingText = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = missing, Alpha = 0, }, @@ -84,7 +84,7 @@ namespace osu.Game.Overlays.Profile.Sections } [BackgroundDependencyLoader] - private void load(APIAccess api, RulesetStore rulesets) + private void load(IAPIProvider api, RulesetStore rulesets) { Api = api; Rulesets = rulesets; @@ -93,13 +93,13 @@ namespace osu.Game.Overlays.Profile.Sections User.TriggerChange(); } - private void onUserChanged(User newUser) + private void onUserChanged(ValueChangedEvent e) { VisiblePages = 0; ItemsContainer.Clear(); ShowMoreButton.Hide(); - if (newUser != null) + if (e.NewValue != null) ShowMore(); } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index 98a4bdba45..843f9b7ef2 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -28,8 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Text = $"{pp:0}pp", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 18, - Font = "Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }); if (weight.HasValue) @@ -40,8 +39,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, - TextSize = 11, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Regular, italics: true) }); } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 18aa684664..f4e08b8db1 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -46,8 +46,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, - TextSize = 11, - Font = "Exo2.0-RegularItalic" + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Regular, italics: true) }; RightFlowContainer.Add(text); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index a48468e4e5..8bfca08fe7 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; @@ -23,8 +24,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Text = Score.TotalScore.ToString("#,###"), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 18, - Font = "Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }); } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 1df07070a1..95a18ccfa9 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; @@ -9,6 +8,7 @@ using osu.Game.Users; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Profile.Sections.Ranks { diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs index f67d333a0f..1ce04effa8 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index 965f668a68..c4b933593e 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index 8b4fb1a229..8fab29e42c 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { public class DrawableRecentActivity : DrawableProfileRow { - private APIAccess api; + private IAPIProvider api; private readonly APIRecentActivity activity; @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent RightFlowContainer.Add(new DrawableDate(activity.CreatedAt) { - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Colour = OsuColour.Gray(0xAA), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 45569271df..56ff4d4dec 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index fd5eda4e44..4b4acb8fbc 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Users; using System.Linq; +using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections.Recent diff --git a/osu.Game/Overlays/Profile/Sections/RecentSection.cs b/osu.Game/Overlays/Profile/Sections/RecentSection.cs index fdccd00bac..8fcc5cc7c0 100644 --- a/osu.Game/Overlays/Profile/Sections/RecentSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RecentSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Overlays.Profile.Sections.Recent; diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs index 35888bee73..f55e5f8c59 100644 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osuTK; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -78,13 +78,13 @@ namespace osu.Game.Overlays.SearchableList }; bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(bindable.Value); + Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); Action = () => bindable.Value = this.style; } - private void Bindable_ValueChanged(PanelDisplayStyle style) + private void Bindable_ValueChanged(ValueChangedEvent e) { - icon.FadeTo(style == this.style ? 1.0f : 0.5f, 100); + icon.FadeTo(e.NewValue == style ? 1.0f : 0.5f, 100); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs index 07f1714e2c..2087a72c54 100644 --- a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs +++ b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics.UserInterface; @@ -19,9 +19,10 @@ namespace osu.Game.Overlays.SearchableList private class HeaderTabItem : OsuTabItem { - public HeaderTabItem(T value) : base(value) + public HeaderTabItem(T value) + : base(value) { - Text.TextSize = 16; + Text.Font = Text.Font.With(size: 16); } } } diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index bd03ff9734..b0a8a0e77d 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK.Graphics; @@ -28,6 +28,11 @@ namespace osu.Game.Overlays.SearchableList protected abstract T DefaultTab { get; } protected virtual Drawable CreateSupplementaryControls() => null; + /// + /// The amount of padding added to content (does not affect background or tab control strip). + /// + protected virtual float ContentHorizontalPadding => SearchableListOverlay.WIDTH_PADDING; + protected SearchableListFilterControl() { if (!typeof(T).IsEnum) @@ -62,7 +67,11 @@ namespace osu.Game.Overlays.SearchableList { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = padding, Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Padding = new MarginPadding + { + Top = padding, + Horizontal = ContentHorizontalPadding + }, Children = new Drawable[] { Search = new FilterSearchTextBox @@ -118,16 +127,13 @@ namespace osu.Game.Overlays.SearchableList private class FilterSearchTextBox : SearchTextBox { - protected override Color4 BackgroundUnfocused => backgroundColour; - protected override Color4 BackgroundFocused => backgroundColour; protected override bool AllowCommit => true; - private Color4 backgroundColour; - [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - backgroundColour = colours.Gray2.Opacity(0.9f); + BackgroundUnfocused = OsuColour.Gray(0.06f); + BackgroundFocused = OsuColour.Gray(0.12f); } } } diff --git a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs index 312197c7ae..afdbe33adb 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 2c97cbeb40..87c369e246 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics; @@ -103,7 +103,7 @@ namespace osu.Game.Overlays.SearchableList protected override void OnFocus(FocusEvent e) { - GetContainingInputManager().ChangeFocus(Filter.Search); + Filter.Search.TakeFocus(); } protected override void PopIn() diff --git a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs index 4c7f3e1c31..f320ef1344 100644 --- a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs +++ b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs index 9eb68b416a..c02db40eca 100644 --- a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs +++ b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs index 60a1c7c125..a16e852902 100644 --- a/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/RulesetSettingsSubsection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Rulesets; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index ad79024f62..7f7545eee3 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 35f0a19796..4e43caff23 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index da96c6ef30..aaa4302553 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index fa4a714ba3..0124f7090e 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index d9326b686f..dfb24a08ae 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index b14a4b8773..8ed196fd01 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Runtime; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -34,8 +35,8 @@ namespace osu.Game.Overlays.Settings.Sections.Debug }; configLatencyMode = config.GetBindable(DebugSetting.ActiveGCMode); - configLatencyMode.BindValueChanged(v => latencyMode.Value = (LatencyMode)v, true); - latencyMode.BindValueChanged(v => configLatencyMode.Value = (GCLatencyMode)v); + configLatencyMode.BindValueChanged(mode => latencyMode.Value = (LatencyMode)mode.NewValue, true); + latencyMode.BindValueChanged(mode => configLatencyMode.Value = (GCLatencyMode)mode.NewValue); } private enum LatencyMode diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index 8b09a2a26a..b671d0e0fd 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 0502e98192..441ee12f0d 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 21d5d452bf..997d1354b3 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a9cefa81da..2cf14f5aff 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index 235ff0f319..3e2272dba6 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index f565ff8556..bf4034d641 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index 977d75079b..236bfbecc3 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 163eced103..d6738250f9 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.General public bool Bounding { - get { return bounding; } + get => bounding; set { bounding = value; @@ -58,14 +58,14 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, APIAccess api) + private void load(OsuColour colours, IAPIProvider api) { this.colours = colours; api?.Register(this); } - public void APIStateChanged(APIAccess api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) { form = null; @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Text = "ACCOUNT", Margin = new MarginPadding { Bottom = 5 }, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black), }, form = new LoginForm { @@ -134,8 +134,7 @@ namespace osu.Game.Overlays.Settings.Sections.General Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Signed in", - TextSize = 18, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, }, @@ -152,9 +151,9 @@ namespace osu.Game.Overlays.Settings.Sections.General panel.Status.BindTo(api.LocalUser.Value.Status); - dropdown.Current.ValueChanged += newValue => + dropdown.Current.ValueChanged += action => { - switch (newValue) + switch (action.NewValue) { case UserAction.Online: api.LocalUser.Value.Status.Value = new UserStatusOnline(); @@ -195,7 +194,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { private TextBox username; private TextBox password; - private APIAccess api; + private IAPIProvider api; public Action RequestHide; @@ -206,7 +205,7 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, OsuConfigManager config, AccountCreationOverlay accountCreation) + private void load(IAPIProvider api, OsuConfigManager config, AccountCreationOverlay accountCreation) { this.api = api; Direction = FillDirection.Vertical; @@ -278,6 +277,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { var h = Header as UserDropdownHeader; if (h == null) return; + h.StatusColour = value; } } @@ -339,7 +339,7 @@ namespace osu.Game.Overlays.Settings.Sections.General public Color4 StatusColour { - set { statusIcon.FadeColour(value, 500, Easing.OutQuint); } + set => statusIcon.FadeColour(value, 500, Easing.OutQuint); } public UserDropdownHeader() diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 34d13b1462..188c9c05ef 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Configuration; @@ -15,19 +15,20 @@ namespace osu.Game.Overlays.Settings.Sections.General [BackgroundDependencyLoader] private void load(Storage storage, OsuConfigManager config) { - Children = new Drawable[] + Add(new SettingsEnumDropdown { - new SettingsEnumDropdown - { - LabelText = "Release stream", - Bindable = config.GetBindable(OsuSetting.ReleaseStream), - }, - new SettingsButton + LabelText = "Release stream", + Bindable = config.GetBindable(OsuSetting.ReleaseStream), + }); + + if (RuntimeInfo.IsDesktop) + { + Add(new SettingsButton { Text = "Open osu! folder", Action = storage.OpenInNativeExplorer, - } - }; + }); + } } } } diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index f75f01c034..ad1e714096 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 54049bfb1f..01cdc9aa32 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 3fa4276616..58d2eb1f1e 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,15 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Drawing; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Platform; using osu.Game.Configuration; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -25,10 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable scalingMode; private Bindable sizeFullscreen; + private readonly BindableList windowModes = new BindableList(); private OsuGameBase game; private SettingsDropdown resolutionDropdown; - private SettingsEnumDropdown windowModeDropdown; + private SettingsDropdown windowModeDropdown; private Bindable scalingPositionX; private Bindable scalingPositionY; @@ -38,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, OsuGameBase game) + private void load(FrameworkConfigManager config, OsuConfigManager osuConfig, OsuGameBase game, GameHost host) { this.game = game; @@ -49,23 +52,34 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingPositionX = osuConfig.GetBindable(OsuSetting.ScalingPositionX); scalingPositionY = osuConfig.GetBindable(OsuSetting.ScalingPositionY); + if (host.Window != null) + windowModes.BindTo(host.Window.SupportedWindowModes); + Container resolutionSettingsContainer; Children = new Drawable[] { - windowModeDropdown = new SettingsEnumDropdown + windowModeDropdown = new SettingsDropdown { LabelText = "Screen mode", Bindable = config.GetBindable(FrameworkSetting.WindowMode), + ItemSource = windowModes, }, resolutionSettingsContainer = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y }, + new SettingsSlider + { + LabelText = "UI Scaling", + TransferValueOnCommit = true, + Bindable = osuConfig.GetBindable(OsuSetting.UIScale), + KeyboardStep = 0.01f + }, new SettingsEnumDropdown { - LabelText = "Scaling", + LabelText = "Screen Scaling", Bindable = osuConfig.GetBindable(OsuSetting.Scaling), }, scalingSettings = new FillFlowContainer> @@ -76,7 +90,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics AutoSizeDuration = transition_duration, AutoSizeEasing = Easing.OutQuint, Masking = true, - Children = new [] + Children = new[] { new SettingsSlider { @@ -120,9 +134,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = sizeFullscreen }; - windowModeDropdown.Bindable.BindValueChanged(windowMode => + windowModeDropdown.Bindable.BindValueChanged(mode => { - if (windowMode == WindowMode.Fullscreen) + if (mode.NewValue == WindowMode.Fullscreen) { resolutionDropdown.Show(); sizeFullscreen.TriggerChange(); @@ -135,13 +149,26 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingMode.BindValueChanged(mode => { scalingSettings.ClearTransforms(); - scalingSettings.AutoSizeAxes = mode != ScalingMode.Off ? Axes.Y : Axes.None; + scalingSettings.AutoSizeAxes = mode.NewValue != ScalingMode.Off ? Axes.Y : Axes.None; - if (mode == ScalingMode.Off) + if (mode.NewValue == ScalingMode.Off) scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - scalingSettings.ForEach(s => s.TransferValueOnCommit = mode == ScalingMode.Everything); + scalingSettings.ForEach(s => s.TransferValueOnCommit = mode.NewValue == ScalingMode.Everything); }, true); + + windowModes.ItemsAdded += _ => windowModesChanged(); + windowModes.ItemsRemoved += _ => windowModesChanged(); + + windowModesChanged(); + } + + private void windowModesChanged() + { + if (windowModes.Count > 1) + windowModeDropdown.Show(); + else + windowModeDropdown.Hide(); } /// @@ -151,7 +178,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics /// A bindable which will propagate updates with a delay. private void bindPreviewEvent(Bindable bindable) { - bindable.ValueChanged += v => + bindable.ValueChanged += _ => { switch (scalingMode.Value) { @@ -163,6 +190,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } private Drawable preview; + private void showPreview() { if (preview?.IsAlive != true) @@ -202,6 +230,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } } + private class UIScaleSlider : OsuSliderBar + { + public override string TooltipText => base.TooltipText + "x"; + } + private class ResolutionSettingsDropdown : SettingsDropdown { protected override OsuDropdown CreateDropdown() => new ResolutionDropdownControl { Items = Items }; @@ -212,6 +245,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { if (item == new Size(9999, 9999)) return "Default"; + return $"{item.Width}x{item.Height}"; } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs index 71d2b31946..92f64d0e14 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 5f3c7aa7e9..7317076c54 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 1ce25bf517..d37acf8700 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 51b0296ca4..3f1e77d482 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsButton { Text = "Key configuration", + TooltipText = "Change global shortcut keys and gameplay bindings", Action = keyConfig.ToggleVisibility }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index c4d180790c..4f2f3dfd1a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Input; -using osu.Framework.Input.Events; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; @@ -62,13 +62,13 @@ namespace osu.Game.Overlays.Settings.Sections.Input const string raw_mouse_handler = @"OsuTKRawMouseHandler"; const string standard_mouse_handler = @"OsuTKMouseHandler"; - ignoredInputHandler.Value = enabled ? standard_mouse_handler : raw_mouse_handler; + ignoredInputHandler.Value = enabled.NewValue ? standard_mouse_handler : raw_mouse_handler; }; ignoredInputHandler = config.GetBindable(FrameworkSetting.IgnoredInputHandlers); ignoredInputHandler.ValueChanged += handler => { - bool raw = !handler.Contains("Raw"); + bool raw = !handler.NewValue.Contains("Raw"); rawInputToggle.Value = raw; sensitivity.Bindable.Disabled = !raw; }; @@ -78,67 +78,16 @@ namespace osu.Game.Overlays.Settings.Sections.Input private class SensitivitySetting : SettingsSlider { - public override Bindable Bindable - { - get { return ((SensitivitySlider)Control).Sensitivity; } - - set - { - BindableDouble doubleValue = (BindableDouble)value; - - // create a second layer of bindable so we can only handle state changes when not being dragged. - ((SensitivitySlider)Control).Sensitivity = doubleValue; - - // this bindable will still act as the "interactive" bindable displayed during a drag. - base.Bindable = new BindableDouble(doubleValue.Value) - { - Default = doubleValue.Default, - MinValue = doubleValue.MinValue, - MaxValue = doubleValue.MaxValue - }; - - // one-way binding to update the sliderbar with changes from external actions. - doubleValue.DisabledChanged += disabled => base.Bindable.Disabled = disabled; - doubleValue.ValueChanged += newValue => base.Bindable.Value = newValue; - } - } - public SensitivitySetting() { KeyboardStep = 0.01f; + TransferValueOnCommit = true; } } private class SensitivitySlider : OsuSliderBar { - public Bindable Sensitivity; - - public SensitivitySlider() - { - Current.ValueChanged += newValue => - { - if (!isDragging && Sensitivity != null) - Sensitivity.Value = newValue; - }; - } - - private bool isDragging; - - protected override bool OnDragStart(DragStartEvent e) - { - isDragging = true; - return base.OnDragStart(e); - } - - protected override bool OnDragEnd(DragEndEvent e) - { - isDragging = false; - Current.TriggerChange(); - - return base.OnDragEnd(e); - } - - public override string TooltipText => Current.Disabled ? "Enable raw input to adjust sensitivity" : Current.Value.ToString(@"0.##x"); + public override string TooltipText => Current.Disabled ? "Enable raw input to adjust sensitivity" : $"{base.TooltipText}x"; } } } diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index df94c1ad08..d37a2a6d65 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs index ebabdd7a5d..9b09a41c92 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 835ec808bc..398a091486 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using System.Threading.Tasks; @@ -25,9 +25,9 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay) { - Children = new Drawable[] + if (beatmaps.SupportsImportFromStable) { - importBeatmapsButton = new SettingsButton + Add(importBeatmapsButton = new SettingsButton { Text = "Import beatmaps from stable", Action = () => @@ -35,20 +35,25 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance importBeatmapsButton.Enabled.Value = false; beatmaps.ImportFromStableAsync().ContinueWith(t => Schedule(() => importBeatmapsButton.Enabled.Value = true)); } - }, - deleteBeatmapsButton = new DangerousSettingsButton + }); + } + + Add(deleteBeatmapsButton = new DangerousSettingsButton + { + Text = "Delete ALL beatmaps", + Action = () => { - Text = "Delete ALL beatmaps", - Action = () => + dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => { - dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => - { - deleteBeatmapsButton.Enabled.Value = false; - Task.Run(() => beatmaps.Delete(beatmaps.GetAllUsableBeatmapSets())).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); - })); - } - }, - importSkinsButton = new SettingsButton + deleteBeatmapsButton.Enabled.Value = false; + Task.Run(() => beatmaps.Delete(beatmaps.GetAllUsableBeatmapSets())).ContinueWith(t => Schedule(() => deleteBeatmapsButton.Enabled.Value = true)); + })); + } + }); + + if (skins.SupportsImportFromStable) + { + Add(importSkinsButton = new SettingsButton { Text = "Import skins from stable", Action = () => @@ -56,7 +61,11 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance importSkinsButton.Enabled.Value = false; skins.ImportFromStableAsync().ContinueWith(t => Schedule(() => importSkinsButton.Enabled.Value = true)); } - }, + }); + } + + AddRange(new Drawable[] + { deleteSkinsButton = new DangerousSettingsButton { Text = "Delete ALL skins", @@ -91,7 +100,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Task.Run(() => beatmaps.Undelete(beatmaps.QueryBeatmapSets(b => b.DeletePending).ToList())).ContinueWith(t => Schedule(() => undeleteButton.Enabled.Value = true)); } }, - }; + }); } } } diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 673a49ea8f..98ed8ebdaa 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs index 62e307f323..a8b3e45a83 100644 --- a/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 3a2e52d2eb..7c959525f7 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index e259996b7f..4b0147eb5d 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Graphics; @@ -52,6 +52,16 @@ namespace osu.Game.Overlays.Settings.Sections LabelText = "Adjust gameplay cursor size based on current beatmap", Bindable = config.GetBindable(OsuSetting.AutoCursorSize) }, + new SettingsCheckbox + { + LabelText = "Beatmap skins", + Bindable = config.GetBindable(OsuSetting.BeatmapSkins) + }, + new SettingsCheckbox + { + LabelText = "Beatmap hitsounds", + Bindable = config.GetBindable(OsuSetting.BeatmapHitsounds) + }, }; skins.ItemAdded += itemAdded; @@ -66,13 +76,13 @@ namespace osu.Game.Overlays.Settings.Sections if (skinDropdown.Items.All(s => s.ID != configBindable.Value)) configBindable.Value = 0; - configBindable.BindValueChanged(v => dropdownBindable.Value = skinDropdown.Items.Single(s => s.ID == v), true); - dropdownBindable.BindValueChanged(v => configBindable.Value = v.ID); + configBindable.BindValueChanged(id => dropdownBindable.Value = skinDropdown.Items.Single(s => s.ID == id.NewValue), true); + dropdownBindable.BindValueChanged(skin => configBindable.Value = skin.NewValue.ID); } private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray()); - private void itemAdded(SkinInfo s, bool existing, bool silent) + private void itemAdded(SkinInfo s, bool existing) { if (existing) return; diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 6689664988..ef98c28285 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,17 +1,33 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsButton : TriangleButton + public class SettingsButton : TriangleButton, IHasTooltip { public SettingsButton() { RelativeSizeAxes = Axes.X; Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }; } + + public string TooltipText { get; set; } + + public override IEnumerable FilterTerms + { + get + { + if (TooltipText != null) + return base.FilterTerms.Append(TooltipText); + + return base.FilterTerms; + } + } } } diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index 2c0f510cb8..46c23c3bbf 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Settings public override string LabelText { - get { return checkbox.LabelText; } - set { checkbox.LabelText = value; } + get => checkbox.LabelText; + set => checkbox.LabelText = value; } } } diff --git a/osu.Game/Overlays/Settings/SettingsDropdown.cs b/osu.Game/Overlays/Settings/SettingsDropdown.cs index 1c3eb6c245..de3f741cd7 100644 --- a/osu.Game/Overlays/Settings/SettingsDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsDropdown.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -26,9 +27,25 @@ namespace osu.Game.Overlays.Settings } } + private IBindableList itemSource; + + public IBindableList ItemSource + { + get => itemSource; + set + { + itemSource = value; + + if (Control != null) + Control.ItemSource = value; + } + } + + public override IEnumerable FilterTerms => base.FilterTerms.Concat(Control.Items.Select(i => i.ToString())); + protected sealed override Drawable CreateControl() => CreateDropdown(); - protected virtual OsuDropdown CreateDropdown() => new DropdownControl { Items = Items }; + protected virtual OsuDropdown CreateDropdown() => new DropdownControl { Items = Items, ItemSource = ItemSource }; protected class DropdownControl : OsuDropdown { diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 2a98b80816..11cdbf6e0a 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index ac1548f00d..e8c2c1ffe8 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; @@ -56,14 +56,13 @@ namespace osu.Game.Overlays.Settings Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = game.Name, - TextSize = 18, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = game.Version, Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, }, diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index fc86a38689..fbf29f7ff5 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings new OsuSpriteText { Text = heading, - TextSize = 40, + Font = OsuFont.GetFont(size: 40), Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Settings { Colour = colours.Pink, Text = subheading, - TextSize = 18, + Font = OsuFont.GetFont(size: 18), Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index 1d7e6350ae..f6517bafd6 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Settings public virtual string LabelText { - get { return text?.Text ?? string.Empty; } + get => text?.Text ?? string.Empty; set { if (text == null) @@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Settings public virtual Bindable Bindable { - get { return bindable; } + get => bindable; set { @@ -72,15 +72,11 @@ namespace osu.Game.Overlays.Settings } } - public IEnumerable FilterTerms => new[] { LabelText }; + public virtual IEnumerable FilterTerms => new[] { LabelText }; public bool MatchingFilter { - set - { - // probably needs a better transition. - this.FadeTo(value ? 1 : 0); - } + set => this.FadeTo(value ? 1 : 0); } protected SettingsItem() @@ -115,12 +111,12 @@ namespace osu.Game.Overlays.Settings public Bindable Bindable { - get { return bindable; } + get => bindable; set { bindable = value; - bindable.ValueChanged += newValue => UpdateState(); - bindable.DisabledChanged += disabled => UpdateState(); + bindable.ValueChanged += _ => UpdateState(); + bindable.DisabledChanged += _ => UpdateState(); } } diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index b7fe748bad..38a8b58a68 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Settings public bool MatchingFilter { - set { this.FadeTo(value ? 1 : 0); } + set => this.FadeTo(value ? 1 : 0); } protected SettingsSection() @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Settings { new OsuSpriteText { - TextSize = header_size, + Font = OsuFont.GetFont(size: header_size), Text = Header, Colour = colours.Yellow, Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS } diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 39a974dd2e..fd96ea972a 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 94a660d1c8..2215e95fec 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -8,6 +8,7 @@ using osu.Game.Graphics.Sprites; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Game.Graphics; namespace osu.Game.Overlays.Settings { @@ -21,12 +22,10 @@ namespace osu.Game.Overlays.Settings public IEnumerable FilterableChildren => Children.OfType(); public IEnumerable FilterTerms => new[] { Header }; + public bool MatchingFilter { - set - { - this.FadeTo(value ? 1 : 0); - } + set => this.FadeTo(value ? 1 : 0); } protected SettingsSubsection() @@ -53,7 +52,7 @@ namespace osu.Game.Overlays.Settings { Text = Header.ToUpperInvariant(), Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black), }, FlowContent }); diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index fbfb5481c5..0f257c2bfb 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index e43d4682b9..969686e36d 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -88,7 +88,7 @@ namespace osu.Game.Overlays.Settings public ExpandedState State { - get { return state; } + get => state; set { expandEvent?.Cancel(); diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index 1b23273c3c..c7736d6047 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -26,12 +26,10 @@ namespace osu.Game.Overlays.Settings public new Action Action; private SettingsSection section; + public SettingsSection Section { - get - { - return section; - } + get => section; set { section = value; @@ -41,9 +39,10 @@ namespace osu.Game.Overlays.Settings } private bool selected; + public bool Selected { - get { return selected; } + get => selected; set { selected = value; diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index df81421ea7..174d3a3de1 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -107,12 +107,12 @@ namespace osu.Game.Overlays SectionsContainer.SelectedSection.ValueChanged += section => { selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section); + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); selectedSidebarButton.Selected = true; }; } - searchTextBox.Current.ValueChanged += newValue => SectionsContainer.SearchContainer.SearchTerm = newValue; + searchTextBox.Current.ValueChanged += term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue; CreateSections()?.ForEach(AddSection); } @@ -179,7 +179,7 @@ namespace osu.Game.Overlays protected override void OnFocus(FocusEvent e) { - GetContainingInputManager().ChangeFocus(searchTextBox); + searchTextBox.TakeFocus(); base.OnFocus(e); } diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index 72c3791f6f..6abf6ec98d 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index a23a96cdf4..cf8053ac6e 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -32,13 +32,12 @@ namespace osu.Game.Overlays.Social new OsuSpriteText { Text = "social ", - TextSize = 25, + Font = OsuFont.GetFont(size: 25), }, browser = new OsuSpriteText { Text = "browser", - TextSize = 25, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 25, weight: FontWeight.Light), }, }, }; @@ -55,6 +54,7 @@ namespace osu.Game.Overlays.Social { [Description("All Players")] AllPlayers, + [Description("Friends")] Friends, //[Description("Team Members")] diff --git a/osu.Game/Overlays/Social/SocialGridPanel.cs b/osu.Game/Overlays/Social/SocialGridPanel.cs index 0051e1e0e5..6f707d640b 100644 --- a/osu.Game/Overlays/Social/SocialGridPanel.cs +++ b/osu.Game/Overlays/Social/SocialGridPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Users; @@ -7,7 +7,8 @@ namespace osu.Game.Overlays.Social { public class SocialGridPanel : SocialPanel { - public SocialGridPanel(User user) : base(user) + public SocialGridPanel(User user) + : base(user) { Width = 300; } diff --git a/osu.Game/Overlays/Social/SocialListPanel.cs b/osu.Game/Overlays/Social/SocialListPanel.cs index ff39e3b236..1ba91e9204 100644 --- a/osu.Game/Overlays/Social/SocialListPanel.cs +++ b/osu.Game/Overlays/Social/SocialListPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Users; @@ -8,7 +8,8 @@ namespace osu.Game.Overlays.Social { public class SocialListPanel : SocialPanel { - public SocialListPanel(User user) : base(user) + public SocialListPanel(User user) + : base(user) { RelativeSizeAxes = Axes.X; } diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs index 4dfeda9041..738f940484 100644 --- a/osu.Game/Overlays/Social/SocialPanel.cs +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -15,7 +15,8 @@ namespace osu.Game.Overlays.Social { private const double hover_transition_time = 400; - public SocialPanel(User user) : base(user) + public SocialPanel(User user) + : base(user) { } diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index bd6cd3cba6..daf3d1c576 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -15,14 +16,13 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; -using osu.Framework.Configuration; using osu.Framework.Threading; namespace osu.Game.Overlays { public class SocialOverlay : SearchableListOverlay, IOnlineComponent { - private APIAccess api; + private IAPIProvider api; private readonly LoadingAnimation loading; private FillFlowContainer panels; @@ -34,9 +34,10 @@ namespace osu.Game.Overlays protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); private IEnumerable users; + public IEnumerable Users { - get { return users; } + get => users; set { if (users?.Equals(value) ?? false) @@ -57,7 +58,7 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (!string.IsNullOrEmpty(text)) + if (!string.IsNullOrEmpty(text.NewValue)) { // force searching in players until searching for friends is supported Header.Tabs.Current.Value = SocialTab.AllPlayers; @@ -67,18 +68,18 @@ namespace osu.Game.Overlays } }; - Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); + Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); - Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); currentQuery.ValueChanged += query => { queryChangedDebounce?.Cancel(); - if (string.IsNullOrEmpty(query)) + if (string.IsNullOrEmpty(query.NewValue)) Scheduler.AddOnce(updateSearch); else queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); @@ -88,7 +89,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; api.Register(this); @@ -123,6 +124,7 @@ namespace osu.Game.Overlays panel = new SocialListPanel(u); break; } + panel.Status.BindTo(u.Status); return panel; }) @@ -130,7 +132,7 @@ namespace osu.Game.Overlays LoadComponentAsync(newPanels, f => { - if(panels != null) + if (panels != null) ScrollFlow.Remove(panels); ScrollFlow.Add(panels = newPanels); @@ -171,6 +173,7 @@ namespace osu.Game.Overlays api.Queue(getUsersRequest = userRequest); break; } + loading.Show(); } @@ -190,7 +193,7 @@ namespace osu.Game.Overlays } } - public void APIStateChanged(APIAccess api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 341f5c3fd1..dca0226499 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; @@ -10,7 +10,7 @@ using osu.Game.Graphics; using osuTK; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Input.Events; namespace osu.Game.Overlays.Toolbar @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Toolbar public Action OnHome; - private readonly ToolbarUserArea userArea; + private ToolbarUserArea userArea; protected override bool BlockPositionalInput => false; @@ -34,6 +34,13 @@ namespace osu.Game.Overlays.Toolbar private readonly Bindable overlayActivationMode = new Bindable(OverlayActivation.All); public Toolbar() + { + RelativeSizeAxes = Axes.X; + Size = new Vector2(1, HEIGHT); + } + + [BackgroundDependencyLoader(true)] + private void load(OsuGame osuGame) { Children = new Drawable[] { @@ -76,16 +83,9 @@ namespace osu.Game.Overlays.Toolbar } }; - RelativeSizeAxes = Axes.X; - Size = new Vector2(1, HEIGHT); - } - - [BackgroundDependencyLoader(true)] - private void load(OsuGame osuGame) - { StateChanged += visibility => { - if (overlayActivationMode == OverlayActivation.Disabled) + if (overlayActivationMode.Value == OverlayActivation.Disabled) State = Visibility.Hidden; }; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index a9d8be6ff2..855c7ad823 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -35,34 +35,25 @@ namespace osu.Game.Overlays.Toolbar public FontAwesome Icon { - set { SetIcon(value); } + set => SetIcon(value); } public string Text { - get { return DrawableText.Text; } - set - { - DrawableText.Text = value; - } + get => DrawableText.Text; + set => DrawableText.Text = value; } public string TooltipMain { - get { return tooltip1.Text; } - set - { - tooltip1.Text = value; - } + get => tooltip1.Text; + set => tooltip1.Text = value; } public string TooltipSub { - get { return tooltip2.Text; } - set - { - tooltip2.Text = value; - } + get => tooltip2.Text; + set => tooltip2.Text = value; } protected virtual Anchor TooltipAnchor => Anchor.TopLeft; @@ -75,7 +66,8 @@ namespace osu.Game.Overlays.Toolbar private readonly SpriteText tooltip2; protected FillFlowContainer Flow; - public ToolbarButton() : base(HoverSampleSet.Loud) + public ToolbarButton() + : base(HoverSampleSet.Loud) { Width = WIDTH; RelativeSizeAxes = Axes.Y; @@ -129,15 +121,13 @@ namespace osu.Game.Overlays.Toolbar Anchor = TooltipAnchor, Origin = TooltipAnchor, Shadow = true, - TextSize = 22, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 22, weight: FontWeight.Bold), }, tooltip2 = new OsuSpriteText { Anchor = TooltipAnchor, Origin = TooltipAnchor, Shadow = true, - TextSize = 16 } } } @@ -149,6 +139,7 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnClick(ClickEvent e) { HoverBackground.FlashColour(Color4.White.Opacity(100), 500, Easing.OutQuint); + tooltipContainer.FadeOut(100); return base.OnClick(e); } diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index 3d9b943d16..226960564d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs index ffc5ecd682..38ce4c7ccf 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index e79b73e725..3675c4578e 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 94a7e69e3f..40ffc71d87 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 42d9527432..751045f61c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -47,11 +47,11 @@ namespace osu.Game.Overlays.Toolbar NotificationCount.ValueChanged += count => { - if (count == 0) + if (count.NewValue == 0) countDisplay.FadeOut(200, Easing.OutQuint); else { - countDisplay.Count = count; + countDisplay.Count = count.NewValue; countDisplay.FadeIn(200, Easing.OutQuint); } }; @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Toolbar public int Count { - get { return count; } + get => count; set { if (count == value) @@ -99,11 +99,10 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.Centre, Origin = Anchor.Centre, Y = -1, - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Padding = new MarginPadding(5), Colour = Color4.White, UseFullGlyphHeight = true, - Font = "Exo2.0-Bold", } }; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 0c8483dec3..ca86ce7aa7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Toolbar public OverlayContainer StateContainer { - get { return stateContainer; } + get => stateContainer; set { stateContainer = value; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs index b0801d95b0..f729810fbc 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osu.Game.Rulesets; @@ -10,9 +10,10 @@ namespace osu.Game.Overlays.Toolbar public class ToolbarRulesetButton : ToolbarButton { private RulesetInfo ruleset; + public RulesetInfo Ruleset { - get { return ruleset; } + get => ruleset; set { ruleset = value; diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 19777bfbeb..d01eab4dab 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Input; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Rulesets; @@ -115,11 +115,11 @@ namespace osu.Game.Overlays.Toolbar Size = new Vector2(modeButtons.DrawSize.X, 1); } - private void rulesetChanged(RulesetInfo ruleset) + private void rulesetChanged(ValueChangedEvent e) { foreach (ToolbarRulesetButton m in modeButtons.Children.Cast()) { - bool isActive = m.Ruleset.ID == ruleset.ID; + bool isActive = m.Ruleset.ID == e.NewValue.ID; m.Active = isActive; if (isActive) activeButton = m; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index 5c3eaf7840..14f652f6fe 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index f45950cb4c..d0e664ecae 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs index d0cb3c0ff2..f9cf5d4350 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -22,7 +22,8 @@ namespace osu.Game.Overlays.Toolbar RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; - Children = new Drawable[] { + Children = new Drawable[] + { button = new ToolbarUserButton { Action = () => LoginOverlay.ToggleVisibility(), diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 36299e51f0..8d1910fc19 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Users; using osuTK; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Toolbar { AutoSizeAxes = Axes.X; - DrawableText.Font = @"Exo2.0-MediumItalic"; + DrawableText.Font = OsuFont.GetFont(italics: true); Add(new OpaqueBackground { Depth = 1 }); @@ -42,12 +43,12 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { api.Register(this); } - public void APIStateChanged(APIAccess api, APIState state) + public void APIStateChanged(IAPIProvider api, APIState state) { switch (state) { @@ -57,7 +58,7 @@ namespace osu.Game.Overlays.Toolbar break; case APIState.Online: Text = api.LocalUser.Value.Username; - avatar.User = api.LocalUser; + avatar.User = api.LocalUser.Value; break; } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index c15f464c7c..48ce055975 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; @@ -26,7 +26,7 @@ namespace osu.Game.Overlays private ProfileSection lastSection; private ProfileSection[] sections; private GetUserRequest userReq; - private APIAccess api; + private IAPIProvider api; protected ProfileHeader Header; private SectionsContainer sectionsContainer; private ProfileTabControl tabs; @@ -56,7 +56,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; } @@ -126,16 +126,16 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both } }); - sectionsContainer.SelectedSection.ValueChanged += s => + sectionsContainer.SelectedSection.ValueChanged += section => { - if (lastSection != s) + if (lastSection != section.NewValue) { - lastSection = s; + lastSection = section.NewValue; tabs.Current.Value = lastSection; } }; - tabs.Current.ValueChanged += s => + tabs.Current.ValueChanged += section => { if (lastSection == null) { @@ -144,9 +144,10 @@ namespace osu.Game.Overlays tabs.Current.Value = lastSection; return; } - if (lastSection != s) + + if (lastSection != section.NewValue) { - lastSection = s; + lastSection = section.NewValue; sectionsContainer.ScrollTo(lastSection); } }; @@ -212,7 +213,8 @@ namespace osu.Game.Overlays private class ProfileTabItem : PageTabItem { - public ProfileTabItem(ProfileSection value) : base(value) + public ProfileTabItem(ProfileSection value) + : base(value) { Text.Text = value.Title; } diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index dddfddedef..6061ead2da 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -69,10 +69,10 @@ namespace osu.Game.Overlays.Volume } }); - Current.ValueChanged += newValue => + Current.ValueChanged += muted => { - icon.Icon = newValue ? FontAwesome.fa_volume_off : FontAwesome.fa_volume_up; - icon.Margin = new MarginPadding { Left = newValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths + icon.Icon = muted.NewValue ? FontAwesome.fa_volume_off : FontAwesome.fa_volume_up; + icon.Margin = new MarginPadding { Left = muted.NewValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths }; Current.TriggerChange(); } diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs index 3a64e12b27..26235fa280 100644 --- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 1263ecd303..da696e0fdd 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Globalization; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -140,8 +140,7 @@ namespace osu.Game.Overlays.Volume { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = "Venera", - TextSize = 0.16f * circleSize + Font = OsuFont.Numeric.With(size: 0.16f * circleSize) }).WithEffect(new GlowEffect { Colour = Color4.Transparent, @@ -169,16 +168,16 @@ namespace osu.Game.Overlays.Volume { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = name } } } }; - Bindable.ValueChanged += newVolume => + Bindable.ValueChanged += volume => { this.TransformTo("DisplayVolume", - newVolume, + volume.NewValue, 400, Easing.OutQuint); }; @@ -218,7 +217,7 @@ namespace osu.Game.Overlays.Volume public double Volume { - get => Bindable; + get => Bindable.Value; private set => Bindable.Value = value; } diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index cbe61b5896..e2e480ef53 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -74,9 +74,9 @@ namespace osu.Game.Overlays volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - muteButton.Current.ValueChanged += mute => + muteButton.Current.ValueChanged += muted => { - if (mute) + if (muted.NewValue) audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); else audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment); @@ -113,7 +113,7 @@ namespace osu.Game.Overlays return true; case GlobalAction.ToggleMute: Show(); - muteButton.Current.Value = !muteButton.Current; + muteButton.Current.Value = !muteButton.Current.Value; return true; } diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index c5a4953c5e..05d3e7df0a 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; diff --git a/osu.Game/Properties/AssemblyInfo.cs b/osu.Game/Properties/AssemblyInfo.cs index df9045b802..cddea7a35f 100644 --- a/osu.Game/Properties/AssemblyInfo.cs +++ b/osu.Game/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Runtime.CompilerServices; @@ -9,3 +9,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("osu.Game.Tests")] [assembly: InternalsVisibleTo("osu.Game.Tests.Dynamic")] +[assembly: InternalsVisibleTo("osu.Game.Tests.iOS")] \ No newline at end of file diff --git a/osu.Game/Replays/Legacy/LegacyReplayFrame.cs b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs index ac9fd96ae6..c3cffa8699 100644 --- a/osu.Game/Replays/Legacy/LegacyReplayFrame.cs +++ b/osu.Game/Replays/Legacy/LegacyReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Replays; using osuTK; diff --git a/osu.Game/Replays/Legacy/ReplayButtonState.cs b/osu.Game/Replays/Legacy/ReplayButtonState.cs index ffeff55e96..4b02cf2cd5 100644 --- a/osu.Game/Replays/Legacy/ReplayButtonState.cs +++ b/osu.Game/Replays/Legacy/ReplayButtonState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; diff --git a/osu.Game/Replays/Replay.cs b/osu.Game/Replays/Replay.cs index bb6d9e7637..31d2ed0d70 100644 --- a/osu.Game/Replays/Replay.cs +++ b/osu.Game/Replays/Replay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Rulesets.Replays; diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs index 09c74d8bac..179cd5e2dc 100644 --- a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Configuration.Tracking; diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs index 74cece5154..ed5fdf9809 100644 --- a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Configuration; diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index 1fdebd586f..d808ee528e 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Mods; @@ -7,8 +7,13 @@ namespace osu.Game.Rulesets.Difficulty { public class DifficultyAttributes { - public readonly Mod[] Mods; - public readonly double StarRating; + public Mod[] Mods; + + public double StarRating; + + public DifficultyAttributes() + { + } public DifficultyAttributes(Mod[] mods, double starRating) { diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 25fd49ff9b..aad55f8a38 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -7,12 +7,20 @@ using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Difficulty { public abstract class DifficultyCalculator { + /// + /// The length of each strain section. + /// + protected virtual int SectionLength => 400; + private readonly Ruleset ruleset; private readonly WorkingBeatmap beatmap; @@ -29,13 +37,15 @@ namespace osu.Game.Rulesets.Difficulty /// A structure describing the difficulty of the beatmap. public DifficultyAttributes Calculate(params Mod[] mods) { + mods = mods.Select(m => m.CreateCopy()).ToArray(); + beatmap.Mods.Value = mods; IBeatmap playableBeatmap = beatmap.GetPlayableBeatmap(ruleset.RulesetInfo); var clock = new StopwatchClock(); mods.OfType().ForEach(m => m.ApplyToClock(clock)); - return Calculate(playableBeatmap, mods, clock.Rate); + return calculate(playableBeatmap, mods, clock.Rate); } /// @@ -53,6 +63,44 @@ namespace osu.Game.Rulesets.Difficulty } } + private DifficultyAttributes calculate(IBeatmap beatmap, Mod[] mods, double clockRate) + { + var skills = CreateSkills(beatmap); + + if (!beatmap.HitObjects.Any()) + return CreateDifficultyAttributes(beatmap, mods, skills, clockRate); + + var difficultyHitObjects = CreateDifficultyHitObjects(beatmap, clockRate).OrderBy(h => h.BaseObject.StartTime).ToList(); + + double sectionLength = SectionLength * clockRate; + + // The first object doesn't generate a strain, so we begin with an incremented section end + double currentSectionEnd = Math.Ceiling(beatmap.HitObjects.First().StartTime / sectionLength) * sectionLength; + + foreach (DifficultyHitObject h in difficultyHitObjects) + { + while (h.BaseObject.StartTime > currentSectionEnd) + { + foreach (Skill s in skills) + { + s.SaveCurrentPeak(); + s.StartNewSectionFrom(currentSectionEnd); + } + + currentSectionEnd += sectionLength; + } + + foreach (Skill s in skills) + s.Process(h); + } + + // The peak strain will not be saved for the last section in the above loop + foreach (Skill s in skills) + s.SaveCurrentPeak(); + + return CreateDifficultyAttributes(beatmap, mods, skills, clockRate); + } + /// /// Creates all combinations which adjust the difficulty. /// @@ -67,12 +115,15 @@ namespace osu.Game.Rulesets.Difficulty case 0: // Initial-case: Empty current set yield return new ModNoMod(); + break; case 1: yield return currentSet.Single(); + break; default: yield return new MultiMod(currentSet.ToArray()); + break; } @@ -96,12 +147,27 @@ namespace osu.Game.Rulesets.Difficulty protected virtual Mod[] DifficultyAdjustmentMods => Array.Empty(); /// - /// Calculates the difficulty of a using a specific combination. + /// Creates to describe beatmap's calculated difficulty. /// - /// The to compute the difficulty for. - /// The s that should be applied. - /// The rate of time in . - /// A structure containing the difficulty attributes. - protected abstract DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate); + /// The whose difficulty was calculated. + /// The s that difficulty was calculated with. + /// The skills which processed the beatmap. + /// The rate at which the gameplay clock is run at. + protected abstract DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate); + + /// + /// Enumerates s to be processed from s in the . + /// + /// The providing the s to enumerate. + /// The rate at which the gameplay clock is run at. + /// The enumerated s. + protected abstract IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate); + + /// + /// Creates the s to calculate the difficulty of an . + /// + /// The whose difficulty will be calculated.The s. + protected abstract Skill[] CreateSkills(IBeatmap beatmap); } } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 48a68928de..2b627ee8e6 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs new file mode 100644 index 0000000000..ebbffb5143 --- /dev/null +++ b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Difficulty.Preprocessing +{ + /// + /// Wraps a and provides additional information to be used for difficulty calculation. + /// + public class DifficultyHitObject + { + /// + /// The this wraps. + /// + public readonly HitObject BaseObject; + + /// + /// The last which occurs before . + /// + public readonly HitObject LastObject; + + /// + /// Amount of time elapsed between and . + /// + public readonly double DeltaTime; + + /// + /// Creates a new . + /// + /// The which this wraps. + /// The last which occurs before in the beatmap. + /// The rate at which the gameplay clock is run at. + public DifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + { + BaseObject = hitObject; + LastObject = lastObject; + DeltaTime = (hitObject.StartTime - lastObject.StartTime) / clockRate; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs similarity index 64% rename from osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs rename to osu.Game/Rulesets/Difficulty/Skills/Skill.cs index 47037c1503..e8020ed185 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs @@ -1,20 +1,24 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; -using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -using osu.Game.Rulesets.Osu.Difficulty.Utils; -using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Utils; -namespace osu.Game.Rulesets.Osu.Difficulty.Skills +namespace osu.Game.Rulesets.Difficulty.Skills { /// - /// Used to processes strain values of s, keep track of strain levels caused by the processed objects + /// Used to processes strain values of s, keep track of strain levels caused by the processed objects /// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects. /// public abstract class Skill { + /// + /// The peak strain for each section of the beatmap. + /// + public IList StrainPeaks => strainPeaks; + /// /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. /// @@ -27,22 +31,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected abstract double StrainDecayBase { get; } /// - /// s that were processed previously. They can affect the strain values of the following objects. + /// The weight by which each strain value decays. /// - protected readonly History Previous = new History(2); // Contained objects not used yet + protected virtual double DecayWeight => 0.9; + + /// + /// s that were processed previously. They can affect the strain values of the following objects. + /// + protected readonly LimitedCapacityStack Previous = new LimitedCapacityStack(2); // Contained objects not used yet private double currentStrain = 1; // We keep track of the strain level at all times throughout the beatmap. private double currentSectionPeak = 1; // We also keep track of the peak strain level in the current section. + private readonly List strainPeaks = new List(); /// - /// Process an and update current strain values accordingly. + /// Process a and update current strain values accordingly. /// - public void Process(OsuDifficultyHitObject current) + public void Process(DifficultyHitObject current) { currentStrain *= strainDecay(current.DeltaTime); - if (!(current.BaseObject is Spinner)) - currentStrain += StrainValueOf(current) * SkillMultiplier; + currentStrain += StrainValueOf(current) * SkillMultiplier; currentSectionPeak = Math.Max(currentStrain, currentSectionPeak); @@ -61,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Sets the initial strain level for a new section. /// - /// The beginning of the new section in milliseconds + /// The beginning of the new section in milliseconds. public void StartNewSectionFrom(double offset) { // The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries. @@ -71,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills } /// - /// Returns the calculated difficulty value representing all processed s. + /// Returns the calculated difficulty value representing all processed s. /// public double DifficultyValue() { @@ -84,16 +93,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills foreach (double strain in strainPeaks) { difficulty += strain * weight; - weight *= 0.9; + weight *= DecayWeight; } return difficulty; } /// - /// Calculates the strain value of an . This value is affected by previously processed objects. + /// Calculates the strain value of a . This value is affected by previously processed objects. /// - protected abstract double StrainValueOf(OsuDifficultyHitObject current); + protected abstract double StrainValueOf(DifficultyHitObject current); private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs similarity index 63% rename from osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs rename to osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index 55bd950209..95b7d9b19d 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -1,18 +1,20 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections; using System.Collections.Generic; -namespace osu.Game.Rulesets.Osu.Difficulty.Utils +namespace osu.Game.Rulesets.Difficulty.Utils { /// - /// An indexed stack with Push() only, which disposes items at the bottom after the capacity is full. - /// Indexing starts at the top of the stack. + /// An indexed stack with limited depth. Indexing starts at the top of the stack. /// - public class History : IEnumerable + public class LimitedCapacityStack : IEnumerable { + /// + /// The number of elements in the stack. + /// public int Count { get; private set; } private readonly T[] array; @@ -20,10 +22,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils private int marker; // Marks the position of the most recently added item. /// - /// Initializes a new instance of the History class that is empty and has the specified capacity. + /// Constructs a new . /// - /// The number of items the History can hold. - public History(int capacity) + /// The number of items the stack can hold. + public LimitedCapacityStack(int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException(); @@ -34,8 +36,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils } /// - /// The most recently added item is returned at index 0. + /// Retrieves the item at an index in the stack. /// + /// The index of the item to retrieve. The top of the stack is returned at index 0. public T this[int i] { get @@ -52,11 +55,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils } /// - /// Adds the item as the most recent one in the history. - /// The oldest item is disposed if the history is full. + /// Pushes an item to this . /// - public void Push(T item) // Overwrite the oldest item instead of shifting every item by one with every addition. + /// The item to push. + public void Push(T item) { + // Overwrite the oldest item instead of shifting every item by one with every addition. if (marker == 0) marker = capacity - 1; else diff --git a/osu.Game/Rulesets/Edit/EditRulesetContainer.cs b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs similarity index 70% rename from osu.Game/Rulesets/Edit/EditRulesetContainer.cs rename to osu.Game/Rulesets/Edit/DrawableEditRuleset.cs index 6f81d47431..76a2e7af12 100644 --- a/osu.Game/Rulesets/Edit/EditRulesetContainer.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Graphics; @@ -11,14 +11,14 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Edit { - public abstract class EditRulesetContainer : CompositeDrawable + public abstract class DrawableEditRuleset : CompositeDrawable { /// - /// The contained by this . + /// The contained by this . /// public abstract Playfield Playfield { get; } - internal EditRulesetContainer() + internal DrawableEditRuleset() { RelativeSizeAxes = Axes.Both; } @@ -38,21 +38,21 @@ namespace osu.Game.Rulesets.Edit internal abstract DrawableHitObject Remove(HitObject hitObject); } - public class EditRulesetContainer : EditRulesetContainer + public class DrawableEditRuleset : DrawableEditRuleset where TObject : HitObject { - public override Playfield Playfield => rulesetContainer.Playfield; + public override Playfield Playfield => drawableRuleset.Playfield; - private Ruleset ruleset => rulesetContainer.Ruleset; - private Beatmap beatmap => rulesetContainer.Beatmap; + private Ruleset ruleset => drawableRuleset.Ruleset; + private Beatmap beatmap => drawableRuleset.Beatmap; - private readonly RulesetContainer rulesetContainer; + private readonly DrawableRuleset drawableRuleset; - public EditRulesetContainer(RulesetContainer rulesetContainer) + public DrawableEditRuleset(DrawableRuleset drawableRuleset) { - this.rulesetContainer = rulesetContainer; + this.drawableRuleset = drawableRuleset; - InternalChild = rulesetContainer; + InternalChild = drawableRuleset; Playfield.DisplayJudgements.Value = false; } @@ -73,10 +73,10 @@ namespace osu.Game.Rulesets.Edit processor?.PostProcess(); // Add visual representation - var drawableObject = rulesetContainer.GetVisualRepresentation(tObject); + var drawableObject = drawableRuleset.GetVisualRepresentation(tObject); - rulesetContainer.Playfield.Add(drawableObject); - rulesetContainer.Playfield.PostProcess(); + drawableRuleset.Playfield.Add(drawableObject); + drawableRuleset.Playfield.PostProcess(); return drawableObject; } @@ -97,8 +97,8 @@ namespace osu.Game.Rulesets.Edit // Remove visual representation var drawableObject = Playfield.AllHitObjects.Single(d => d.HitObject == hitObject); - rulesetContainer.Playfield.Remove(drawableObject); - rulesetContainer.Playfield.PostProcess(); + drawableRuleset.Playfield.Remove(drawableObject); + drawableRuleset.Playfield.PostProcess(); return drawableObject; } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index da7c3dda6a..45bf9b8be7 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Edit { public abstract class HitObjectComposer : CompositeDrawable { - public IEnumerable HitObjects => RulesetContainer.Playfield.AllHitObjects; + public IEnumerable HitObjects => DrawableRuleset.Playfield.AllHitObjects; protected readonly Ruleset Ruleset; @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Edit private readonly List layerContainers = new List(); - protected EditRulesetContainer RulesetContainer { get; private set; } + protected DrawableEditRuleset DrawableRuleset { get; private set; } private BlueprintContainer blueprintContainer; @@ -48,14 +48,14 @@ namespace osu.Game.Rulesets.Edit } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, IFrameBasedClock framedClock) + private void load(IBindable beatmap, IFrameBasedClock framedClock) { Beatmap.BindTo(beatmap); try { - RulesetContainer = CreateRulesetContainer(); - RulesetContainer.Clock = framedClock; + DrawableRuleset = CreateDrawableRuleset(); + DrawableRuleset.Clock = framedClock; } catch (Exception e) { @@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - RulesetContainer, + DrawableRuleset, layerAboveRuleset } } @@ -111,8 +111,8 @@ namespace osu.Game.Rulesets.Edit toolboxCollection.Items = CompositionTools.Select(t => new RadioButton(t.Name, () => blueprintContainer.CurrentTool = t)) - .Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null)) - .ToList(); + .Prepend(new RadioButton("Select", () => blueprintContainer.CurrentTool = null)) + .ToList(); toolboxCollection.Items[0].Select(); } @@ -140,27 +140,27 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = RulesetContainer.Playfield.Anchor; - l.Origin = RulesetContainer.Playfield.Origin; - l.Position = RulesetContainer.Playfield.Position; - l.Size = RulesetContainer.Playfield.Size; + l.Anchor = DrawableRuleset.Playfield.Anchor; + l.Origin = DrawableRuleset.Playfield.Origin; + l.Position = DrawableRuleset.Playfield.Position; + l.Size = DrawableRuleset.Playfield.Size; }); } /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// - public virtual bool CursorInPlacementArea => RulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public virtual bool CursorInPlacementArea => DrawableRuleset.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); /// /// Adds a to the and visualises it. /// /// The to add. - public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(RulesetContainer.Add(hitObject)); + public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(DrawableRuleset.Add(hitObject)); - public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(RulesetContainer.Remove(hitObject)); + public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(DrawableRuleset.Remove(hitObject)); - internal abstract EditRulesetContainer CreateRulesetContainer(); + internal abstract DrawableEditRuleset CreateDrawableRuleset(); protected abstract IReadOnlyList CompositionTools { get; } @@ -189,9 +189,9 @@ namespace osu.Game.Rulesets.Edit { } - internal override EditRulesetContainer CreateRulesetContainer() - => new EditRulesetContainer(CreateRulesetContainer(Ruleset, Beatmap.Value)); + internal override DrawableEditRuleset CreateDrawableRuleset() + => new DrawableEditRuleset(CreateDrawableRuleset(Ruleset, Beatmap.Value)); - protected abstract RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap); + protected abstract DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap); } } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 1d568313ca..74aa9ace2d 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Edit } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, IAdjustableClock clock) + private void load(IBindable beatmap, IAdjustableClock clock) { this.beatmap.BindTo(beatmap); @@ -75,6 +75,7 @@ namespace osu.Game.Rulesets.Edit { if (state == value) return; + state = value; if (state == PlacementState.Shown) diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index ec4df01e55..85b6c91a07 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; diff --git a/osu.Game/Rulesets/Edit/ToolboxGroup.cs b/osu.Game/Rulesets/Edit/ToolboxGroup.cs index 4de0c518e6..eabb834616 100644 --- a/osu.Game/Rulesets/Edit/ToolboxGroup.cs +++ b/osu.Game/Rulesets/Edit/ToolboxGroup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Screens.Play.PlayerSettings; diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 1cb3c4c451..825c63e6ee 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Edit.Tools { diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index dd0152d957..89db954c36 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -32,6 +32,12 @@ namespace osu.Game.Rulesets.Judgements protected Container JudgementBody; protected SpriteText JudgementText; + /// + /// Duration of initial fade in. + /// Default fade out will start immediately after this duration. + /// + protected virtual double FadeInDuration => 100; + /// /// Creates a drawable which visualises a . /// @@ -58,19 +64,26 @@ namespace osu.Game.Rulesets.Judgements Child = new SkinnableDrawable($"Play/{Result.Type}", _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), - Font = @"Venera", + Font = OsuFont.Numeric.With(size: 12), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), - TextSize = 12 }, restrictSize: false) }; } + protected virtual void ApplyHitAnimations() + { + JudgementBody.ScaleTo(0.9f); + JudgementBody.ScaleTo(1, 500, Easing.OutElastic); + + this.Delay(FadeInDuration).FadeOut(400); + } + protected override void LoadComplete() { base.LoadComplete(); - this.FadeInFromZero(100, Easing.OutQuint); + this.FadeInFromZero(FadeInDuration, Easing.OutQuint); switch (Result.Type) { @@ -86,10 +99,7 @@ namespace osu.Game.Rulesets.Judgements this.Delay(600).FadeOut(200); break; default: - JudgementBody.ScaleTo(0.9f); - JudgementBody.ScaleTo(1, 500, Easing.OutElastic); - - this.Delay(100).FadeOut(400); + ApplyHitAnimations(); break; } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 86a41a08ff..e14eedd3dc 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; @@ -58,5 +58,7 @@ namespace osu.Game.Rulesets.Judgements /// The to find the numeric health increase for. /// The numeric health increase of . public double HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); + + public override string ToString() => $"AffectsCombo:{AffectsCombo} MaxResult:{MaxResult} MaxScore:{MaxNumericResult}"; } } diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index 5cadf7e2ee..d4ef5750b1 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -55,5 +55,7 @@ namespace osu.Game.Rulesets.Judgements { Judgement = judgement; } + + public override string ToString() => $"{Type} (Score:{Judgement.NumericResultFor(this)} HP:{Judgement.HealthIncreaseFor(this)} {Judgement})"; } } diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index 6a4042a906..c0262b783b 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mods { diff --git a/osu.Game/Rulesets/Mods/IApplicableMod.cs b/osu.Game/Rulesets/Mods/IApplicableMod.cs index 30046c3dc2..8ca1a3f8a5 100644 --- a/osu.Game/Rulesets/Mods/IApplicableMod.cs +++ b/osu.Game/Rulesets/Mods/IApplicableMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mods { diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs index 1eb74ca76a..a634976b3c 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs index 1b8e62b53c..eb80fa131a 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Mods/IApplicableToClock.cs b/osu.Game/Rulesets/Mods/IApplicableToClock.cs index a9570d80c2..e5767b5fbf 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToClock.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToClock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Timing; diff --git a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs index 3f32253544..4d4cd75434 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs index fca04ca513..5630315770 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/Mods/IApplicableToDrawableRuleset.cs b/osu.Game/Rulesets/Mods/IApplicableToDrawableRuleset.cs new file mode 100644 index 0000000000..b012beb0c0 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToDrawableRuleset.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for s that can be applied to s. + /// + public interface IApplicableToDrawableRuleset : IApplicableMod + where TObject : HitObject + { + /// + /// Applies this to a . + /// + /// The to apply to. + void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset); + } +} diff --git a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs index d6f330d9df..c13b62812b 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs b/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs deleted file mode 100644 index a3c5ab3df4..0000000000 --- a/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.UI; - -namespace osu.Game.Rulesets.Mods -{ - /// - /// An interface for s that can be applied to s. - /// - public interface IApplicableToRulesetContainer : IApplicableMod - where TObject : HitObject - { - /// - /// Applies this to a . - /// - /// The to apply to. - void ApplyToRulesetContainer(RulesetContainer rulesetContainer); - } -} diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs index 772eac478c..1d0ed94ef4 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Mods/IMod.cs b/osu.Game/Rulesets/Mods/IMod.cs index 49a3963496..448ad0eb30 100644 --- a/osu.Game/Rulesets/Mods/IMod.cs +++ b/osu.Game/Rulesets/Mods/IMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/Mods/IReadFromConfig.cs b/osu.Game/Rulesets/Mods/IReadFromConfig.cs index 93c9ae0c34..d66fabce70 100644 --- a/osu.Game/Rulesets/Mods/IReadFromConfig.cs +++ b/osu.Game/Rulesets/Mods/IReadFromConfig.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Configuration; diff --git a/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs index be879759bd..9baa252caf 100644 --- a/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs +++ b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.UI; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 14ee6b99ec..1f9907caa7 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using System; @@ -65,5 +65,10 @@ namespace osu.Game.Rulesets.Mods /// [JsonIgnore] public virtual Type[] IncompatibleMods => new Type[] { }; + + /// + /// Creates a copy of this initialised to a default state. + /// + public virtual Mod CreateCopy() => (Mod)Activator.CreateInstance(GetType()); } } diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 72ae88d67a..1c76abbc4b 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; @@ -11,14 +11,10 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer + public abstract class ModAutoplay : ModAutoplay, IApplicableToDrawableRuleset where T : HitObject { - protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; - - public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; - - public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) => rulesetContainer.SetReplayScore(CreateReplayScore(rulesetContainer.Beatmap)); + public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) => drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap)); } public abstract class ModAutoplay : Mod, IApplicableFailOverride @@ -31,5 +27,9 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 1; public bool AllowFail => false; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; + + public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; + + public virtual Score CreateReplayScore(IBeatmap beatmap) => new Score { Replay = new Replay() }; } } diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 5c4040ee4c..6f8eed4a0a 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index 5e3ec60be3..dded688e80 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; using osu.Framework.Timing; @@ -16,9 +16,8 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToClock(IAdjustableClock clock) { - var pitchAdjust = clock as IHasPitchAdjust; - if (pitchAdjust != null) - pitchAdjust.PitchAdjust = 0.75; + if (clock is IHasPitchAdjust pitchAdjust) + pitchAdjust.PitchAdjust *= RateAdjust; else base.ApplyToClock(clock); } diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index 5c1d732995..9ea9eb76bc 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Timing; +using System.Linq; using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModDoubleTime : Mod, IApplicableToClock + public abstract class ModDoubleTime : ModTimeAdjust, IApplicableToClock { public override string Name => "Double Time"; public override string Acronym => "DT"; @@ -15,11 +15,9 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Zoooooooooom..."; public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime) }; - public virtual void ApplyToClock(IAdjustableClock clock) - { - clock.Rate = 1.5; - } + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModHalfTime)).ToArray(); + + protected override double RateAdjust => 1.5; } } diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index 03781bea47..ef4de0e300 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 98da97d6fe..23e928d991 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mods } } - public abstract class ModFlashlight : ModFlashlight, IApplicableToRulesetContainer, IApplicableToScoreProcessor + public abstract class ModFlashlight : ModFlashlight, IApplicableToDrawableRuleset, IApplicableToScoreProcessor where T : HitObject { public const double FLASHLIGHT_FADE_DURATION = 800; @@ -45,15 +45,15 @@ namespace osu.Game.Rulesets.Mods Combo.BindTo(scoreProcessor.Combo); } - public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { var flashlight = CreateFlashlight(); flashlight.Combo = Combo; flashlight.RelativeSizeAxes = Axes.Both; flashlight.Colour = Color4.Black; - rulesetContainer.KeyBindingInputManager.Add(flashlight); + drawableRuleset.KeyBindingInputManager.Add(flashlight); - flashlight.Breaks = rulesetContainer.Beatmap.Breaks; + flashlight.Breaks = drawableRuleset.Beatmap.Breaks; } public abstract Flashlight CreateFlashlight(); @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mods public abstract class Flashlight : Drawable { internal BindableInt Combo; - private Shader shader; + private IShader shader; protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(); @@ -104,11 +104,12 @@ namespace osu.Game.Rulesets.Mods } } - protected abstract void OnComboChange(int newCombo); + protected abstract void OnComboChange(ValueChangedEvent e); protected abstract string FragmentShader { get; } private Vector2 flashlightPosition; + protected Vector2 FlashlightPosition { get => flashlightPosition; @@ -122,6 +123,7 @@ namespace osu.Game.Rulesets.Mods } private Vector2 flashlightSize; + protected Vector2 FlashlightSize { get => flashlightSize; @@ -137,7 +139,7 @@ namespace osu.Game.Rulesets.Mods private class FlashlightDrawNode : DrawNode { - public Shader Shader; + public IShader Shader; public Quad ScreenSpaceDrawQuad; public Vector2 FlashlightPosition; public Vector2 FlashlightSize; diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index 2d95b10db1..fe26c96214 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Timing; +using System.Linq; using osu.Game.Graphics; namespace osu.Game.Rulesets.Mods { - public abstract class ModHalfTime : Mod, IApplicableToClock + public abstract class ModHalfTime : ModTimeAdjust, IApplicableToClock { public override string Name => "Half Time"; public override string Acronym => "HT"; @@ -15,11 +15,9 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyReduction; public override string Description => "Less zoom..."; public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) }; - public virtual void ApplyToClock(IAdjustableClock clock) - { - clock.Rate = 0.75; - } + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModDoubleTime)).ToArray(); + + protected override double RateAdjust => 0.75; } } diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 14f997ae8c..4b8792098e 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index b843171521..e526125947 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.Mods { @@ -27,10 +27,12 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility ? 1 : 0)) + foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) d.ApplyCustomUpdateState += ApplyHiddenState; } - protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) { } + protected virtual void ApplyHiddenState(DrawableHitObject hitObject, ArmedState state) + { + } } } diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index f4fe1c3831..a689292ed7 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; using osu.Framework.Timing; @@ -16,9 +16,8 @@ namespace osu.Game.Rulesets.Mods public override void ApplyToClock(IAdjustableClock clock) { - var pitchAdjust = clock as IHasPitchAdjust; - if (pitchAdjust != null) - pitchAdjust.PitchAdjust = 1.5; + if (clock is IHasPitchAdjust pitchAdjust) + pitchAdjust.PitchAdjust *= RateAdjust; else base.ApplyToClock(clock); } diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 223af7d304..5bcba289c6 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Rulesets/Mods/ModNoMod.cs b/osu.Game/Rulesets/Mods/ModNoMod.cs index c75849149b..0ddbd2a8cb 100644 --- a/osu.Game/Rulesets/Mods/ModNoMod.cs +++ b/osu.Game/Rulesets/Mods/ModNoMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mods { diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index b7ded41024..5145f85124 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index 769cde6746..ee59810a94 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 77d411d8fd..26223b24d1 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Rulesets/Mods/ModTimeAdjust.cs b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs new file mode 100644 index 0000000000..513883f552 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModTimeAdjust.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Audio; +using osu.Framework.Timing; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModTimeAdjust : Mod + { + public override Type[] IncompatibleMods => new[] { typeof(ModTimeRamp) }; + + protected abstract double RateAdjust { get; } + + public virtual void ApplyToClock(IAdjustableClock clock) + { + if (clock is IHasTempoAdjust tempo) + tempo.TempoAdjust *= RateAdjust; + else + clock.Rate *= RateAdjust; + } + } +} diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs new file mode 100644 index 0000000000..62407907c1 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -0,0 +1,89 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Audio; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osuTK; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModTimeRamp : Mod + { + public override Type[] IncompatibleMods => new[] { typeof(ModTimeAdjust) }; + + protected abstract double FinalRateAdjustment { get; } + } + + public abstract class ModTimeRamp : ModTimeRamp, IUpdatableByPlayfield, IApplicableToClock, IApplicableToBeatmap + where T : HitObject + { + private double finalRateTime; + + private double beginRampTime; + + private IAdjustableClock clock; + + /// + /// The point in the beatmap at which the final ramping rate should be reached. + /// + private const double final_rate_progress = 0.75f; + + public virtual void ApplyToClock(IAdjustableClock clock) + { + this.clock = clock; + + lastAdjust = 1; + + // for preview purposes. during gameplay, Update will overwrite this setting. + applyAdjustment(1); + } + + public virtual void ApplyToBeatmap(Beatmap beatmap) + { + HitObject lastObject = beatmap.HitObjects.LastOrDefault(); + + beginRampTime = beatmap.HitObjects.FirstOrDefault()?.StartTime ?? 0; + finalRateTime = final_rate_progress * ((lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0); + } + + public virtual void Update(Playfield playfield) + { + applyAdjustment((clock.CurrentTime - beginRampTime) / finalRateTime); + } + + private double lastAdjust = 1; + + /// + /// Adjust the rate along the specified ramp + /// + /// The amount of adjustment to apply (from 0..1). + private void applyAdjustment(double amount) + { + double adjust = 1 + (Math.Sign(FinalRateAdjustment) * MathHelper.Clamp(amount, 0, 1) * Math.Abs(FinalRateAdjustment)); + + switch (clock) + { + case IHasPitchAdjust pitch: + pitch.PitchAdjust /= lastAdjust; + pitch.PitchAdjust *= adjust; + break; + case IHasTempoAdjust tempo: + tempo.TempoAdjust /= lastAdjust; + tempo.TempoAdjust *= adjust; + break; + default: + clock.Rate /= lastAdjust; + clock.Rate *= adjust; + break; + } + + lastAdjust = adjust; + } + } +} diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 9c962bbcd5..cd649728cf 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Mods { diff --git a/osu.Game/Rulesets/Mods/ModWindDown.cs b/osu.Game/Rulesets/Mods/ModWindDown.cs new file mode 100644 index 0000000000..174070eb85 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModWindDown.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mods +{ + public class ModWindDown : ModTimeRamp + where T : HitObject + { + public override string Name => "Wind Down"; + public override string Acronym => "WD"; + public override string Description => "Sloooow doooown..."; + public override FontAwesome Icon => FontAwesome.fa_chevron_circle_down; + public override double ScoreMultiplier => 1.0; + + protected override double FinalRateAdjustment => -0.25; + + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindUp)).ToArray(); + } +} diff --git a/osu.Game/Rulesets/Mods/ModWindUp.cs b/osu.Game/Rulesets/Mods/ModWindUp.cs new file mode 100644 index 0000000000..bf9af8a51d --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModWindUp.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mods +{ + public class ModWindUp : ModTimeRamp + where T : HitObject + { + public override string Name => "Wind Up"; + public override string Acronym => "WU"; + public override string Description => "Can you keep up?"; + public override FontAwesome Icon => FontAwesome.fa_chevron_circle_up; + public override double ScoreMultiplier => 1.0; + + protected override double FinalRateAdjustment => 0.5; + + public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModWindDown)).ToArray(); + } +} diff --git a/osu.Game/Rulesets/Mods/MultiMod.cs b/osu.Game/Rulesets/Mods/MultiMod.cs index 26e09a59e0..f7d574d3c7 100644 --- a/osu.Game/Rulesets/Mods/MultiMod.cs +++ b/osu.Game/Rulesets/Mods/MultiMod.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs index 9a72c44d67..b2d9f50602 100644 --- a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs +++ b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Drawables { diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e0728826df..e1e76f109d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; @@ -124,14 +124,14 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - State.ValueChanged += state => + State.ValueChanged += armed => { - UpdateState(state); + UpdateState(armed.NewValue); // apply any custom state overrides - ApplyCustomUpdateState?.Invoke(this, state); + ApplyCustomUpdateState?.Invoke(this, armed.NewValue); - if (State == ArmedState.Hit) + if (armed.NewValue == ArmedState.Hit) PlaySamples(); }; @@ -220,6 +220,16 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNewResult?.Invoke(this, Result); } + /// + /// Will called at least once after the of this has been passed. + /// + internal void OnLifetimeEnd() + { + foreach (var nested in NestedHitObjects) + nested.OnLifetimeEnd(); + UpdateResult(false); + } + /// /// Processes this , checking if a scoring result has occurred. /// diff --git a/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs index e10b50e672..8f4c95c634 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs index ce365f04bd..48fcfabc2f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; namespace osu.Game.Rulesets.Objects.Drawables diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 010fc450e0..fd542be67d 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs index d44da4e16c..d3c29d90ce 100644 --- a/osu.Game/Rulesets/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects { diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs index 40fb98a997..c5b7686da6 100644 --- a/osu.Game/Rulesets/Objects/HitWindows.cs +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Objects private static readonly IReadOnlyDictionary base_ranges = new Dictionary { { HitResult.Perfect, (44.8, 38.8, 27.8) }, - { HitResult.Great, (128, 98, 68 ) }, + { HitResult.Great, (128, 98, 68) }, { HitResult.Good, (194, 164, 134) }, { HitResult.Ok, (254, 224, 194) }, { HitResult.Meh, (302, 272, 242) }, diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index 0573a08361..febfd3696c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index e8962cd5ec..48f637dfe8 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs index a187caaa26..56790629b4 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index db79ca60f1..0089d1eb88 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; @@ -8,12 +8,14 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasCombo + internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition, IHasCombo { public double EndTime { get; set; } public double Duration => EndTime - StartTime; + public float X => 256; // Required for CatchBeatmapConverter + public bool NewCombo { get; set; } public int ComboOffset { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 85eb29033e..8d6bb8bd3f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using osu.Game.Beatmaps.Formats; using osu.Game.Audio; @@ -46,9 +45,11 @@ namespace osu.Game.Rulesets.Objects.Legacy { string[] split = text.Split(','); - Vector2 pos = new Vector2((int)Convert.ToSingle(split[0], CultureInfo.InvariantCulture), (int)Convert.ToSingle(split[1], CultureInfo.InvariantCulture)); + Vector2 pos = new Vector2((int)Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE)); - ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]); + double startTime = Parsing.ParseDouble(split[2]) + Offset; + + ConvertHitObjectType type = (ConvertHitObjectType)Parsing.ParseInt(split[3]); int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; type &= ~ConvertHitObjectType.ComboOffset; @@ -56,7 +57,7 @@ namespace osu.Game.Rulesets.Objects.Legacy bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); type &= ~ConvertHitObjectType.NewCombo; - var soundType = (LegacySoundType)int.Parse(split[4]); + var soundType = (LegacySoundType)Parsing.ParseInt(split[4]); var bankInfo = new SampleBankInfo(); HitObject result = null; @@ -107,7 +108,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } string[] temp = t.Split(':'); - points[pointIndex++] = new Vector2((int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture), (int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture)) - pos; + points[pointIndex++] = new Vector2((int)Parsing.ParseDouble(temp[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(temp[1], Parsing.MAX_COORDINATE_VALUE)) - pos; } // osu-stable special-cased colinear perfect curves to a CurveType.Linear @@ -116,7 +117,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points)) pathType = PathType.Linear; - int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture); + int repeatCount = Parsing.ParseInt(split[6]); if (repeatCount > 9000) throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high"); @@ -124,9 +125,8 @@ namespace osu.Game.Rulesets.Objects.Legacy // osu-stable treated the first span of the slider as a repeat, but no repeats are happening repeatCount = Math.Max(0, repeatCount - 1); - if (split.Length > 7) - length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture); + length = Math.Max(0, Parsing.ParseDouble(split[7])); if (split.Length > 10) readCustomSampleBanks(split[10], bankInfo); @@ -185,7 +185,9 @@ namespace osu.Game.Rulesets.Objects.Legacy } else if (type.HasFlag(ConvertHitObjectType.Spinner)) { - result = CreateSpinner(new Vector2(512, 384) / 2, combo, comboOffset, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + Offset); + double endTime = Math.Max(startTime, Parsing.ParseDouble(split[5]) + Offset); + + result = CreateSpinner(new Vector2(512, 384) / 2, combo, comboOffset, endTime); if (split.Length > 6) readCustomSampleBanks(split[6], bankInfo); @@ -194,12 +196,12 @@ namespace osu.Game.Rulesets.Objects.Legacy { // Note: Hold is generated by BMS converts - double endTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture); + double endTime = Math.Max(startTime, Parsing.ParseDouble(split[2])); if (split.Length > 5 && !string.IsNullOrEmpty(split[5])) { string[] ss = split[5].Split(':'); - endTime = Convert.ToDouble(ss[0], CultureInfo.InvariantCulture); + endTime = Math.Max(startTime, Parsing.ParseDouble(ss[0])); readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); } @@ -212,7 +214,7 @@ namespace osu.Game.Rulesets.Objects.Legacy return null; } - result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + Offset; + result.StartTime = startTime; if (result.Samples.Count == 0) result.Samples = convertSoundType(soundType, bankInfo); @@ -223,8 +225,14 @@ namespace osu.Game.Rulesets.Objects.Legacy } catch (FormatException) { - throw new FormatException("One or more hit objects were malformed."); + Logger.Log("A hitobject could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); } + catch (OverflowException) + { + Logger.Log("A hitobject could not be parsed correctly and will be ignored", LoggingTarget.Runtime, LogLevel.Important); + } + + return null; } private void readCustomSampleBanks(string str, SampleBankInfo bankInfo) @@ -234,8 +242,8 @@ namespace osu.Game.Rulesets.Objects.Legacy string[] split = str.Split(':'); - var bank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[0]); - var addbank = (LegacyBeatmapDecoder.LegacySampleBank)int.Parse(split[1]); + var bank = (LegacyBeatmapDecoder.LegacySampleBank)Parsing.ParseInt(split[0]); + var addbank = (LegacyBeatmapDecoder.LegacySampleBank)Parsing.ParseInt(split[1]); string stringBank = bank.ToString().ToLowerInvariant(); if (stringBank == @"none") @@ -248,10 +256,10 @@ namespace osu.Game.Rulesets.Objects.Legacy bankInfo.Add = string.IsNullOrEmpty(stringAddBank) ? stringBank : stringAddBank; if (split.Length > 2) - bankInfo.CustomSampleBank = int.Parse(split[2]); + bankInfo.CustomSampleBank = Parsing.ParseInt(split[2]); if (split.Length > 3) - bankInfo.Volume = int.Parse(split[3]); + bankInfo.Volume = Math.Max(0, Parsing.ParseInt(split[3])); bankInfo.Filename = split.Length > 4 ? split[4] : null; } @@ -302,7 +310,16 @@ namespace osu.Game.Rulesets.Objects.Legacy { // Todo: This should return the normal SampleInfos if the specified sample file isn't found, but that's a pretty edge-case scenario if (!string.IsNullOrEmpty(bankInfo.Filename)) - return new List { new FileSampleInfo { Filename = bankInfo.Filename } }; + { + return new List + { + new FileSampleInfo + { + Filename = bankInfo.Filename, + Volume = bankInfo.Volume + } + }; + } var soundTypes = new List { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs index fa47e56de7..c9f7224643 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Objects.Legacy Slider = 1 << 1, NewCombo = 1 << 2, Spinner = 1 << 3, - ComboOffset = 1 << 4 | 1 << 5 | 1 << 6, + ComboOffset = (1 << 4) | (1 << 5) | (1 << 6), Hold = 1 << 7 } } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 0512a97354..bb1a5e200d 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index cbc8d2d4df..06fde576d2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index b81fed9f03..8a3e232e60 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Audio; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 86a10fd363..096c07f7d2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index e1572889a3..226d91bb86 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index 5a443c2ac2..eb20fa67f1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index c8d10816bd..84b66a4c26 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index f65452858a..b98de32bd0 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index bceca0675e..c850feb189 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 49f27b01f6..e5a8884aa2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 66e504bf22..5cecc2a59f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Legacy.Taiko { diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 16ed49ce2b..bab21b31ad 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 11c0a2baae..5cedc6e2e5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Legacy.Taiko { diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 4c8807a1d3..ca9fdd53ed 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/SliderEventGenerator.cs b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs new file mode 100644 index 0000000000..7cda7485f9 --- /dev/null +++ b/osu.Game/Rulesets/Objects/SliderEventGenerator.cs @@ -0,0 +1,148 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osuTK; + +namespace osu.Game.Rulesets.Objects +{ + public static class SliderEventGenerator + { + public static IEnumerable Generate(double startTime, double spanDuration, double velocity, double tickDistance, double totalDistance, int spanCount, double? legacyLastTickOffset) + { + // A very lenient maximum length of a slider for ticks to be generated. + // This exists for edge cases such as /b/1573664 where the beatmap has been edited by the user, and should never be reached in normal usage. + const double max_length = 100000; + + var length = Math.Min(max_length, totalDistance); + tickDistance = MathHelper.Clamp(tickDistance, 0, length); + + var minDistanceFromEnd = velocity * 10; + + yield return new SliderEventDescriptor + { + Type = SliderEventType.Head, + SpanIndex = 0, + SpanStartTime = startTime, + Time = startTime, + PathProgress = 0, + }; + + if (tickDistance != 0) + { + for (var span = 0; span < spanCount; span++) + { + var spanStartTime = startTime + span * spanDuration; + var reversed = span % 2 == 1; + + for (var d = tickDistance; d <= length; d += tickDistance) + { + if (d >= length - minDistanceFromEnd) + break; + + var pathProgress = d / length; + var timeProgress = reversed ? 1 - pathProgress : pathProgress; + + yield return new SliderEventDescriptor + { + Type = SliderEventType.Tick, + SpanIndex = span, + SpanStartTime = spanStartTime, + Time = spanStartTime + timeProgress * spanDuration, + PathProgress = pathProgress, + }; + } + + if (span < spanCount - 1) + { + yield return new SliderEventDescriptor + { + Type = SliderEventType.Repeat, + SpanIndex = span, + SpanStartTime = startTime + span * spanDuration, + Time = spanStartTime + spanDuration, + PathProgress = (span + 1) % 2, + }; + } + } + } + + double totalDuration = spanCount * spanDuration; + + // Okay, I'll level with you. I made a mistake. It was 2007. + // Times were simpler. osu! was but in its infancy and sliders were a new concept. + // A hack was made, which has unfortunately lived through until this day. + // + // This legacy tick is used for some calculations and judgements where audio output is not required. + // Generally we are keeping this around just for difficulty compatibility. + // Optimistically we do not want to ever use this for anything user-facing going forwards. + + int finalSpanIndex = spanCount - 1; + double finalSpanStartTime = startTime + finalSpanIndex * spanDuration; + double finalSpanEndTime = Math.Max(startTime + totalDuration / 2, (finalSpanStartTime + spanDuration) - (legacyLastTickOffset ?? 0)); + double finalProgress = (finalSpanEndTime - finalSpanStartTime) / spanDuration; + + if (spanCount % 2 == 0) finalProgress = 1 - finalProgress; + + yield return new SliderEventDescriptor + { + Type = SliderEventType.LegacyLastTick, + SpanIndex = finalSpanIndex, + SpanStartTime = finalSpanStartTime, + Time = finalSpanEndTime, + PathProgress = finalProgress, + }; + + yield return new SliderEventDescriptor + { + Type = SliderEventType.Tail, + SpanIndex = finalSpanIndex, + SpanStartTime = startTime + (spanCount - 1) * spanDuration, + Time = startTime + totalDuration, + PathProgress = spanCount % 2, + }; + } + } + + /// + /// Describes a point in time on a slider given special meaning. + /// Should be used by rulesets to visualise the slider. + /// + public struct SliderEventDescriptor + { + /// + /// The type of event. + /// + public SliderEventType Type; + + /// + /// The time of this event. + /// + public double Time; + + /// + /// The zero-based index of the span. In the case of repeat sliders, this will increase after each . + /// + public int SpanIndex; + + /// + /// The time at which the contained begins. + /// + public double SpanStartTime; + + /// + /// The progress along the slider's at which this event occurs. + /// + public double PathProgress; + } + + public enum SliderEventType + { + Tick, + LegacyLastTick, + Head, + Tail, + Repeat + } +} diff --git a/osu.Game/Rulesets/Objects/SliderPath.cs b/osu.Game/Rulesets/Objects/SliderPath.cs index fe38fd4f65..1e9767a54f 100644 --- a/osu.Game/Rulesets/Objects/SliderPath.cs +++ b/osu.Game/Rulesets/Objects/SliderPath.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -125,6 +125,7 @@ namespace osu.Game.Rulesets.Objects { if (isInitialised) return; + isInitialised = true; controlPoints = controlPoints ?? Array.Empty(); @@ -280,6 +281,7 @@ namespace osu.Game.Rulesets.Objects public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; + return obj is SliderPath other && Equals(other); } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs index 95f1a1cb3d..d1a4683a1d 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs index a3dded94ec..e07da93a3a 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasComboInformation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs index a6e2c15f5a..e98a888bd7 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; diff --git a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs index 535eb21ff4..e7f552115e 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs index 8383e879a3..516f1002a4 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasHold.cs b/osu.Game/Rulesets/Objects/Types/IHasHold.cs index 429c582bab..469b8b7892 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasHold.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasHold.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs b/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs index ab2573e933..caf22c3023 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasLegacyLastTickOffset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs index d14e4cc1fb..8948fe59a9 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index ea8784db47..8be95c063d 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Audio; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs index 49b1d7cb28..7e55b21050 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs index 8ec7ab39fe..d2561b10a7 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Objects/Types/PathType.cs b/osu.Game/Rulesets/Objects/Types/PathType.cs index 5156302fe1..923ce9eba4 100644 --- a/osu.Game/Rulesets/Objects/Types/PathType.cs +++ b/osu.Game/Rulesets/Objects/Types/PathType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Objects.Types { diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index 1b6f17a5e4..1d4cdbf04c 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -1,14 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Objects; using osu.Game.Beatmaps; using osu.Game.Replays; namespace osu.Game.Rulesets.Replays { - public abstract class AutoGenerator : IAutoGenerator - where T : HitObject + public abstract class AutoGenerator : IAutoGenerator { /// /// Creates the auto replay and returns it. @@ -21,11 +19,11 @@ namespace osu.Game.Rulesets.Replays /// /// The beatmap we're making. /// - protected Beatmap Beatmap; + protected IBeatmap Beatmap; #endregion - protected AutoGenerator(Beatmap beatmap) + protected AutoGenerator(IBeatmap beatmap) { Beatmap = beatmap; } diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index abe1a1520d..c89ac59e10 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -99,6 +99,7 @@ namespace osu.Game.Rulesets.Replays // that would occur as a result of this frame in forward playback if (currentDirection == -1) return CurrentTime = CurrentFrame.Time - 1; + return CurrentTime = CurrentFrame.Time; } } diff --git a/osu.Game/Rulesets/Replays/IAutoGenerator.cs b/osu.Game/Rulesets/Replays/IAutoGenerator.cs index 90aea199c8..b1905e2b6f 100644 --- a/osu.Game/Rulesets/Replays/IAutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/IAutoGenerator.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Replays; diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index fedab8053f..85e068ae79 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.Replays { diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index 9ece4b80d5..7ecdc0715b 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Replays.Legacy; diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 53e3e40374..feac49ca2c 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets /// An enumerable of constructed s public virtual IEnumerable ConvertLegacyMods(LegacyMods mods) => new Mod[] { }; - public Mod GetAutoplayMod() => GetAllMods().First(mod => mod is ModAutoplay); + public ModAutoplay GetAutoplayMod() => GetAllMods().OfType().First(); protected Ruleset(RulesetInfo rulesetInfo = null) { @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets /// The beatmap to create the hit renderer for. /// Unable to successfully load the beatmap to be usable with this ruleset. /// - public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap); + public abstract DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap); /// /// Creates a to convert a to one that is applicable for this . diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs index 7e83ba0961..4ac866fc90 100644 --- a/osu.Game/Rulesets/RulesetConfigCache.cs +++ b/osu.Game/Rulesets/RulesetConfigCache.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 6c21b9fd2f..ca331ec339 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 513173ef2f..0ebadd73d2 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll")) + foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll") + .Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } @@ -124,7 +125,7 @@ namespace osu.Game.Rulesets } catch (Exception e) { - Logger.Error(e, "Failed to load ruleset"); + Logger.Error(e, $"Failed to load ruleset {filename}"); } } } diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 98874a4890..2376f12e9e 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4b3012192d..0fddb19a6c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Create a for this processor. /// - protected virtual HitWindows CreateHitWindows() => new HitWindows(); + public virtual HitWindows CreateHitWindows() => new HitWindows(); /// /// The current rank. @@ -113,6 +113,7 @@ namespace osu.Game.Rulesets.Scoring return ScoreRank.B; if (acc > 0.7) return ScoreRank.C; + return ScoreRank.D; } @@ -168,11 +169,11 @@ namespace osu.Game.Rulesets.Scoring /// public virtual void PopulateScore(ScoreInfo score) { - score.TotalScore = (int)Math.Round(TotalScore); - score.Combo = Combo; - score.MaxCombo = HighestCombo; - score.Accuracy = Math.Round(Accuracy, 4); - score.Rank = Rank; + score.TotalScore = (long)Math.Round(TotalScore.Value); + score.Combo = Combo.Value; + score.MaxCombo = HighestCombo.Value; + score.Accuracy = Math.Round(Accuracy.Value, 4); + score.Rank = Rank.Value; score.Date = DateTimeOffset.Now; var hitWindows = CreateHitWindows(); @@ -209,15 +210,15 @@ namespace osu.Game.Rulesets.Scoring { } - public ScoreProcessor(RulesetContainer rulesetContainer) + public ScoreProcessor(DrawableRuleset drawableRuleset) { Debug.Assert(base_portion + combo_portion == 1.0); - rulesetContainer.OnNewResult += applyResult; - rulesetContainer.OnRevertResult += revertResult; + drawableRuleset.OnNewResult += applyResult; + drawableRuleset.OnRevertResult += revertResult; - ApplyBeatmap(rulesetContainer.Beatmap); - SimulateAutoplay(rulesetContainer.Beatmap); + ApplyBeatmap(drawableRuleset.Beatmap); + SimulateAutoplay(drawableRuleset.Beatmap); Reset(true); if (maxBaseScore == 0 || maxHighestCombo == 0) @@ -298,8 +299,8 @@ namespace osu.Game.Rulesets.Scoring /// The to apply. protected virtual void ApplyResult(JudgementResult result) { - result.ComboAtJudgement = Combo; - result.HighestComboAtJudgement = HighestCombo; + result.ComboAtJudgement = Combo.Value; + result.HighestComboAtJudgement = HighestCombo.Value; JudgedHits++; @@ -371,10 +372,10 @@ namespace osu.Game.Rulesets.Scoring { default: case ScoringMode.Standardised: - return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; + return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo.Value / maxHighestCombo) + bonusScore; case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) - return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); + return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) / 25); } } @@ -389,7 +390,7 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { MaxHits = JudgedHits; - maxHighestCombo = HighestCombo; + maxHighestCombo = HighestCombo.Value; maxBaseScore = baseScore; } diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 4988bac5ce..9bab065d1e 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs similarity index 61% rename from osu.Game/Rulesets/UI/RulesetContainer.cs rename to osu.Game/Rulesets/UI/DrawableRuleset.cs index c8c7f3154b..31c0afd743 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -13,26 +13,28 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; +using osu.Framework.Input.Events; using osu.Game.Configuration; +using osu.Game.Graphics.Cursor; using osu.Game.Input.Handlers; using osu.Game.Overlays; using osu.Game.Replays; using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; +using osu.Game.Screens.Play; namespace osu.Game.Rulesets.UI { /// - /// Base RulesetContainer. Doesn't hold objects. - /// - /// Should not be derived - derive instead. - /// + /// Displays an interactive ruleset gameplay instance. /// - public abstract class RulesetContainer : Container + /// The type of HitObject contained by this DrawableRuleset. + public abstract class DrawableRuleset : DrawableRuleset, IProvideCursor, ICanAttachKeyCounter + where TObject : HitObject { /// /// The selected variant. @@ -40,27 +42,11 @@ namespace osu.Game.Rulesets.UI public virtual int Variant => 0; /// - /// The input manager for this RulesetContainer. - /// - internal IHasReplayHandler ReplayInputManager => KeyBindingInputManager as IHasReplayHandler; - - /// - /// The key conversion input manager for this RulesetContainer. + /// The key conversion input manager for this DrawableRuleset. /// public PassThroughInputManager KeyBindingInputManager; - /// - /// Whether a replay is currently loaded. - /// - public readonly BindableBool HasReplayLoaded = new BindableBool(); - - public abstract IEnumerable Objects { get; } - - /// - /// The point in time at which gameplay starts, including any required lead-in for display purposes. - /// Defaults to two seconds before the first . Override as necessary. - /// - public virtual double GameplayStartTime => Objects.First().StartTime - 2000; + public override double GameplayStartTime => Objects.First().StartTime - 2000; private readonly Lazy playfield; @@ -72,37 +58,63 @@ namespace osu.Game.Rulesets.UI /// /// Place to put drawables above hit objects but below UI. /// - public Container Overlays { get; protected set; } + public Container Overlays { get; private set; } /// - /// The cursor provided by this . May be null if no cursor is provided. + /// Invoked when a has been applied by a . /// - public readonly CursorContainer Cursor; + public event Action OnNewResult; - public readonly Ruleset Ruleset; + /// + /// Invoked when a is being reverted by a . + /// + public event Action OnRevertResult; + + /// + /// The beatmap. + /// + public Beatmap Beatmap; + + public override IEnumerable Objects => Beatmap.HitObjects; protected IRulesetConfigManager Config { get; private set; } + /// + /// The mods which are to be applied. + /// + private readonly IEnumerable mods; + + private FrameStabilityContainer frameStabilityContainer; + private OnScreenDisplay onScreenDisplay; /// - /// A visual representation of a . + /// Creates a ruleset visualisation for the provided ruleset and beatmap. /// - /// The ruleset being repesented. - protected RulesetContainer(Ruleset ruleset) + /// The ruleset being represented. + /// The beatmap to create the hit renderer for. + protected DrawableRuleset(Ruleset ruleset, WorkingBeatmap workingBeatmap) + : base(ruleset) { - Ruleset = ruleset; + Debug.Assert(workingBeatmap != null, "DrawableRuleset initialized with a null beatmap."); + + RelativeSizeAxes = Axes.Both; + + Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo); + + mods = workingBeatmap.Mods.Value; + applyBeatmapMods(mods); + + KeyBindingInputManager = CreateInputManager(); playfield = new Lazy(CreatePlayfield); IsPaused.ValueChanged += paused => { - if (HasReplayLoaded) + if (HasReplayLoaded.Value) return; - KeyBindingInputManager.UseParentInput = !paused; + KeyBindingInputManager.UseParentInput = !paused.NewValue; }; - - Cursor = CreateCursor(); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -121,159 +133,103 @@ namespace osu.Game.Rulesets.UI return dependencies; } - public abstract ScoreProcessor CreateScoreProcessor(); + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + KeyBindingInputManager.AddRange(new Drawable[] + { + Playfield + }); + + InternalChildren = new Drawable[] + { + frameStabilityContainer = new FrameStabilityContainer + { + Child = KeyBindingInputManager, + }, + Overlays = new Container { RelativeSizeAxes = Axes.Both } + }; + + applyRulesetMods(mods, config); + + loadObjects(); + } + + /// + /// Creates and adds drawable representations of hit objects to the play field. + /// + private void loadObjects() + { + foreach (TObject h in Beatmap.HitObjects) + addRepresentation(h); + + Playfield.PostProcess(); + + foreach (var mod in mods.OfType()) + mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); + } + + public override void RequestResume(Action continueResume) => continueResume(); + + /// + /// Creates and adds the visual representation of a to this . + /// + /// The to add the visual representation for. + private void addRepresentation(TObject hitObject) + { + var drawableObject = GetVisualRepresentation(hitObject); + + if (drawableObject == null) + return; + + drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r); + drawableObject.OnRevertResult += (_, r) => OnRevertResult?.Invoke(r); + + Playfield.Add(drawableObject); + } + + public override void SetReplayScore(Score replayScore) + { + if (!(KeyBindingInputManager is IHasReplayHandler replayInputManager)) + throw new InvalidOperationException($"A {nameof(KeyBindingInputManager)} which supports replay loading is not available"); + + var handler = (ReplayScore = replayScore) != null ? CreateReplayInputHandler(replayScore.Replay) : null; + + replayInputManager.ReplayInputHandler = handler; + frameStabilityContainer.ReplayInputHandler = handler; + + HasReplayLoaded.Value = replayInputManager.ReplayInputHandler != null; + + if (replayInputManager.ReplayInputHandler != null) + replayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace; + } + + /// + /// Creates a DrawableHitObject from a HitObject. + /// + /// The HitObject to make drawable. + /// The DrawableHitObject. + public abstract DrawableHitObject GetVisualRepresentation(TObject h); + + public void Attach(KeyCounterCollection keyCounter) => + (KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(keyCounter); /// /// Creates a key conversion input manager. An exception will be thrown if a valid is not returned. /// /// The input manager. - public abstract PassThroughInputManager CreateInputManager(); + protected abstract PassThroughInputManager CreateInputManager(); protected virtual ReplayInputHandler CreateReplayInputHandler(Replay replay) => null; - public Score ReplayScore { get; private set; } - - /// - /// Whether the game is paused. Used to block user input. - /// - public readonly BindableBool IsPaused = new BindableBool(); - - /// - /// Sets a replay to be used, overriding local input. - /// - /// The replay, null for local input. - public virtual void SetReplayScore(Score replayScore) - { - if (ReplayInputManager == null) - throw new InvalidOperationException($"A {nameof(KeyBindingInputManager)} which supports replay loading is not available"); - - ReplayScore = replayScore; - ReplayInputManager.ReplayInputHandler = replayScore != null ? CreateReplayInputHandler(replayScore.Replay) : null; - - HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null; - } - - /// - /// Creates the cursor. May be null if the doesn't provide a custom cursor. - /// - protected virtual CursorContainer CreateCursor() => null; - /// /// Creates a Playfield. /// /// The Playfield. protected abstract Playfield CreatePlayfield(); - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (Config != null) - { - onScreenDisplay?.StopTracking(this, Config); - Config = null; - } - } - } - - /// - /// RulesetContainer that applies conversion to Beatmaps. Does not contain a Playfield - /// and does not load drawable hit objects. - /// - /// Should not be derived - derive instead. - /// - /// - /// The type of HitObject contained by this RulesetContainer. - public abstract class RulesetContainer : RulesetContainer - where TObject : HitObject - { - /// - /// Invoked when a has been applied by a . - /// - public event Action OnNewResult; - - /// - /// Invoked when a is being reverted by a . - /// - public event Action OnRevertResult; - - /// - /// The Beatmap - /// - public Beatmap Beatmap; - - /// - /// All the converted hit objects contained by this hit renderer. - /// - public override IEnumerable Objects => Beatmap.HitObjects; - - /// - /// The mods which are to be applied. - /// - protected IEnumerable Mods; - - /// - /// The this was created with. - /// - protected readonly WorkingBeatmap WorkingBeatmap; - public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); - protected override Container Content => content; - private Container content; - - /// - /// Whether to assume the beatmap passed into this is for the current ruleset. - /// Creates a hit renderer for a beatmap. - /// - /// The ruleset being repesented. - /// The beatmap to create the hit renderer for. - protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap) - : base(ruleset) - { - Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap."); - - WorkingBeatmap = workingBeatmap; - // ReSharper disable once PossibleNullReferenceException - Mods = workingBeatmap.Mods.Value; - - RelativeSizeAxes = Axes.Both; - - Beatmap = (Beatmap)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo); - - KeyBindingInputManager = CreateInputManager(); - KeyBindingInputManager.RelativeSizeAxes = Axes.Both; - - applyBeatmapMods(Mods); - } - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - KeyBindingInputManager.Children = new Drawable[] - { - content = new Container - { - RelativeSizeAxes = Axes.Both, - }, - Playfield - }; - - if (Cursor != null) - KeyBindingInputManager.Add(Cursor); - - InternalChildren = new Drawable[] - { - KeyBindingInputManager, - Overlays = new Container { RelativeSizeAxes = Axes.Both } - }; - - // Apply mods - applyRulesetMods(Mods, config); - - loadObjects(); - } - /// /// Applies the active mods to the Beatmap. /// @@ -288,7 +244,7 @@ namespace osu.Game.Rulesets.UI } /// - /// Applies the active mods to this RulesetContainer. + /// Applies the active mods to this DrawableRuleset. /// /// private void applyRulesetMods(IEnumerable mods, OsuConfigManager config) @@ -296,83 +252,108 @@ namespace osu.Game.Rulesets.UI if (mods == null) return; - foreach (var mod in mods.OfType>()) - mod.ApplyToRulesetContainer(this); + foreach (var mod in mods.OfType>()) + mod.ApplyToDrawableRuleset(this); foreach (var mod in mods.OfType()) mod.ReadFromConfig(config); } - public override void SetReplayScore(Score replayScore) + #region IProvideCursor + + protected override bool OnHover(HoverEvent e) => true; // required for IProvideCursor + + public override CursorContainer Cursor => Playfield.Cursor; + + public bool ProvidingUserCursor => Playfield.Cursor != null && !HasReplayLoaded.Value; + + #endregion + + protected override void Dispose(bool isDisposing) { - base.SetReplayScore(replayScore); + base.Dispose(isDisposing); - if (ReplayInputManager?.ReplayInputHandler != null) - ReplayInputManager.ReplayInputHandler.GamefieldToScreenSpace = Playfield.GamefieldToScreenSpace; + if (Config != null) + { + onScreenDisplay?.StopTracking(this, Config); + Config = null; + } } - - /// - /// Creates and adds drawable representations of hit objects to the play field. - /// - private void loadObjects() - { - foreach (TObject h in Beatmap.HitObjects) - AddRepresentation(h); - - Playfield.PostProcess(); - - foreach (var mod in Mods.OfType()) - mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); - } - - /// - /// Creates and adds the visual representation of a to this . - /// - /// The to add the visual representation for. - internal void AddRepresentation(TObject hitObject) - { - var drawableObject = GetVisualRepresentation(hitObject); - - if (drawableObject == null) - return; - - drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r); - drawableObject.OnRevertResult += (_, r) => OnRevertResult?.Invoke(r); - - Playfield.Add(drawableObject); - } - - /// - /// Creates a DrawableHitObject from a HitObject. - /// - /// The HitObject to make drawable. - /// The DrawableHitObject. - public abstract DrawableHitObject GetVisualRepresentation(TObject h); } /// - /// A derivable RulesetContainer that manages the Playfield and HitObjects. + /// Displays an interactive ruleset gameplay instance. + /// + /// This type is required only for adding non-generic type to the draw hierarchy. + /// Once IDrawable is a thing, this can also become an interface. + /// /// - /// The type of Playfield contained by this RulesetContainer. - /// The type of HitObject contained by this RulesetContainer. - public abstract class RulesetContainer : RulesetContainer - where TObject : HitObject - where TPlayfield : Playfield + public abstract class DrawableRuleset : CompositeDrawable { /// - /// The playfield. + /// Whether a replay is currently loaded. /// - protected new TPlayfield Playfield => (TPlayfield)base.Playfield; + public readonly BindableBool HasReplayLoaded = new BindableBool(); /// - /// Creates a hit renderer for a beatmap. + /// Whether the game is paused. Used to block user input. /// - /// The ruleset being repesented. - /// The beatmap to create the hit renderer for. - protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) - : base(ruleset, beatmap) + public readonly BindableBool IsPaused = new BindableBool(); + + /// ~ + /// The associated ruleset. + /// + public readonly Ruleset Ruleset; + + /// + /// Creates a ruleset visualisation for the provided ruleset. + /// + /// The ruleset. + internal DrawableRuleset(Ruleset ruleset) { + Ruleset = ruleset; } + + /// + /// All the converted hit objects contained by this hit renderer. + /// + public abstract IEnumerable Objects { get; } + + /// + /// The point in time at which gameplay starts, including any required lead-in for display purposes. + /// Defaults to two seconds before the first . Override as necessary. + /// + public abstract double GameplayStartTime { get; } + + /// + /// The currently loaded replay. Usually null in the case of a local player. + /// + public Score ReplayScore { get; protected set; } + + /// + /// The cursor being displayed by the . May be null if no cursor is provided. + /// + public abstract CursorContainer Cursor { get; } + + /// + /// Sets a replay to be used, overriding local input. + /// + /// The replay, null for local input. + public abstract void SetReplayScore(Score replayScore); + + /// + /// Invoked when the interactive user requests resuming from a paused state. + /// Allows potentially delaying the resume process until an interaction is performed. + /// + /// The action to run when resuming is to be completed. + public abstract void RequestResume(Action continueResume); + + /// + /// Create a for the associated ruleset and link with this + /// . + /// + /// A score processor. + public abstract ScoreProcessor CreateScoreProcessor(); } public class BeatmapInvalidForRulesetException : ArgumentException diff --git a/osu.Game/Rulesets/UI/FrameStabilityContainer.cs b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs new file mode 100644 index 0000000000..161e7aecb4 --- /dev/null +++ b/osu.Game/Rulesets/UI/FrameStabilityContainer.cs @@ -0,0 +1,153 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Input.Handlers; +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.UI +{ + /// + /// A container which consumes a parent gameplay clock and standardises frame counts for children. + /// Will ensure a minimum of 40 frames per clock second is maintained, regardless of any system lag or seeks. + /// + public class FrameStabilityContainer : Container, IHasReplayHandler + { + public FrameStabilityContainer() + { + RelativeSizeAxes = Axes.Both; + gameplayClock = new GameplayClock(framedClock = new FramedClock(manualClock = new ManualClock())); + } + + private readonly ManualClock manualClock; + + private readonly FramedClock framedClock; + + [Cached] + private GameplayClock gameplayClock; + + private IFrameBasedClock parentGameplayClock; + + [BackgroundDependencyLoader(true)] + private void load(GameplayClock clock) + { + if (clock != null) + parentGameplayClock = clock; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + setClock(); + } + + /// + /// Whether we are running up-to-date with our parent clock. + /// If not, we will need to keep processing children until we catch up. + /// + private bool requireMoreUpdateLoops; + + /// + /// Whether we are in a valid state (ie. should we keep processing children frames). + /// This should be set to false when the replay is, for instance, waiting for future frames to arrive. + /// + private bool validState; + + protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState; + + private bool isAttached => ReplayInputHandler != null; + + private const int max_catch_up_updates_per_frame = 50; + + private const double sixty_frame_time = 1000.0 / 60; + + public override bool UpdateSubTree() + { + requireMoreUpdateLoops = true; + validState = true; + + int loops = 0; + + while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) + { + updateClock(); + + if (validState) + { + base.UpdateSubTree(); + UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); + } + } + + return true; + } + + private void updateClock() + { + if (parentGameplayClock == null) + setClock(); // LoadComplete may not be run yet, but we still want the clock. + + validState = true; + + manualClock.Rate = parentGameplayClock.Rate; + manualClock.IsRunning = parentGameplayClock.IsRunning; + + var newProposedTime = parentGameplayClock.CurrentTime; + + try + { + if (Math.Abs(manualClock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) + { + newProposedTime = manualClock.Rate > 0 + ? Math.Min(newProposedTime, manualClock.CurrentTime + sixty_frame_time) + : Math.Max(newProposedTime, manualClock.CurrentTime - sixty_frame_time); + } + + if (!isAttached) + { + manualClock.CurrentTime = newProposedTime; + } + else + { + double? newTime = ReplayInputHandler.SetFrameFromTime(newProposedTime); + + if (newTime == null) + { + // we shouldn't execute for this time value. probably waiting on more replay data. + validState = false; + + requireMoreUpdateLoops = true; + manualClock.CurrentTime = newProposedTime; + return; + } + + manualClock.CurrentTime = newTime.Value; + } + + requireMoreUpdateLoops = manualClock.CurrentTime != parentGameplayClock.CurrentTime; + } + finally + { + // The manual clock time has changed in the above code. The framed clock now needs to be updated + // to ensure that the its time is valid for our children before input is processed + framedClock.ProcessFrame(); + } + } + + private void setClock() + { + // in case a parent gameplay clock isn't available, just use the parent clock. + if (parentGameplayClock == null) + parentGameplayClock = Clock; + + Clock = gameplayClock; + ProcessCustomClock = false; + } + + public ReplayInputHandler ReplayInputHandler { get; set; } + } +} diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 261132c56b..2f3a384e95 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.UI { - public class HitObjectContainer : CompositeDrawable + public class HitObjectContainer : LifetimeManagementContainer { public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); public IEnumerable AliveObjects => AliveInternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); @@ -31,5 +31,11 @@ namespace osu.Game.Rulesets.UI int i = yObj.HitObject.StartTime.CompareTo(xObj.HitObject.StartTime); return i == 0 ? CompareReverseChildID(x, y) : i; } + + protected override void OnChildLifetimeBoundaryCrossed(LifetimeBoundaryCrossedEvent e) + { + if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward && e.Child is DrawableHitObject hitObject) + hitObject.OnLifetimeEnd(); + } } } diff --git a/osu.Game/Rulesets/UI/JudgementContainer.cs b/osu.Game/Rulesets/UI/JudgementContainer.cs index e0d62aba30..f1a68a0323 100644 --- a/osu.Game/Rulesets/UI/JudgementContainer.cs +++ b/osu.Game/Rulesets/UI/JudgementContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index b5c8da8879..9f80dea9f7 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK.Graphics; @@ -22,8 +22,8 @@ namespace osu.Game.Rulesets.UI public FontAwesome Icon { - get { return modIcon.Icon; } - set { modIcon.Icon = value; } + get => modIcon.Icon; + set => modIcon.Icon = value; } private readonly ModType type; @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.UI public bool Highlighted { - get { return highlighted; } + get => highlighted; set { diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 1e9a19ae70..78d14a27e3 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -7,9 +7,10 @@ using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osuTK; @@ -60,9 +61,13 @@ namespace osu.Game.Rulesets.UI private WorkingBeatmap beatmap; [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) + private void load(IBindable beatmap) { this.beatmap = beatmap.Value; + + Cursor = CreateCursor(); + if (Cursor != null) + CursorTargetContainer.Add(Cursor); } /// @@ -82,6 +87,23 @@ namespace osu.Game.Rulesets.UI /// The DrawableHitObject to remove. public virtual bool Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); + /// + /// The cursor currently being used by this . May be null if no cursor is provided. + /// + public CursorContainer Cursor { get; private set; } + + /// + /// Provide an optional cursor which is to be used for gameplay. + /// If providing a cursor, must also point to a valid target container. + /// + /// The cursor, or null if a cursor is not rqeuired. + protected virtual CursorContainer CreateCursor() => null; + + /// + /// The target container to add the cursor after it is created. + /// + protected virtual Container CursorTargetContainer => null; + /// /// Registers a as a nested . /// This does not add the to the draw hierarchy. diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index a76942e3fa..e303166774 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -11,7 +11,6 @@ using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Input.StateChanges.Events; using osu.Framework.Input.States; -using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Input.Bindings; using osu.Game.Input.Handlers; @@ -27,14 +26,6 @@ namespace osu.Game.Rulesets.UI public abstract class RulesetInputManager : PassThroughInputManager, ICanAttachKeyCounter, IHasReplayHandler where T : struct { - public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer - { - public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) - : base(ruleset, variant, unique) - { - } - } - protected override InputState CreateInitialState() { var state = base.CreateInitialState(); @@ -50,6 +41,12 @@ namespace osu.Game.Rulesets.UI InternalChild = KeyBindingContainer = CreateKeyBindingContainer(ruleset, variant, unique); } + [BackgroundDependencyLoader(true)] + private void load(OsuConfigManager config) + { + mouseDisabled = config.GetBindable(OsuSetting.MouseDisableButtons); + } + #region Action mapping (for replays) public override void HandleInputStateChange(InputStateChangeEvent inputStateChange) @@ -91,121 +88,10 @@ namespace osu.Game.Rulesets.UI #endregion - #region Clock control - - private ManualClock clock; - private IFrameBasedClock parentClock; - - protected override void LoadComplete() - { - base.LoadComplete(); - - //our clock will now be our parent's clock, but we want to replace this to allow manual control. - parentClock = Clock; - - ProcessCustomClock = false; - Clock = new FramedClock(clock = new ManualClock - { - CurrentTime = parentClock.CurrentTime, - Rate = parentClock.Rate, - }); - } - - /// - /// Whether we are running up-to-date with our parent clock. - /// If not, we will need to keep processing children until we catch up. - /// - private bool requireMoreUpdateLoops; - - /// - /// Whether we are in a valid state (ie. should we keep processing children frames). - /// This should be set to false when the replay is, for instance, waiting for future frames to arrive. - /// - private bool validState; - - protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState; - - private bool isAttached => replayInputHandler != null && !UseParentInput; - - private const int max_catch_up_updates_per_frame = 50; - - public override bool UpdateSubTree() - { - requireMoreUpdateLoops = true; - validState = true; - - int loops = 0; - - while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) - { - if (!base.UpdateSubTree()) - return false; - - UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); - - if (isAttached) - { - // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated - // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before - // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead - // called manually at the correct time here. - base.Update(); - } - } - - return true; - } - - protected override void Update() - { - if (parentClock == null) return; - - clock.Rate = parentClock.Rate; - clock.IsRunning = parentClock.IsRunning; - - if (!isAttached) - { - clock.CurrentTime = parentClock.CurrentTime; - } - else - { - double? newTime = replayInputHandler.SetFrameFromTime(parentClock.CurrentTime); - - if (newTime == null) - { - // we shouldn't execute for this time value. probably waiting on more replay data. - validState = false; - return; - } - - clock.CurrentTime = newTime.Value; - } - - requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; - - // The manual clock time has changed in the above code. The framed clock now needs to be updated - // to ensure that the its time is valid for our children before input is processed - Clock.ProcessFrame(); - - if (!isAttached) - { - // For non-replay input handling, this provides equivalent input ordering as if Update was not overridden - base.Update(); - } - } - - #endregion - #region Setting application (disables etc.) private Bindable mouseDisabled; - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - mouseDisabled = config.GetBindable(OsuSetting.MouseDisableButtons); - } - protected override bool Handle(UIEvent e) { switch (e) @@ -213,12 +99,15 @@ namespace osu.Game.Rulesets.UI case MouseDownEvent mouseDown when mouseDown.Button == MouseButton.Left || mouseDown.Button == MouseButton.Right: if (mouseDisabled.Value) return false; + break; case MouseUpEvent mouseUp: if (!CurrentState.Mouse.IsPressed(mouseUp.Button)) return false; + break; } + return base.Handle(e); } @@ -251,6 +140,14 @@ namespace osu.Game.Rulesets.UI protected virtual RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) => new RulesetKeyBindingContainer(ruleset, variant, unique); + + public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer + { + public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + : base(ruleset, variant, unique) + { + } + } } /// diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs index 5628fb51f3..75ea3efdf2 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/ConstantScrollAlgorithm.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs index 2ece9bef9b..a104b0629f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollAlgorithm.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs index 231aaa3c02..5316585493 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/OverlappingScrollAlgorithm.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Lists; using osu.Game.Rulesets.Timing; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs index 8f8f546992..3c9a205412 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/SequentialScrollAlgorithm.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs similarity index 86% rename from osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs index 83b9e31a46..3b368652f2 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/DrawableScrollingRuleset.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Lists; @@ -20,12 +21,11 @@ using osu.Game.Rulesets.UI.Scrolling.Algorithms; namespace osu.Game.Rulesets.UI.Scrolling { /// - /// A type of that supports a . - /// s inside this will scroll within the playfield. + /// A type of that supports a . + /// s inside this will scroll within the playfield. /// - public abstract class ScrollingRulesetContainer : RulesetContainer, IKeyBindingHandler + public abstract class DrawableScrollingRuleset : DrawableRuleset, IKeyBindingHandler where TObject : HitObject - where TPlayfield : ScrollingPlayfield { /// /// The default span of time visible by the length of the scrolling axes. @@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// Provides the default s that adjust the scrolling rate of s - /// inside this . + /// inside this . /// /// private readonly SortedList controlPoints = new SortedList(Comparer.Default); @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.UI.Scrolling [Cached(Type = typeof(IScrollingInfo))] private readonly LocalScrollingInfo scrollingInfo; - protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) + protected DrawableScrollingRuleset(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { scrollingInfo = new LocalScrollingInfo(); @@ -157,16 +157,24 @@ namespace osu.Game.Rulesets.UI.Scrolling switch (action) { case GlobalAction.IncreaseScrollSpeed: - this.TransformBindableTo(TimeRange, TimeRange - time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(TimeRange, TimeRange.Value - time_span_step, 200, Easing.OutQuint); return true; case GlobalAction.DecreaseScrollSpeed: - this.TransformBindableTo(TimeRange, TimeRange + time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(TimeRange, TimeRange.Value + time_span_step, 200, Easing.OutQuint); return true; } return false; } + protected override void LoadComplete() + { + base.LoadComplete(); + + if (!(Playfield is ScrollingPlayfield)) + throw new ArgumentException($"{nameof(Playfield)} must be a {nameof(ScrollingPlayfield)} when using {nameof(DrawableScrollingRuleset)}."); + } + public bool OnReleased(GlobalAction action) => false; private class LocalScrollingInfo : IScrollingInfo diff --git a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs index 21cbd855a9..cd85932599 100644 --- a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs +++ b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling.Algorithms; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index d0db8f8835..81e1a6c916 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Rulesets.UI.Scrolling { @@ -9,14 +9,17 @@ namespace osu.Game.Rulesets.UI.Scrolling /// Hit objects will scroll vertically from the bottom of the hitobject container. /// Up, + /// /// Hit objects will scroll vertically from the top of the hitobject container. /// Down, + /// /// Hit objects will scroll horizontally from the right of the hitobject container. /// Left, + /// /// Hit objects will scroll horizontally from the left of the hitobject container. /// diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 00642b3d41..ed3534fb36 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 0eb67b8bb1..bf2203e176 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.UI.Scrolling diff --git a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs index 5866c04192..77edd24612 100644 --- a/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/DatabasedLegacyScoreParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 3184f776a7..ace8892330 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -57,12 +57,32 @@ namespace osu.Game.Scoring.Legacy var countKatu = (int)sr.ReadUInt16(); var countMiss = (int)sr.ReadUInt16(); - score.ScoreInfo.Statistics[HitResult.Great] = count300; - score.ScoreInfo.Statistics[HitResult.Good] = count100; - score.ScoreInfo.Statistics[HitResult.Meh] = count50; - score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki; - score.ScoreInfo.Statistics[HitResult.Ok] = countKatu; - score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; + switch (currentRuleset.LegacyID) + { + case 0: + score.ScoreInfo.Statistics[HitResult.Great] = count300; + score.ScoreInfo.Statistics[HitResult.Good] = count100; + score.ScoreInfo.Statistics[HitResult.Meh] = count50; + score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; + break; + case 1: + score.ScoreInfo.Statistics[HitResult.Great] = count300; + score.ScoreInfo.Statistics[HitResult.Good] = count100; + score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; + break; + case 2: + score.ScoreInfo.Statistics[HitResult.Perfect] = count300; + score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; + break; + case 3: + score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki; + score.ScoreInfo.Statistics[HitResult.Great] = count300; + score.ScoreInfo.Statistics[HitResult.Good] = countKatu; + score.ScoreInfo.Statistics[HitResult.Ok] = count100; + score.ScoreInfo.Statistics[HitResult.Meh] = count50; + score.ScoreInfo.Statistics[HitResult.Miss] = countMiss; + break; + } score.ScoreInfo.TotalScore = sr.ReadInt32(); score.ScoreInfo.MaxCombo = sr.ReadUInt16(); @@ -91,12 +111,14 @@ namespace osu.Game.Scoring.Legacy byte[] properties = new byte[5]; if (replayInStream.Read(properties, 0, 5) != 5) throw new IOException("input .lzma is too short"); + long outSize = 0; for (int i = 0; i < 8; i++) { int v = replayInStream.ReadByte(); if (v < 0) throw new IOException("Can't Read 1"); + outSize |= (long)(byte)v << (8 * i); } @@ -109,19 +131,19 @@ namespace osu.Game.Scoring.Legacy } } - calculateAccuracy(score.ScoreInfo); + CalculateAccuracy(score.ScoreInfo); return score; } - private void calculateAccuracy(ScoreInfo score) + protected void CalculateAccuracy(ScoreInfo score) { - int countMiss = score.Statistics[HitResult.Miss]; - int count50 = score.Statistics[HitResult.Meh]; - int count100 = score.Statistics[HitResult.Good]; - int count300 = score.Statistics[HitResult.Great]; - int countGeki = score.Statistics[HitResult.Perfect]; - int countKatu = score.Statistics[HitResult.Ok]; + score.Statistics.TryGetValue(HitResult.Miss, out int countMiss); + score.Statistics.TryGetValue(HitResult.Meh, out int count50); + score.Statistics.TryGetValue(HitResult.Good, out int count100); + score.Statistics.TryGetValue(HitResult.Great, out int count300); + score.Statistics.TryGetValue(HitResult.Perfect, out int countGeki); + score.Statistics.TryGetValue(HitResult.Ok, out int countKatu); switch (score.Ruleset.ID) { @@ -244,6 +266,7 @@ namespace osu.Game.Scoring.Legacy var convertible = currentRuleset.CreateConvertibleReplayFrame(); if (convertible == null) throw new InvalidOperationException($"Legacy replay cannot be converted for the ruleset: {currentRuleset.Description}"); + convertible.ConvertFrom(legacyFrame, currentBeatmap); var frame = (ReplayFrame)convertible; diff --git a/osu.Game/Scoring/LegacyDatabasedScore.cs b/osu.Game/Scoring/LegacyDatabasedScore.cs index 768c5da7af..172e08e2d0 100644 --- a/osu.Game/Scoring/LegacyDatabasedScore.cs +++ b/osu.Game/Scoring/LegacyDatabasedScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game/Scoring/Score.cs b/osu.Game/Scoring/Score.cs index ffbee920cb..4e82b1584e 100644 --- a/osu.Game/Scoring/Score.cs +++ b/osu.Game/Scoring/Score.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Replays; diff --git a/osu.Game/Scoring/ScoreFileInfo.cs b/osu.Game/Scoring/ScoreFileInfo.cs index e5595397b8..9075fdec5b 100644 --- a/osu.Game/Scoring/ScoreFileInfo.cs +++ b/osu.Game/Scoring/ScoreFileInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations; using osu.Game.Database; diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 78cc3592c7..d36f963016 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -25,10 +25,10 @@ namespace osu.Game.Scoring public ScoreRank Rank { get; set; } [JsonProperty("total_score")] - public int TotalScore { get; set; } + public long TotalScore { get; set; } [JsonProperty("accuracy")] - [Column(TypeName="DECIMAL(1,4)")] + [Column(TypeName = "DECIMAL(1,4)")] public double Accuracy { get; set; } [JsonProperty(@"pp")] @@ -109,7 +109,27 @@ namespace osu.Game.Scoring public string UserString { get => User?.Username; - set => User = new User { Username = value }; + set + { + if (User == null) + User = new User(); + + User.Username = value; + } + } + + [JsonIgnore] + [Column("UserID")] + public long? UserID + { + get => User?.Id ?? 1; + set + { + if (User == null) + User = new User(); + + User.Id = value ?? 1; + } } [JsonIgnore] @@ -158,5 +178,7 @@ namespace osu.Game.Scoring { public string Acronym { get; set; } } + + public override string ToString() => $"{User} playing {Beatmap}"; } } diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 663f441f2f..7a527bfc69 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Scoring/ScoreRank.cs b/osu.Game/Scoring/ScoreRank.cs index efc513c39c..82c33748bb 100644 --- a/osu.Game/Scoring/ScoreRank.cs +++ b/osu.Game/Scoring/ScoreRank.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,20 +9,28 @@ namespace osu.Game.Scoring { [Description(@"F")] F, + [Description(@"F")] D, + [Description(@"C")] C, + [Description(@"B")] B, + [Description(@"A")] A, + [Description(@"S")] S, + [Description(@"SPlus")] SH, + [Description(@"SS")] X, + [Description(@"SSPlus")] XH, } diff --git a/osu.Game/Scoring/ScoreStore.cs b/osu.Game/Scoring/ScoreStore.cs index 8b99bc0e8d..9627481f4d 100644 --- a/osu.Game/Scoring/ScoreStore.cs +++ b/osu.Game/Scoring/ScoreStore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using Microsoft.EntityFrameworkCore; @@ -8,7 +8,7 @@ using osu.Game.Database; namespace osu.Game.Scoring { - public class ScoreStore : MutableDatabaseBackedStore + public class ScoreStore : MutableDatabaseBackedStoreWithFileIncludes { public ScoreStore(IDatabaseContextFactory factory, Storage storage) : base(factory, storage) @@ -17,7 +17,6 @@ namespace osu.Game.Scoring protected override IQueryable AddIncludesForConsumption(IQueryable query) => base.AddIncludesForConsumption(query) - .Include(s => s.Files).ThenInclude(f => f.FileInfo) .Include(s => s.Beatmap) .Include(s => s.Ruleset); } diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index ed477c9d0b..bbe162cf7c 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using System.Threading; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -12,6 +11,12 @@ namespace osu.Game.Screens { public abstract class BackgroundScreen : Screen, IEquatable { + protected BackgroundScreen() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + public virtual bool Equals(BackgroundScreen other) { return other?.GetType() == GetType(); @@ -26,64 +31,40 @@ namespace osu.Game.Screens return false; } - public override void Push(Screen screen) - { - // When trying to push a non-loaded screen, load it asynchronously and re-invoke Push - // once it's done. - if (screen.LoadState == LoadState.NotLoaded) - { - LoadComponentAsync(screen, d => Push((BackgroundScreen)d)); - return; - } - - // Make sure the in-progress loading is complete before pushing the screen. - while (screen.LoadState < LoadState.Ready) - Thread.Sleep(1); - - try - { - base.Push(screen); - } - catch (ScreenAlreadyExitedException) - { - // screen may have exited before the push was successful. - } - } - protected override void Update() { base.Update(); - Content.Scale = new Vector2(1 + x_movement_amount / DrawSize.X * 2); + Scale = new Vector2(1 + x_movement_amount / DrawSize.X * 2); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { - Content.FadeOut(); - Content.MoveToX(x_movement_amount); + this.FadeOut(); + this.MoveToX(x_movement_amount); - Content.FadeIn(transition_length, Easing.InOutQuart); - Content.MoveToX(0, transition_length, Easing.InOutQuart); + this.FadeIn(transition_length, Easing.InOutQuart); + this.MoveToX(0, transition_length, Easing.InOutQuart); base.OnEntering(last); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { - Content.MoveToX(-x_movement_amount, transition_length, Easing.InOutQuart); + this.MoveToX(-x_movement_amount, transition_length, Easing.InOutQuart); base.OnSuspending(next); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { - Content.FadeOut(transition_length, Easing.OutExpo); - Content.MoveToX(x_movement_amount, transition_length, Easing.OutExpo); + this.FadeOut(transition_length, Easing.OutExpo); + this.MoveToX(x_movement_amount, transition_length, Easing.OutExpo); return base.OnExiting(next); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { - Content.MoveToX(0, transition_length, Easing.OutExpo); + this.MoveToX(0, transition_length, Easing.OutExpo); base.OnResuming(last); } } diff --git a/osu.Game/Screens/BackgroundScreenStack.cs b/osu.Game/Screens/BackgroundScreenStack.cs new file mode 100644 index 0000000000..5f82329496 --- /dev/null +++ b/osu.Game/Screens/BackgroundScreenStack.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osuTK; + +namespace osu.Game.Screens +{ + public class BackgroundScreenStack : ScreenStack + { + public BackgroundScreenStack() + : base(false) + { + Scale = new Vector2(1.06f); + RelativeSizeAxes = Axes.Both; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + //public float ParallaxAmount { set => parallax.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * value; } + + public new void Push(BackgroundScreen screen) + { + if (screen == null) + return; + + if (EqualityComparer.Default.Equals((BackgroundScreen)CurrentScreen, screen)) + return; + + base.Push(screen); + } + } +} diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index e326cdb0ca..6df418753c 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,21 +1,60 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Game.Beatmaps; using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenBeatmap : BlurrableBackgroundScreen + public class BackgroundScreenBeatmap : BackgroundScreen { + protected Background Background; + private WorkingBeatmap beatmap; + /// + /// Whether or not user dim settings should be applied to this Background. + /// + public readonly Bindable EnableUserDim = new Bindable(); + + public readonly Bindable StoryboardReplacesBackground = new Bindable(); + + /// + /// The amount of blur to be applied in addition to user-specified blur. + /// + public readonly Bindable BlurAmount = new Bindable(); + + private readonly UserDimContainer fadeContainer; + + protected virtual UserDimContainer CreateFadeContainer() => new UserDimContainer { RelativeSizeAxes = Axes.Both }; + + public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null) + { + Beatmap = beatmap; + InternalChild = fadeContainer = CreateFadeContainer(); + fadeContainer.EnableUserDim.BindTo(EnableUserDim); + fadeContainer.BlurAmount.BindTo(BlurAmount); + } + + [BackgroundDependencyLoader] + private void load() + { + var background = new BeatmapBackground(beatmap); + LoadComponent(background); + switchBackground(background); + } + + private CancellationTokenSource cancellationSource; + public WorkingBeatmap Beatmap { - get { return beatmap; } + get => beatmap; set { if (beatmap == value && beatmap != null) @@ -25,51 +64,51 @@ namespace osu.Game.Screens.Backgrounds Schedule(() => { - LoadComponentAsync(new BeatmapBackground(beatmap), b => Schedule(() => - { - float newDepth = 0; - if (Background != null) - { - newDepth = Background.Depth + 1; - Background.FinishTransforms(); - Background.FadeOut(250); - Background.Expire(); - } + if ((Background as BeatmapBackground)?.Beatmap == beatmap) + return; - b.Depth = newDepth; - Add(Background = b); - Background.BlurSigma = BlurTarget; - })); + cancellationSource?.Cancel(); + LoadComponentAsync(new BeatmapBackground(beatmap), switchBackground, (cancellationSource = new CancellationTokenSource()).Token); }); } } - public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null) + private void switchBackground(BeatmapBackground b) { - Beatmap = beatmap; + float newDepth = 0; + if (Background != null) + { + newDepth = Background.Depth + 1; + Background.FinishTransforms(); + Background.FadeOut(250); + Background.Expire(); + } + + b.Depth = newDepth; + fadeContainer.Background = Background = b; + StoryboardReplacesBackground.BindTo(fadeContainer.StoryboardReplacesBackground); } public override bool Equals(BackgroundScreen other) { - var otherBeatmapBackground = other as BackgroundScreenBeatmap; - if (otherBeatmapBackground == null) return false; + if (!(other is BackgroundScreenBeatmap otherBeatmapBackground)) return false; return base.Equals(other) && beatmap == otherBeatmapBackground.Beatmap; } - private class BeatmapBackground : Background + protected class BeatmapBackground : Background { - private readonly WorkingBeatmap beatmap; + public readonly WorkingBeatmap Beatmap; public BeatmapBackground(WorkingBeatmap beatmap) { - this.beatmap = beatmap; + Beatmap = beatmap; } [BackgroundDependencyLoader] private void load(TextureStore textures) { - Sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); + Sprite.Texture = Beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); } } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs index c097d25178..9e2559cc56 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBlack.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -12,14 +12,14 @@ namespace osu.Game.Screens.Backgrounds { public BackgroundScreenBlack() { - Child = new Box + InternalChild = new Box { Colour = Color4.Black, RelativeSizeAxes = Axes.Both, }; } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { Show(); } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index 041391db1e..0cb41bc562 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics.Backgrounds; @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Backgrounds public BackgroundScreenCustom(string textureName) { this.textureName = textureName; - Add(new Background(textureName)); + AddInternal(new Background(textureName)); } public override bool Equals(BackgroundScreen other) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 989883c8b3..7092ac0c4a 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -1,34 +1,50 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Threading; using osu.Game.Graphics.Backgrounds; +using osu.Game.Online.API; +using osu.Game.Skinning; +using osu.Game.Users; namespace osu.Game.Screens.Backgrounds { - public class BackgroundScreenDefault : BlurrableBackgroundScreen + public class BackgroundScreenDefault : BackgroundScreen { + private Background background; + private int currentDisplay; private const int background_count = 5; private string backgroundName => $@"Menu/menu-background-{currentDisplay % background_count + 1}"; + private Bindable user; + private Bindable skin; + [BackgroundDependencyLoader] - private void load() + private void load(IAPIProvider api, SkinManager skinManager) { + user = api.LocalUser.GetBoundCopy(); + skin = skinManager.CurrentSkin.GetBoundCopy(); + + user.ValueChanged += _ => Next(); + skin.ValueChanged += _ => Next(); + currentDisplay = RNG.Next(0, background_count); - display(new Background(backgroundName)); + + display(createBackground()); } private void display(Background newBackground) { - Background?.FadeOut(800, Easing.InOutSine); - Background?.Expire(); + background?.FadeOut(800, Easing.InOutSine); + background?.Expire(); - Add(Background = newBackground); + AddInternal(background = newBackground); currentDisplay++; } @@ -37,10 +53,38 @@ namespace osu.Game.Screens.Backgrounds public void Next() { nextTask?.Cancel(); - nextTask = Scheduler.AddDelayed(() => + nextTask = Scheduler.AddDelayed(() => { LoadComponentAsync(createBackground(), display); }, 100); + } + + private Background createBackground() + { + Background newBackground; + + if (user.Value?.IsSupporter ?? false) + newBackground = new SkinnedBackground(skin.Value, backgroundName); + else + newBackground = new Background(backgroundName); + + newBackground.Depth = currentDisplay; + + return newBackground; + } + + private class SkinnedBackground : Background + { + private readonly Skin skin; + + public SkinnedBackground(Skin skin, string fallbackTextureName) + : base(fallbackTextureName) { - LoadComponentAsync(new Background(backgroundName) { Depth = currentDisplay }, display); - }, 100); + this.skin = skin; + } + + [BackgroundDependencyLoader] + private void load() + { + Sprite.Texture = skin.GetTexture("menu-background") ?? Sprite.Texture; + } } } } diff --git a/osu.Game/Screens/BlurrableBackgroundScreen.cs b/osu.Game/Screens/BlurrableBackgroundScreen.cs deleted file mode 100644 index 4b6abbf063..0000000000 --- a/osu.Game/Screens/BlurrableBackgroundScreen.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Game.Graphics.Backgrounds; -using osuTK; - -namespace osu.Game.Screens -{ - public abstract class BlurrableBackgroundScreen : BackgroundScreen - { - protected Background Background; - - protected Vector2 BlurTarget; - - public TransformSequence BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) - => Background?.BlurTo(BlurTarget = sigma, duration, easing); - } -} diff --git a/osu.Game/Screens/Charts/ChartInfo.cs b/osu.Game/Screens/Charts/ChartInfo.cs index 35021709d6..d9a9ad5eeb 100644 --- a/osu.Game/Screens/Charts/ChartInfo.cs +++ b/osu.Game/Screens/Charts/ChartInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Charts { diff --git a/osu.Game/Screens/Charts/ChartListing.cs b/osu.Game/Screens/Charts/ChartListing.cs index a618bba8c4..18bba6433f 100644 --- a/osu.Game/Screens/Charts/ChartListing.cs +++ b/osu.Game/Screens/Charts/ChartListing.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,8 +8,9 @@ namespace osu.Game.Screens.Charts { public class ChartListing : ScreenWhiteBox { - protected override IEnumerable PossibleChildren => new[] { - typeof(ChartInfo) + protected override IEnumerable PossibleChildren => new[] + { + typeof(ChartInfo) }; } } diff --git a/osu.Game/Screens/Direct/OnlineListing.cs b/osu.Game/Screens/Direct/OnlineListing.cs index 9d2d09a695..8376383674 100644 --- a/osu.Game/Screens/Direct/OnlineListing.cs +++ b/osu.Game/Screens/Direct/OnlineListing.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Direct { diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 3124482c73..ea3b68e3bd 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Edit { @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit public override int Value { - get { return base.Value; } + get => base.Value; set { if (!VALID_DIVISORS.Contains(value)) diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index caf9ba27ff..cb5078a479 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Edit.Components } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, OsuColour colours) + private void load(IBindable beatmap, OsuColour colours) { Beatmap.BindTo(beatmap); background.Colour = colours.Gray1; diff --git a/osu.Game/Screens/Edit/Components/CircularButton.cs b/osu.Game/Screens/Edit/Components/CircularButton.cs index 98c3a7888d..931c7d03a0 100644 --- a/osu.Game/Screens/Edit/Components/CircularButton.cs +++ b/osu.Game/Screens/Edit/Components/CircularButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics.UserInterface; using osuTK; diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index a647a8d75f..752615245e 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -110,7 +110,8 @@ namespace osu.Game.Screens.Edit.Components.Menus { public TextContainer() { - NormalText.TextSize = BoldText.TextSize = 14; + NormalText.Font = NormalText.Font.With(size: 14); + BoldText.Font = BoldText.Font.With(size: 14); NormalText.Margin = BoldText.Margin = new MarginPadding { Horizontal = 10, Vertical = MARGIN_VERTICAL }; } } @@ -174,6 +175,7 @@ namespace osu.Game.Screens.Edit.Components.Menus { if (Item is EditorMenuItemSpacer) return true; + return base.OnHover(e); } @@ -181,6 +183,7 @@ namespace osu.Game.Screens.Edit.Components.Menus { if (Item is EditorMenuItemSpacer) return true; + return base.OnClick(e); } } diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs index 1c9253cce7..0a2c073dcd 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics.UserInterface; diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs index 17ee88241e..4e75a92e19 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuItemSpacer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Edit.Components.Menus { diff --git a/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs index 56f6056bf9..089da4f222 100644 --- a/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs +++ b/osu.Game/Screens/Edit/Components/Menus/ScreenSelectionTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index d2e51d1f57..227ad29000 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Edit.Components } }; - tabs.Current.ValueChanged += newValue => Beatmap.Value.Track.Tempo.Value = newValue; + tabs.Current.ValueChanged += tempo => Beatmap.Value.Track.Tempo.Value = tempo.NewValue; } protected override bool OnKeyDown(KeyDownEvent e) @@ -114,7 +114,8 @@ namespace osu.Game.Screens.Edit.Components private readonly OsuSpriteText text; private readonly OsuSpriteText textBold; - public PlaybackTabItem(double value) : base(value) + public PlaybackTabItem(double value) + : base(value) { RelativeSizeAxes = Axes.Both; @@ -127,15 +128,14 @@ namespace osu.Game.Screens.Edit.Components Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Text = $"{value:0%}", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, textBold = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Text = $"{value:0%}", - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Alpha = 0, }, }; @@ -163,9 +163,9 @@ namespace osu.Game.Screens.Edit.Components private void updateState() { - text.FadeColour(Active || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint); - text.FadeTo(Active ? 0 : 1, fade_duration, Easing.OutQuint); - textBold.FadeTo(Active ? 1 : 0, fade_duration, Easing.OutQuint); + text.FadeColour(Active.Value || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint); + text.FadeTo(Active.Value ? 0 : 1, fade_duration, Easing.OutQuint); + textBold.FadeTo(Active.Value ? 1 : 0, fade_duration, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index eb113efbab..1ad69afe91 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -80,10 +80,10 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons { base.LoadComplete(); - button.Selected.ValueChanged += v => + button.Selected.ValueChanged += selected => { updateSelectionState(); - if (v) + if (selected.NewValue) Selected?.Invoke(button); }; @@ -95,16 +95,16 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons if (!IsLoaded) return; - BackgroundColour = button.Selected ? selectedBackgroundColour : defaultBackgroundColour; - bubble.Colour = button.Selected ? selectedBubbleColour : defaultBubbleColour; + BackgroundColour = button.Selected.Value ? selectedBackgroundColour : defaultBackgroundColour; + bubble.Colour = button.Selected.Value ? selectedBubbleColour : defaultBubbleColour; } protected override bool OnClick(ClickEvent e) { - if (button.Selected) + if (button.Selected.Value) return true; - if (!Enabled) + if (!Enabled.Value) return true; button.Selected.Value = true; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs index c671fa71c2..3692c0437b 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Edit.Components.RadioButtons { diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs index fdb5770ecf..16574c0baf 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Extensions.IEnumerableExtensions; @@ -12,13 +12,15 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons public class RadioButtonCollection : CompositeDrawable { private IReadOnlyList items; + public IReadOnlyList Items { - get { return items; } + get => items; set { if (ReferenceEquals(items, value)) return; + items = value; buttonContainer.Clear(); @@ -42,11 +44,12 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons } private RadioButton currentlySelected; + private void addButton(RadioButton button) { - button.Selected.ValueChanged += v => + button.Selected.ValueChanged += selected => { - if (v) + if (selected.NewValue) { currentlySelected?.Deselect(); currentlySelected = button; diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 129ea2bf7d..0391074b11 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -1,11 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using System; using osu.Framework.Allocation; using osu.Framework.Timing; +using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components { @@ -17,15 +18,13 @@ namespace osu.Game.Screens.Edit.Components public TimeInfoContainer() { - Children = new Drawable[] { trackTimer = new OsuSpriteText { Origin = Anchor.BottomLeft, RelativePositionAxes = Axes.Y, - TextSize = 22, - FixedWidth = true, + Font = OsuFont.GetFont(size: 22, fixedWidth: true), Y = 0.5f, } }; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs index 3af3fcbdd7..103e39e78a 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index 1146037004..ceccbffc9c 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index 4bef22463e..102955657e 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; @@ -26,12 +26,12 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts // Consider all non-timing points as the same type cpi.SamplePoints.Select(c => (ControlPoint)c) - .Concat(cpi.EffectPoints) - .Concat(cpi.DifficultyPoints) - .Distinct() - // Non-timing points should not be added where there are timing points - .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) - .ForEach(addNonTimingPoint); + .Concat(cpi.EffectPoints) + .Concat(cpi.DifficultyPoints) + .Distinct() + // Non-timing points should not be added where there are timing points + .Where(c => cpi.TimingPointAt(c.Time).Time != c.Time) + .ForEach(addNonTimingPoint); } private void addTimingPoint(ControlPoint controlPoint) => Add(new TimingPointVisualisation(controlPoint)); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index 3f3826d55c..07d307f293 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -32,6 +32,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts protected override bool OnDragStart(DragStartEvent e) => true; protected override bool OnDragEnd(DragEndEvent e) => true; + protected override bool OnDrag(DragEvent e) { seekToPosition(e.ScreenSpaceMousePosition); diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index 104fb76f1c..26d9614631 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -27,12 +27,12 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Beatmap.ValueChanged += b => { updateRelativeChildSize(); - LoadBeatmap(b); + LoadBeatmap(b.NewValue); }; } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) + private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); } diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index 0b4cba00f3..20db2cac21 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs index 0b5c6018e8..de63df5463 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index 40955195a4..9c00cce57a 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index 373f4d1682..3f7672ae08 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }, new Drawable[] { - new TextFlowContainer(s => s.TextSize = 14) + new TextFlowContainer(s => s.Font = s.Font.With(size: 14)) { Padding = new MarginPadding { Horizontal = 15 }, Text = "beat snap divisor", @@ -157,12 +157,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void LoadComplete() { base.LoadComplete(); - - beatDivisor.ValueChanged += v => updateText(); - updateText(); + beatDivisor.BindValueChanged(val => Text = $"1/{val.NewValue}", true); } - - private void updateText() => Text = $"1/{beatDivisor.Value}"; } private class DivisorButton : IconButton @@ -219,9 +215,9 @@ namespace osu.Game.Screens.Edit.Compose.Components AddInternal(marker = new Marker()); - CurrentNumber.ValueChanged += v => + CurrentNumber.ValueChanged += div => { - marker.MoveToX(getMappedPosition(v), 100, Easing.OutQuint); + marker.MoveToX(getMappedPosition(div.NewValue), 100, Easing.OutQuint); marker.Flash(); }; } @@ -238,11 +234,11 @@ namespace osu.Game.Screens.Edit.Compose.Components { case Key.Right: beatDivisor.Next(); - OnUserChange(Current); + OnUserChange(Current.Value); return true; case Key.Left: beatDivisor.Previous(); - OnUserChange(Current); + OnUserChange(Current.Value); return true; default: return false; @@ -279,7 +275,7 @@ namespace osu.Game.Screens.Edit.Compose.Components var xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; CurrentNumber.Value = availableDivisors.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First(); - OnUserChange(Current); + OnUserChange(Current.Value); } private float getMappedPosition(float divisor) => (float)Math.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 80bfe21367..a1e62cd38b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -68,6 +68,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (currentTool == value) return; + currentTool = value; refreshTool(); @@ -188,6 +189,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { if (!(x is SelectionBlueprint xBlueprint) || !(y is SelectionBlueprint yBlueprint)) return base.Compare(x, y); + return Compare(xBlueprint, yBlueprint); } diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 5051eb40e3..143615148a 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs b/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs index b62ea4cf81..4d956336b7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs +++ b/osu.Game/Screens/Edit/Compose/Components/EditorPlayfieldBorder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index f8ceeedba9..bcb2bee601 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs index 620fc255c3..0d4c48b5f6 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/CentreMarker.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index 0c626f2c54..748c9e2ba3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline private WaveformGraph waveform; [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, IAdjustableClock adjustableClock, OsuColour colours) + private void load(IBindable beatmap, IAdjustableClock adjustableClock, OsuColour colours) { this.adjustableClock = adjustableClock; @@ -49,13 +49,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // We don't want the centre marker to scroll AddInternal(new CentreMarker()); - WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint); Beatmap.BindTo(beatmap); Beatmap.BindValueChanged(b => { - waveform.Waveform = b.Waveform; - track = b.Track; + waveform.Waveform = b.NewValue.Waveform; + track = b.NewValue.Track; }, true); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs index 1e16a3264c..3b24925f2c 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_plus, - Action = () => timeline.Zoom++ + Action = () => changeZoom(1) }, new TimelineButton { @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_minus, - Action = () => timeline.Zoom-- + Action = () => changeZoom(-1) }, } } @@ -124,5 +124,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline timeline.WaveformVisible.BindTo(waveformCheckbox.Current); } + + private void changeZoom(float change) => timeline.Zoom += change; } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index df482fc1d9..5ded97393b 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -19,8 +19,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline public FontAwesome Icon { - get { return button.Icon; } - set { button.Icon = value; } + get => button.Icon; + set => button.Icon = value; } private readonly IconButton button; diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs index 71cea595d0..1e94a20dc7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/ZoomableScrollContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -47,6 +47,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { if (value < 1) throw new ArgumentException($"{nameof(MinZoom)} must be >= 1.", nameof(value)); + minZoom = value; if (Zoom < value) @@ -66,6 +67,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { if (value < 1) throw new ArgumentException($"{nameof(MaxZoom)} must be >= 1.", nameof(value)); + maxZoom = value; if (Zoom > value) @@ -108,6 +110,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } private float zoomTarget = 1; + private void setZoomTarget(float newZoom, float focusPoint) { zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); diff --git a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs index 91332aa94f..9ccf974244 100644 --- a/osu.Game/Screens/Edit/Compose/ComposeScreen.cs +++ b/osu.Game/Screens/Edit/Compose/ComposeScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using JetBrains.Annotations; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs index f93b294536..47a4277430 100644 --- a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs +++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Screens/Edit/Design/DesignScreen.cs b/osu.Game/Screens/Edit/Design/DesignScreen.cs index 7c482a9380..2a334e1b30 100644 --- a/osu.Game/Screens/Edit/Design/DesignScreen.cs +++ b/osu.Game/Screens/Edit/Design/DesignScreen.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 9bccefc508..0ba1e74aca 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK.Graphics; @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Platform; @@ -21,6 +22,8 @@ using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Design; using osuTK.Input; +using System.Collections.Generic; +using osu.Framework; namespace osu.Game.Screens.Edit { @@ -28,8 +31,9 @@ namespace osu.Game.Screens.Edit { protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg4"); - protected override bool HideOverlaysOnEnter => true; - public override bool AllowBeatmapRulesetChange => false; + public override bool HideOverlaysOnEnter => true; + + public override bool DisallowExternalBeatmapRulesetChanges => true; private Box bottomBackground; private Container screenContainer; @@ -51,7 +55,7 @@ namespace osu.Game.Screens.Edit { this.host = host; - // TODO: should probably be done at a RulesetContainer level to share logic with Player. + // TODO: should probably be done at a DrawableRuleset level to share logic with Player. var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock(); clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false }; clock.ChangeSource(sourceClock); @@ -65,7 +69,16 @@ namespace osu.Game.Screens.Edit SummaryTimeline timeline; PlaybackControl playback; - Children = new[] + var fileMenuItems = new List(); + if (RuntimeInfo.IsDesktop) + { + fileMenuItems.Add(new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap)); + fileMenuItems.Add(new EditorMenuItemSpacer()); + } + + fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); + + InternalChildren = new[] { new Container { @@ -92,12 +105,7 @@ namespace osu.Game.Screens.Edit { new MenuItem("File") { - Items = new[] - { - new EditorMenuItem("Export", MenuItemType.Standard, exportBeatmap), - new EditorMenuItemSpacer(), - new EditorMenuItem("Exit", MenuItemType.Standard, Exit) - } + Items = fileMenuItems } } } @@ -194,20 +202,20 @@ namespace osu.Game.Screens.Edit return true; } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { Beatmap.Value.Track?.Stop(); base.OnResuming(last); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); Background.FadeColour(Color4.DarkGray, 500); Beatmap.Value.Track?.Stop(); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { Background.FadeColour(Color4.White, 500); if (Beatmap.Value.Track != null) @@ -221,11 +229,11 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); - private void onModeChanged(EditorScreenMode mode) + private void onModeChanged(ValueChangedEvent e) { currentScreen?.Exit(); - switch (mode) + switch (e.NewValue) { case EditorScreenMode.Compose: currentScreen = new ComposeScreen(); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 05ba1ab732..8f65366650 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit public bool SeekSnapped(double position) { var timingPoint = ControlPointInfo.TimingPointAt(position); - double beatSnapLength = timingPoint.BeatLength / beatDivisor; + double beatSnapLength = timingPoint.BeatLength / beatDivisor.Value; // We will be snapping to beats within the timing point position -= timingPoint.Time; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Edit timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; } - double seekAmount = timingPoint.BeatLength / beatDivisor * amount; + double seekAmount = timingPoint.BeatLength / beatDivisor.Value * amount; double seekTime = CurrentTime + seekAmount * direction; if (!snapped || ControlPointInfo.TimingPoints.Count == 0) diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index 3a8fc3ef80..045e5a1226 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Edit } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) + private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); } diff --git a/osu.Game/Screens/Edit/EditorScreenMode.cs b/osu.Game/Screens/Edit/EditorScreenMode.cs index 17de6c4125..12cfcc605b 100644 --- a/osu.Game/Screens/Edit/EditorScreenMode.cs +++ b/osu.Game/Screens/Edit/EditorScreenMode.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,10 +9,13 @@ namespace osu.Game.Screens.Edit { [Description("setup")] SongSetup, + [Description("compose")] Compose, + [Description("design")] Design, + [Description("timing")] Timing, } diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs index eae080bc81..50d524d1f5 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -38,8 +38,8 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents public float LabelTextSize { - get => label.TextSize; - set => label.TextSize = value; + get => label.Font.Size; + set => label.Font = label.Font.With(size: value); } public string PlaceholderText @@ -103,8 +103,7 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents Origin = Anchor.TopLeft, Padding = new MarginPadding { Left = default_label_left_padding, Top = default_label_top_padding }, Colour = Color4.White, - TextSize = default_label_text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: default_label_text_size, weight: FontWeight.Bold), }, textBox = new OsuTextBox { diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs new file mode 100644 index 0000000000..b25bcdeab1 --- /dev/null +++ b/osu.Game/Screens/IOsuScreen.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Overlays; +using osu.Game.Rulesets; + +namespace osu.Game.Screens +{ + public interface IOsuScreen : IScreen + { + /// + /// Whether the beatmap or ruleset should be allowed to be changed by the user or game. + /// Used to mark exclusive areas where this is strongly prohibited, like gameplay. + /// + bool DisallowExternalBeatmapRulesetChanges { get; } + + /// + /// Whether a top-level component should be allowed to exit the current screen to, for example, + /// complete an import. Note that this can be overridden by a user if they specifically request. + /// + bool AllowExternalScreenChange { get; } + + /// + /// Whether this allows the cursor to be displayed. + /// + bool CursorVisible { get; } + + /// + /// Whether all overlays should be hidden when this screen is entered or resumed. + /// + bool HideOverlaysOnEnter { get; } + + /// + /// Whether overlays should be able to be opened once this screen is entered or resumed. + /// + OverlayActivation InitialOverlayActivationMode { get; } + + /// + /// The amount of parallax to be applied while this screen is displayed. + /// + float BackgroundParallaxAmount { get; } + + Bindable Beatmap { get; } + + Bindable Ruleset { get; } + } +} diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index a59a8a77ef..d858cb076a 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -17,9 +17,11 @@ namespace osu.Game.Screens { private bool showDisclaimer; - protected override bool HideOverlaysOnEnter => true; + public override bool HideOverlaysOnEnter => true; - protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + + public override bool CursorVisible => false; protected override bool AllowBackButton => false; @@ -55,11 +57,11 @@ namespace osu.Game.Screens protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler(); - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - LoadComponentAsync(precompiler = CreateShaderPrecompiler(), Add); + LoadComponentAsync(precompiler = CreateShaderPrecompiler(), AddInternal); LoadComponentAsync(loadableScreen = CreateLoadableScreen()); checkIfLoaded(); @@ -73,7 +75,7 @@ namespace osu.Game.Screens return; } - Push(loadableScreen); + this.Push(loadableScreen); } [BackgroundDependencyLoader] @@ -87,7 +89,7 @@ namespace osu.Game.Screens /// public class ShaderPrecompiler : Drawable { - private readonly List loadTargets = new List(); + private readonly List loadTargets = new List(); public bool FinishedCompiling { get; private set; } @@ -104,7 +106,7 @@ namespace osu.Game.Screens loadTargets.Add(manager.Load(VertexShaderDescriptor.TEXTURE_3, FragmentShaderDescriptor.TEXTURE)); } - protected virtual bool AllLoaded => loadTargets.All(s => s.Loaded); + protected virtual bool AllLoaded => loadTargets.All(s => s.IsLoaded); protected override void Update() { diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index fee5453165..a02c2a37fa 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; @@ -118,7 +118,6 @@ namespace osu.Game.Screens.Menu AllowMultiline = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 16, Position = new Vector2(0, 35), Text = text } @@ -243,7 +242,7 @@ namespace osu.Game.Screens.Menu public ButtonState State { - get { return state; } + get => state; set { diff --git a/osu.Game/Screens/Menu/ButtonArea.cs b/osu.Game/Screens/Menu/ButtonArea.cs index 88fdb0a05e..d6e1aef63c 100644 --- a/osu.Game/Screens/Menu/ButtonArea.cs +++ b/osu.Game/Screens/Menu/ButtonArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 14eae54cb2..3df4ef9059 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,11 +8,12 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; using osu.Framework.Logging; +using osu.Framework.Platform; using osu.Framework.Threading; using osu.Game.Graphics; using osu.Game.Input; @@ -90,7 +91,20 @@ namespace osu.Game.Screens.Menu }); buttonArea.Flow.CentreTarget = iconFacade; + } + [Resolved(CanBeNull = true)] + private OsuGame game { get; set; } + + [Resolved] + private IAPIProvider api { get; set; } + + [Resolved(CanBeNull = true)] + private NotificationOverlay notifications { get; set; } + + [BackgroundDependencyLoader(true)] + private void load(AudioManager audio, IdleTracker idleTracker, GameHost host) + { buttonsPlay.Add(new Button(@"solo", @"button-solo-select", FontAwesome.fa_user, new Color4(102, 68, 204, 255), () => OnSolo?.Invoke(), WEDGE_WIDTH, Key.P)); buttonsPlay.Add(new Button(@"multi", @"button-generic-select", FontAwesome.fa_users, new Color4(94, 63, 186, 255), onMulti, 0, Key.M)); buttonsPlay.Add(new Button(@"chart", @"button-generic-select", FontAwesome.fa_osu_charts, new Color4(80, 53, 160, 255), () => OnChart?.Invoke())); @@ -99,25 +113,14 @@ namespace osu.Game.Screens.Menu buttonsTopLevel.Add(new Button(@"play", @"button-play-select", FontAwesome.fa_osu_logo, new Color4(102, 68, 204, 255), () => State = ButtonSystemState.Play, WEDGE_WIDTH, Key.P)); buttonsTopLevel.Add(new Button(@"osu!editor", @"button-generic-select", FontAwesome.fa_osu_edit_o, new Color4(238, 170, 0, 255), () => OnEdit?.Invoke(), 0, Key.E)); buttonsTopLevel.Add(new Button(@"osu!direct", @"button-direct-select", FontAwesome.fa_osu_chevron_down_o, new Color4(165, 204, 0, 255), () => OnDirect?.Invoke(), 0, Key.D)); - buttonsTopLevel.Add(new Button(@"exit", string.Empty, FontAwesome.fa_osu_cross_o, new Color4(238, 51, 153, 255), () => OnExit?.Invoke(), 0, Key.Q)); + + if (host.CanExit) + buttonsTopLevel.Add(new Button(@"exit", string.Empty, FontAwesome.fa_osu_cross_o, new Color4(238, 51, 153, 255), () => OnExit?.Invoke(), 0, Key.Q)); buttonArea.AddRange(buttonsPlay); buttonArea.AddRange(buttonsTopLevel); - } - [Resolved(CanBeNull = true)] - private OsuGame game { get; set; } - - [Resolved] - private APIAccess api { get; set; } - - [Resolved(CanBeNull = true)] - private NotificationOverlay notifications { get; set; } - - [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, IdleTracker idleTracker) - { - isIdle.ValueChanged += updateIdleState; + isIdle.ValueChanged += idle => updateIdleState(idle.NewValue); if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); @@ -203,7 +206,7 @@ namespace osu.Game.Screens.Menu public ButtonSystemState State { - get { return state; } + get => state; set { diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index c9ad519897..e6a90f76c0 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -1,14 +1,22 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.API; using osuTK; using osuTK.Graphics; using osu.Game.Overlays; +using osu.Game.Users; namespace osu.Game.Screens.Menu { @@ -18,13 +26,19 @@ namespace osu.Game.Screens.Menu private SpriteIcon icon; private Color4 iconColour; private LinkFlowContainer textFlow; + private LinkFlowContainer supportFlow; - protected override bool HideOverlaysOnEnter => true; - protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + public override bool HideOverlaysOnEnter => true; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; public override bool CursorVisible => false; - private const float icon_y = -0.09f; + private Drawable heart; + + private const float icon_y = -85; + private const float icon_size = 30; + + private readonly Bindable currentUser = new Bindable(); public Disclaimer() { @@ -32,52 +46,107 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, IAPIProvider api) { - Children = new Drawable[] + InternalChildren = new Drawable[] { icon = new SpriteIcon { Anchor = Anchor.Centre, Origin = Anchor.Centre, Icon = FontAwesome.fa_warning, - Size = new Vector2(30), - RelativePositionAxes = Axes.Both, + Size = new Vector2(icon_size), Y = icon_y, }, - textFlow = new LinkFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(50), - TextAnchor = Anchor.TopCentre, + Direction = FillDirection.Vertical, + Y = icon_y + icon_size, Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Spacing = new Vector2(0, 2), + Origin = Anchor.TopCentre, + Children = new Drawable[] + { + textFlow = new LinkFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Spacing = new Vector2(0, 2), + }, + supportFlow = new LinkFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + TextAnchor = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Alpha = 0, + Spacing = new Vector2(0, 2), + }, + } } }; - textFlow.AddText("This is an ", t => - { - t.TextSize = 30; - t.Font = @"Exo2.0-Light"; - }); - textFlow.AddText("early development build", t => - { - t.TextSize = 30; - t.Font = @"Exo2.0-SemiBold"; - }); + textFlow.AddText("This is an ", t => t.Font = t.Font.With(Typeface.Exo, 30, FontWeight.Light)); + textFlow.AddText("early development build", t => t.Font = t.Font.With(Typeface.Exo, 30, FontWeight.SemiBold)); - textFlow.AddParagraph("Don't expect everything to work perfectly."); - textFlow.AddParagraph(""); - textFlow.AddParagraph("Detailed bug reports are welcomed via github issues."); - textFlow.AddParagraph(""); + textFlow.AddParagraph("Things may not work as expected", t => t.Font = t.Font.With(size: 20)); + textFlow.NewParagraph(); - textFlow.AddText("Visit "); - textFlow.AddLink("discord.gg/ppy", "https://discord.gg/ppy"); - textFlow.AddText(" if you want to help out or follow progress!"); + Action format = t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold); + + textFlow.AddParagraph("Detailed bug reports are welcomed via github issues.", format); + textFlow.NewParagraph(); + + textFlow.AddText("Visit ", format); + textFlow.AddLink("discord.gg/ppy", "https://discord.gg/ppy", creationParameters: format); + textFlow.AddText(" to help out or follow progress!", format); + + textFlow.NewParagraph(); + textFlow.NewParagraph(); + textFlow.NewParagraph(); iconColour = colours.Yellow; + + currentUser.BindTo(api.LocalUser); + currentUser.BindValueChanged(e => + { + supportFlow.Children.ForEach(d => d.FadeOut().Expire()); + + if (e.NewValue.IsSupporter) + { + supportFlow.AddText("Thank you for supporting osu!", format); + } + else + { + supportFlow.AddText("Consider becoming an ", format); + supportFlow.AddLink("osu!supporter", "https://osu.ppy.sh/home/support", creationParameters: format); + supportFlow.AddText(" to help support the game", format); + } + + heart = supportFlow.AddIcon(FontAwesome.fa_heart, t => + { + t.Padding = new MarginPadding { Left = 5 }; + t.Font = t.Font.With(size: 12); + t.Origin = Anchor.Centre; + t.Colour = colours.Pink; + }).First(); + + if (IsLoaded) + animateHeart(); + + if (supportFlow.IsPresent) + supportFlow.FadeInFromZero(500); + }, true); + } + + private void animateHeart() + { + heart.FlashColour(Color4.White, 750, Easing.OutQuint).Loop(); } protected override void LoadComplete() @@ -86,19 +155,28 @@ namespace osu.Game.Screens.Menu LoadComponentAsync(intro = new Intro()); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - icon.Delay(1500).FadeColour(iconColour, 200, Easing.OutQuint); - icon.Delay(1500).MoveToY(icon_y * 1.1f, 100, Easing.OutCirc).Then().MoveToY(icon_y, 100, Easing.InCirc); + icon.Delay(1000).FadeColour(iconColour, 200, Easing.OutQuint); + icon.Delay(1000) + .MoveToY(icon_y * 1.1f, 160, Easing.OutCirc) + .RotateTo(-10, 160, Easing.OutCirc) + .Then() + .MoveToY(icon_y, 160, Easing.InCirc) + .RotateTo(0, 160, Easing.InCirc); - Content + supportFlow.FadeOut().Delay(2000).FadeIn(500); + + animateHeart(); + + this .FadeInFromZero(500) .Then(5500) .FadeOut(250) .ScaleTo(0.9f, 250, Easing.InQuint) - .Finally(d => Push(intro)); + .Finally(d => this.Push(intro)); } } } diff --git a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs index 4ada46749c..519834859d 100644 --- a/osu.Game/Screens/Menu/ExitConfirmOverlay.cs +++ b/osu.Game/Screens/Menu/ExitConfirmOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index 1c6fe37b1b..ec7333ec02 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 8d9cd8dbe9..2392d650a0 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.MathUtils; @@ -28,14 +28,12 @@ namespace osu.Game.Screens.Menu /// public bool DidLoadMenu; - private readonly Bindable beatmap = new Bindable(); - private MainMenu mainMenu; private SampleChannel welcome; private SampleChannel seeya; - protected override bool HideOverlaysOnEnter => true; - protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + public override bool HideOverlaysOnEnter => true; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; public override bool CursorVisible => false; @@ -47,16 +45,14 @@ namespace osu.Game.Screens.Menu private WorkingBeatmap introBeatmap; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) + private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { - this.beatmap.BindTo(beatmap); - menuVoice = config.GetBindable(OsuSetting.MenuVoice); menuMusic = config.GetBindable(OsuSetting.MenuMusic); BeatmapSetInfo setInfo = null; - if (!menuMusic) + if (!menuMusic.Value) { var sets = beatmaps.GetAllUsableBeatmapSets(); if (sets.Count > 0) @@ -95,15 +91,15 @@ namespace osu.Game.Screens.Menu if (!resuming) { - beatmap.Value = introBeatmap; + Beatmap.Value = introBeatmap; - if (menuVoice) + if (menuVoice.Value) welcome.Play(); Scheduler.AddDelayed(delegate { // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. - if (menuMusic) + if (menuMusic.Value) track.Start(); LoadComponentAsync(mainMenu = new MainMenu()); @@ -111,12 +107,11 @@ namespace osu.Game.Screens.Menu Scheduler.AddDelayed(delegate { DidLoadMenu = true; - Push(mainMenu); + this.Push(mainMenu); }, delay_step_one); }, delay_step_two); } - logo.RelativePositionAxes = Axes.Both; logo.Colour = Color4.White; logo.Ripple = false; @@ -145,31 +140,30 @@ namespace osu.Game.Screens.Menu } } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { - Content.FadeOut(300); + this.FadeOut(300); base.OnSuspending(next); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { //cancel exiting if we haven't loaded the menu yet. return !DidLoadMenu; } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { - if (!(last is MainMenu)) - Content.FadeIn(300); + this.FadeIn(300); double fadeOutTime = EXIT_DELAY; //we also handle the exit transition. - if (menuVoice) + if (menuVoice.Value) seeya.Play(); else fadeOutTime = 500; - Scheduler.AddDelayed(Exit, fadeOutTime); + Scheduler.AddDelayed(this.Exit, fadeOutTime); //don't want to fade out completely else we will stop running updates and shit will hit the fan. Game.FadeTo(0.01f, fadeOutTime); diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index 91dc7937f8..093d01f12d 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osuTK; @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Menu Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, - Children = new [] + Children = new[] { lineTopLeft = new Box { @@ -102,9 +102,8 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Text = "welcome", Padding = new MarginPadding { Bottom = 10 }, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), Alpha = 0, - TextSize = 42, Spacing = new Vector2(5), }, new CircularContainer diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 70a01a5c9f..a41a12927b 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -1,10 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; -using osuTK.Graphics.ES30; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.Colour; @@ -16,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; namespace osu.Game.Screens.Menu { @@ -64,7 +63,7 @@ namespace osu.Game.Screens.Menu private readonly float[] frequencyAmplitudes = new float[256]; - private Shader shader; + private IShader shader; private readonly Texture texture; public LogoVisualisation() @@ -75,7 +74,7 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private void load(ShaderManager shaders, IBindableBeatmap beatmap) + private void load(ShaderManager shaders, IBindable beatmap) { this.beatmap.BindTo(beatmap); shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); @@ -132,8 +131,6 @@ namespace osu.Game.Screens.Menu protected override DrawNode CreateDrawNode() => new VisualisationDrawNode(); - private readonly VisualiserSharedData sharedData = new VisualiserSharedData(); - protected override void ApplyDrawNode(DrawNode node) { base.ApplyDrawNode(node); @@ -143,27 +140,23 @@ namespace osu.Game.Screens.Menu visNode.Shader = shader; visNode.Texture = texture; visNode.Size = DrawSize.X; - visNode.Shared = sharedData; visNode.Colour = AccentColour; visNode.AudioData = frequencyAmplitudes; } - private class VisualiserSharedData - { - public readonly LinearBatch VertexBatch = new LinearBatch(100 * 4, 10, PrimitiveType.Quads); - } - private class VisualisationDrawNode : DrawNode { - public Shader Shader; + public IShader Shader; public Texture Texture; - public VisualiserSharedData Shared; + //Asuming the logo is a circle, we don't need a second dimension. public float Size; public Color4 Colour; public float[] AudioData; + private readonly QuadBatch vertexBatch = new QuadBatch(100, 10); + public override void Draw(Action vertexAction) { base.Draw(vertexAction); @@ -208,14 +201,22 @@ namespace osu.Game.Screens.Menu rectangle, colourInfo, null, - Shared.VertexBatch.AddAction, + vertexBatch.AddAction, //barSize by itself will make it smooth more in the X axis than in the Y axis, this reverts that. Vector2.Divide(inflation, barSize.Yx)); } } } + Shader.Unbind(); } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + vertexBatch.Dispose(); + } } } } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 974e42dda0..5403f7c702 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; using osuTK.Input; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Screens; @@ -18,36 +19,39 @@ using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; using osu.Game.Screens.Select; using osu.Game.Screens.Tournament; +using osu.Framework.Platform; namespace osu.Game.Screens.Menu { public class MainMenu : OsuScreen { - private readonly ButtonSystem buttons; + private ButtonSystem buttons; - protected override bool HideOverlaysOnEnter => buttons.State == ButtonSystemState.Initial; + public override bool HideOverlaysOnEnter => buttons.State == ButtonSystemState.Initial; - protected override bool AllowBackButton => buttons.State != ButtonSystemState.Initial; + protected override bool AllowBackButton => buttons.State != ButtonSystemState.Initial && host.CanExit; public override bool AllowExternalScreenChange => true; - private readonly BackgroundScreenDefault background; private Screen songSelect; - private readonly MenuSideFlashes sideFlashes; + private MenuSideFlashes sideFlashes; + + [Resolved] + private GameHost host { get; set; } + + private BackgroundScreenDefault background; protected override BackgroundScreen CreateBackground() => background; - public MainMenu() + [BackgroundDependencyLoader(true)] + private void load(OsuGame game = null) { - background = new BackgroundScreenDefault(); + if (host.CanExit) + AddInternal(new ExitConfirmOverlay { Action = this.Exit }); - Children = new Drawable[] + AddRangeInternal(new Drawable[] { - new ExitConfirmOverlay - { - Action = Exit, - }, new ParallaxContainer { ParallaxAmount = 0.01f, @@ -55,17 +59,17 @@ namespace osu.Game.Screens.Menu { buttons = new ButtonSystem { - OnChart = delegate { Push(new ChartListing()); }, - OnDirect = delegate { Push(new OnlineListing()); }, - OnEdit = delegate { Push(new Editor()); }, + OnChart = delegate { this.Push(new ChartListing()); }, + OnDirect = delegate { this.Push(new OnlineListing()); }, + OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, - OnMulti = delegate { Push(new Multiplayer()); }, - OnExit = Exit, + OnMulti = delegate { this.Push(new Multiplayer()); }, + OnExit = this.Exit, } } }, sideFlashes = new MenuSideFlashes(), - }; + }); buttons.StateChanged += state => { @@ -73,19 +77,13 @@ namespace osu.Game.Screens.Menu { case ButtonSystemState.Initial: case ButtonSystemState.Exit: - background.FadeColour(Color4.White, 500, Easing.OutSine); + Background.FadeColour(Color4.White, 500, Easing.OutSine); break; default: - background.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine); + Background.FadeColour(OsuColour.Gray(0.8f), 500, Easing.OutSine); break; } }; - } - - [BackgroundDependencyLoader(true)] - private void load(OsuGame game = null) - { - LoadComponentAsync(background); if (game != null) { @@ -93,6 +91,7 @@ namespace osu.Game.Screens.Menu buttons.OnDirect = game.ToggleDirect; } + LoadComponentAsync(background = new BackgroundScreenDefault()); preloadSongSelect(); } @@ -104,7 +103,7 @@ namespace osu.Game.Screens.Menu public void LoadToSolo() => Schedule(onSolo); - private void onSolo() => Push(consumeSongSelect()); + private void onSolo() => this.Push(consumeSongSelect()); private Screen consumeSongSelect() { @@ -113,7 +112,7 @@ namespace osu.Game.Screens.Menu return s; } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); buttons.FadeInFromZero(500); @@ -148,8 +147,8 @@ namespace osu.Game.Screens.Menu const float length = 300; - Content.FadeIn(length, Easing.OutQuint); - Content.MoveTo(new Vector2(0, 0), length, Easing.OutQuint); + this.FadeIn(length, Easing.OutQuint); + this.MoveTo(new Vector2(0, 0), length, Easing.OutQuint); sideFlashes.Delay(length).FadeIn(64, Easing.InQuint); } @@ -162,15 +161,15 @@ namespace osu.Game.Screens.Menu .OnComplete(l => buttons.SetOsuLogo(null)); } - private void beatmap_ValueChanged(WorkingBeatmap newValue) + private void beatmap_ValueChanged(ValueChangedEvent e) { - if (!IsCurrentScreen) + if (!this.IsCurrentScreen()) return; - background.Next(); + ((BackgroundScreenDefault)Background).Next(); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); @@ -178,26 +177,26 @@ namespace osu.Game.Screens.Menu buttons.State = ButtonSystemState.EnteringMode; - Content.FadeOut(length, Easing.InSine); - Content.MoveTo(new Vector2(-800, 0), length, Easing.InSine); + this.FadeOut(length, Easing.InSine); + this.MoveTo(new Vector2(-800, 0), length, Easing.InSine); sideFlashes.FadeOut(64, Easing.OutQuint); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { base.OnResuming(last); - background.Next(); + (Background as BackgroundScreenDefault)?.Next(); //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { buttons.State = ButtonSystemState.Exit; - Content.FadeOut(3000); + this.FadeOut(3000); return base.OnExiting(next); } @@ -205,7 +204,7 @@ namespace osu.Game.Screens.Menu { if (!e.Repeat && e.ControlPressed && e.ShiftPressed && e.Key == Key.D) { - Push(new Drawings()); + this.Push(new Drawings()); return true; } diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 188e95ced5..ce0a38ba8d 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -14,6 +13,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using System; +using osu.Framework.Bindables; namespace osu.Game.Screens.Menu { @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, OsuColour colours) + private void load(IBindable beatmap, OsuColour colours) { this.beatmap.BindTo(beatmap); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index eafe44c0fc..af697d37bd 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Menu public bool Triangles { - set { colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); } + set => colourAndTriangles.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); } public bool BeatMatching = true; @@ -71,8 +71,8 @@ namespace osu.Game.Screens.Menu public bool Ripple { - get { return rippleContainer.Alpha > 0; } - set { rippleContainer.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); } + get => rippleContainer.Alpha > 0; + set => rippleContainer.FadeTo(value ? 1 : 0, transition_length, Easing.OutQuint); } private readonly Box flashLayer; diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index b58af398ca..e096fb33da 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -1,12 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -14,10 +11,8 @@ using osu.Game.Online.Chat; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTitle : CompositeDrawable + public class BeatmapTitle : MultiplayerComposite { - public readonly IBindable Beatmap = new Bindable(); - private readonly LinkFlowContainer textFlow; public BeatmapTitle() @@ -27,13 +22,13 @@ namespace osu.Game.Screens.Multi.Components InternalChild = textFlow = new LinkFlowContainer { AutoSizeAxes = Axes.Both }; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - base.LoadComplete(); - Beatmap.BindValueChanged(v => updateText(), true); + CurrentItem.BindValueChanged(_ => updateText(), true); } - private float textSize = OsuSpriteText.FONT_SIZE; + private float textSize = OsuFont.DEFAULT_FONT_SIZE; public float TextSize { @@ -42,6 +37,7 @@ namespace osu.Game.Screens.Multi.Components { if (textSize == value) return; + textSize = value; updateText(); @@ -53,15 +49,17 @@ namespace osu.Game.Screens.Multi.Components private void updateText() { - if (!IsLoaded) + if (LoadState < LoadState.Loading) return; textFlow.Clear(); - if (Beatmap.Value == null) + var beatmap = CurrentItem.Value?.Beatmap; + + if (beatmap == null) textFlow.AddText("No beatmap selected", s => { - s.TextSize = TextSize; + s.Font = s.Font.With(size: TextSize); s.Colour = colours.PinkLight; }); else @@ -70,20 +68,20 @@ namespace osu.Game.Screens.Multi.Components { new OsuSpriteText { - Text = new LocalisedString((Beatmap.Value.Metadata.ArtistUnicode, Beatmap.Value.Metadata.Artist)), - TextSize = TextSize, + Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), + Font = OsuFont.GetFont(size: TextSize), }, new OsuSpriteText { Text = " - ", - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize), }, new OsuSpriteText { - Text = new LocalisedString((Beatmap.Value.Metadata.TitleUnicode, Beatmap.Value.Metadata.Title)), - TextSize = TextSize, + Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), + Font = OsuFont.GetFont(size: TextSize), } - }, null, LinkAction.OpenBeatmap, Beatmap.Value.OnlineBeatmapID.ToString(), "Open beatmap"); + }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } } } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index 04ac0cc4c3..23771451bd 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -1,31 +1,26 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; using osuTK; namespace osu.Game.Screens.Multi.Components { - public class BeatmapTypeInfo : CompositeDrawable + public class BeatmapTypeInfo : MultiplayerComposite { - public readonly IBindable Beatmap = new Bindable(); - public readonly IBindable Ruleset = new Bindable(); - public readonly IBindable Type = new Bindable(); - public BeatmapTypeInfo() { AutoSizeAxes = Axes.Both; + } - BeatmapTitle beatmapTitle; - ModeTypeInfo modeTypeInfo; + [BackgroundDependencyLoader] + private void load() + { LinkFlowContainer beatmapAuthor; InternalChild = new FillFlowContainer @@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Components Spacing = new Vector2(5, 0), Children = new Drawable[] { - modeTypeInfo = new ModeTypeInfo(), + new ModeTypeInfo(), new Container { AutoSizeAxes = Axes.X, @@ -44,8 +39,8 @@ namespace osu.Game.Screens.Multi.Components Margin = new MarginPadding { Left = 5 }, Children = new Drawable[] { - beatmapTitle = new BeatmapTitle(), - beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14) + new BeatmapTitle(), + beatmapAuthor = new LinkFlowContainer(s => s.Font = s.Font.With(size: 14)) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -56,22 +51,18 @@ namespace osu.Game.Screens.Multi.Components } }; - modeTypeInfo.Beatmap.BindTo(Beatmap); - modeTypeInfo.Ruleset.BindTo(Ruleset); - modeTypeInfo.Type.BindTo(Type); - - beatmapTitle.Beatmap.BindTo(Beatmap); - - Beatmap.BindValueChanged(v => + CurrentItem.BindValueChanged(item => { beatmapAuthor.Clear(); - if (v != null) + var beatmap = item.NewValue?.Beatmap; + + if (beatmap != null) { beatmapAuthor.AddText("mapped by ", s => s.Colour = OsuColour.Gray(0.8f)); - beatmapAuthor.AddLink(v.Metadata.Author.Username, null, LinkAction.OpenUserProfile, v.Metadata.Author.Id.ToString(), "View Profile"); + beatmapAuthor.AddLink(beatmap.Metadata.Author.Username, null, LinkAction.OpenUserProfile, beatmap.Metadata.Author.Id.ToString(), "View Profile"); } - }); + }, true); } } } diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index dc765832db..b6b0332cf3 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -29,8 +29,9 @@ namespace osu.Game.Screens.Multi.Components protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return true; + return base.OnClick(e); } } diff --git a/osu.Game/Screens/Multi/Components/DrawableGameType.cs b/osu.Game/Screens/Multi/Components/DrawableGameType.cs index 3406e179d4..f4941dd73a 100644 --- a/osu.Game/Screens/Multi/Components/DrawableGameType.cs +++ b/osu.Game/Screens/Multi/Components/DrawableGameType.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index aad409e2c7..6080458aec 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -1,32 +1,30 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; using osuTK; namespace osu.Game.Screens.Multi.Components { - public class ModeTypeInfo : CompositeDrawable + public class ModeTypeInfo : MultiplayerComposite { private const float height = 30; private const float transition_duration = 100; - private readonly Container rulesetContainer; - - public readonly IBindable Beatmap = new Bindable(); - public readonly IBindable Ruleset = new Bindable(); - public readonly IBindable Type = new Bindable(); + private Container drawableRuleset; public ModeTypeInfo() { AutoSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader] + private void load() + { Container gameTypeContainer; InternalChild = new FillFlowContainer @@ -37,7 +35,7 @@ namespace osu.Game.Screens.Multi.Components LayoutDuration = 100, Children = new[] { - rulesetContainer = new Container + drawableRuleset = new Container { AutoSizeAxes = Axes.Both, }, @@ -48,20 +46,20 @@ namespace osu.Game.Screens.Multi.Components }, }; - Beatmap.BindValueChanged(updateBeatmap); - Ruleset.BindValueChanged(_ => updateBeatmap(Beatmap.Value)); - Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }); + CurrentItem.BindValueChanged(item => updateBeatmap(item.NewValue), true); + + Type.BindValueChanged(type => gameTypeContainer.Child = new DrawableGameType(type.NewValue) { Size = new Vector2(height) }, true); } - private void updateBeatmap(BeatmapInfo beatmap) + private void updateBeatmap(PlaylistItem item) { - if (beatmap != null) + if (item?.Beatmap != null) { - rulesetContainer.FadeIn(transition_duration); - rulesetContainer.Child = new DifficultyIcon(beatmap, Ruleset.Value) { Size = new Vector2(height) }; + drawableRuleset.FadeIn(transition_duration); + drawableRuleset.Child = new DifficultyIcon(item.Beatmap, item.Ruleset) { Size = new Vector2(height) }; } else - rulesetContainer.FadeOut(transition_duration); + drawableRuleset.FadeOut(transition_duration); } } } diff --git a/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs b/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs new file mode 100644 index 0000000000..968fa6e72e --- /dev/null +++ b/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs @@ -0,0 +1,31 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Beatmaps.Drawables; + +namespace osu.Game.Screens.Multi.Components +{ + public class MultiplayerBackgroundSprite : MultiplayerComposite + { + private readonly BeatmapSetCoverType beatmapSetCoverType; + + public MultiplayerBackgroundSprite(BeatmapSetCoverType beatmapSetCoverType = BeatmapSetCoverType.Cover) + { + this.beatmapSetCoverType = beatmapSetCoverType; + } + + [BackgroundDependencyLoader] + private void load() + { + UpdateableBeatmapBackgroundSprite sprite; + + InternalChild = sprite = CreateBackgroundSprite(); + + CurrentItem.BindValueChanged(item => sprite.Beatmap.Value = item.NewValue?.Beatmap, true); + } + + protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(beatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; + } +} diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCountDisplay.cs similarity index 58% rename from osu.Game/Screens/Multi/Components/ParticipantCount.cs rename to osu.Game/Screens/Multi/Components/ParticipantCountDisplay.cs index fc19039872..498eeb09b3 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCountDisplay.cs @@ -1,31 +1,29 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Users; namespace osu.Game.Screens.Multi.Components { - public class ParticipantCountDisplay : CompositeDrawable + public class ParticipantCountDisplay : MultiplayerComposite { private const float text_size = 30; private const float transition_duration = 100; - private readonly OsuSpriteText slash, maxText; - - public readonly IBindable> Participants = new Bindable>(); - public readonly IBindable ParticipantCount = new Bindable(); - public readonly IBindable MaxParticipants = new Bindable(); + private OsuSpriteText slash, maxText; public ParticipantCountDisplay() { AutoSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader] + private void load() + { OsuSpriteText count; InternalChild = new FillFlowContainer @@ -37,26 +35,22 @@ namespace osu.Game.Screens.Multi.Components { count = new OsuSpriteText { - TextSize = text_size, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: text_size) }, slash = new OsuSpriteText { Text = @"/", - TextSize = text_size, - Font = @"Exo2.0-Light" + Font = OsuFont.GetFont(weight: FontWeight.Light, size: text_size) }, maxText = new OsuSpriteText { - TextSize = text_size, - Font = @"Exo2.0-Light" + Font = OsuFont.GetFont(weight: FontWeight.Light, size: text_size) }, } }; - Participants.BindValueChanged(v => count.Text = v.Count().ToString()); MaxParticipants.BindValueChanged(_ => updateMax(), true); - ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0")); + ParticipantCount.BindValueChanged(c => count.Text = c.NewValue.ToString("#,0"), true); } private void updateMax() diff --git a/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs index ca93ea2366..d799f846c2 100644 --- a/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs +++ b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,16 +13,16 @@ using osu.Game.Online.Multiplayer.RoomStatuses; namespace osu.Game.Screens.Multi.Components { - public class RoomStatusInfo : CompositeDrawable + public class RoomStatusInfo : MultiplayerComposite { - private readonly RoomBindings bindings = new RoomBindings(); - - public RoomStatusInfo(Room room) + public RoomStatusInfo() { - bindings.Room = room; - AutoSizeAxes = Axes.Both; + } + [BackgroundDependencyLoader] + private void load() + { StatusPart statusPart; EndDatePart endDatePart; @@ -34,17 +34,16 @@ namespace osu.Game.Screens.Multi.Components { statusPart = new StatusPart { - TextSize = 14, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14) }, - endDatePart = new EndDatePart { TextSize = 14 } + endDatePart = new EndDatePart { Font = OsuFont.GetFont(size: 14) } } }; - statusPart.EndDate.BindTo(bindings.EndDate); - statusPart.Status.BindTo(bindings.Status); - statusPart.Availability.BindTo(bindings.Availability); - endDatePart.EndDate.BindTo(bindings.EndDate); + statusPart.EndDate.BindTo(EndDate); + statusPart.Status.BindTo(Status); + statusPart.Availability.BindTo(Availability); + endDatePart.EndDate.BindTo(EndDate); } private class EndDatePart : DrawableDate @@ -54,7 +53,7 @@ namespace osu.Game.Screens.Multi.Components public EndDatePart() : base(DateTimeOffset.UtcNow) { - EndDate.BindValueChanged(d => Date = d); + EndDate.BindValueChanged(date => Date = date.NewValue); } protected override string Format() diff --git a/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs b/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs new file mode 100644 index 0000000000..97af6674bf --- /dev/null +++ b/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs @@ -0,0 +1,31 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Screens.Multi.Components +{ + public class StatusColouredContainer : Container + { + private readonly double transitionDuration; + + [Resolved(typeof(Room), nameof(Room.Status))] + private Bindable status { get; set; } + + public StatusColouredContainer(double transitionDuration = 100) + { + this.transitionDuration = transitionDuration; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + status.BindValueChanged(s => this.FadeColour(s.NewValue.GetAppropriateColour(colours), transitionDuration), true); + } + } +} diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 2849fd89e0..0e958bf523 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Multi private readonly OsuSpriteText screenType; private readonly HeaderBreadcrumbControl breadcrumbs; - public Header(Screen initialScreen) + public Header(ScreenStack stack) { RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Multi new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { new FillFlowContainer @@ -64,18 +64,17 @@ namespace osu.Game.Screens.Multi new OsuSpriteText { Text = "multiplayer ", - TextSize = 25, + Font = OsuFont.GetFont(size: 25) }, screenType = new OsuSpriteText { - TextSize = 25, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 25) }, }, }, }, }, - breadcrumbs = new HeaderBreadcrumbControl(initialScreen) + breadcrumbs = new HeaderBreadcrumbControl(stack) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -85,10 +84,10 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => + breadcrumbs.Current.ValueChanged += scren => { - if (s is IMultiplayerSubScreen mpScreen) - screenType.Text = mpScreen.ShortTitle.ToLowerInvariant(); + if (scren.NewValue is IMultiplayerSubScreen multiScreen) + screenType.Text = multiScreen.ShortTitle.ToLowerInvariant(); }; breadcrumbs.Current.TriggerChange(); @@ -103,8 +102,8 @@ namespace osu.Game.Screens.Multi private class HeaderBreadcrumbControl : ScreenBreadcrumbControl { - public HeaderBreadcrumbControl(Screen initialScreen) - : base(initialScreen) + public HeaderBreadcrumbControl(ScreenStack stack) + : base(stack) { } diff --git a/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs b/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs index 4796ffc05c..31ee123f83 100644 --- a/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs +++ b/osu.Game/Screens/Multi/IMultiplayerSubScreen.cs @@ -1,10 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Multi { - public interface IMultiplayerSubScreen + public interface IMultiplayerSubScreen : IOsuScreen { + string Title { get; } + string ShortTitle { get; } } } diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index 6af8a35208..f6c979851e 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Multiplayer; -using osu.Game.Screens.Multi.Lounge.Components; namespace osu.Game.Screens.Multi { @@ -40,11 +39,5 @@ namespace osu.Game.Screens.Multi /// Parts the currently-joined . /// void PartRoom(); - - /// - /// Queries for s matching a new . - /// - /// The to match. - void Filter(FilterCriteria criteria); } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index 219121cb53..4bab68058f 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -34,12 +35,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components public event Action StateChanged; - private readonly RoomBindings bindings = new RoomBindings(); - private readonly Box selectionBox; - private UpdateableBeatmapBackgroundSprite background; - private BeatmapTitle beatmapTitle; - private ModeTypeInfo modeTypeInfo; + private CachedModelDependencyContainer dependencies; [Resolved] private BeatmapManager beatmaps { get; set; } @@ -47,12 +44,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components public readonly Room Room; private SelectionState state; + public SelectionState State { - get { return state; } + get => state; set { if (value == state) return; + state = value; if (state == SelectionState.Selected) @@ -67,9 +66,10 @@ namespace osu.Game.Screens.Multi.Lounge.Components public IEnumerable FilterTerms => new[] { Room.Name.Value }; private bool matchingFilter; + public bool MatchingFilter { - get { return matchingFilter; } + get => matchingFilter; set { matchingFilter = value; @@ -80,7 +80,6 @@ namespace osu.Game.Screens.Multi.Lounge.Components public DrawableRoom(Room room) { Room = room; - bindings.Room = room; RelativeSizeAxes = Axes.X; Height = height + SELECTION_BORDER_WIDTH * 2; @@ -98,13 +97,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - Box sideStrip; - ParticipantInfo participantInfo; - OsuSpriteText name; - Children = new Drawable[] { - selectionBox, + new StatusColouredContainer(transition_duration) + { + RelativeSizeAxes = Axes.Both, + Child = selectionBox + }, new Container { RelativeSizeAxes = Axes.Both, @@ -127,10 +126,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"212121"), }, - sideStrip = new Box + new StatusColouredContainer(transition_duration) { RelativeSizeAxes = Axes.Y, Width = side_strip_width, + Child = new Box { RelativeSizeAxes = Axes.Both } }, new Container { @@ -138,7 +138,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Width = cover_width, Masking = true, Margin = new MarginPadding { Left = side_strip_width }, - Child = background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both } + Child = new MultiplayerBackgroundSprite(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both } }, new Container { @@ -159,8 +159,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components Spacing = new Vector2(5f), Children = new Drawable[] { - name = new OsuSpriteText { TextSize = 18 }, - participantInfo = new ParticipantInfo(), + new RoomName { Font = OsuFont.GetFont(size: 18) }, + new ParticipantInfo(), }, }, new FillFlowContainer @@ -173,11 +173,11 @@ namespace osu.Game.Screens.Multi.Lounge.Components Spacing = new Vector2(0, 5), Children = new Drawable[] { - new RoomStatusInfo(Room), - beatmapTitle = new BeatmapTitle { TextSize = 14 }, + new RoomStatusInfo(), + new BeatmapTitle { TextSize = 14 }, }, }, - modeTypeInfo = new ModeTypeInfo + new ModeTypeInfo { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, @@ -188,22 +188,13 @@ namespace osu.Game.Screens.Multi.Lounge.Components }, }, }; + } - background.Beatmap.BindTo(bindings.CurrentBeatmap); - modeTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); - modeTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); - modeTypeInfo.Type.BindTo(bindings.Type); - beatmapTitle.Beatmap.BindTo(bindings.CurrentBeatmap); - participantInfo.Host.BindTo(bindings.Host); - participantInfo.Participants.BindTo(bindings.Participants); - participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); - - bindings.Name.BindValueChanged(n => name.Text = n, true); - bindings.Status.BindValueChanged(s => - { - foreach (Drawable d in new Drawable[] { selectionBox, sideStrip }) - d.FadeColour(s.GetAppropriateColour(colours), transition_duration); - }, true); + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Model.Value = Room; + return dependencies; } protected override void LoadComplete() @@ -211,5 +202,17 @@ namespace osu.Game.Screens.Multi.Lounge.Components base.LoadComplete(); this.FadeInFromZero(transition_duration); } + + private class RoomName : OsuSpriteText + { + [Resolved(typeof(Room), nameof(Online.Multiplayer.Room.Name))] + private Bindable name { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + Current = name; + } + } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 286a4c18b0..8e14f76e4b 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -1,7 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Graphics; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -13,22 +15,46 @@ namespace osu.Game.Screens.Multi.Lounge.Components protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); protected override PrimaryFilter DefaultTab => PrimaryFilter.Open; + protected override float ContentHorizontalPadding => base.ContentHorizontalPadding + OsuScreen.HORIZONTAL_OVERFLOW_PADDING; + + [Resolved(CanBeNull = true)] + private Bindable filter { get; set; } + public FilterControl() { DisplayStyleControl.Hide(); } - public FilterCriteria CreateCriteria() => new FilterCriteria + [BackgroundDependencyLoader] + private void load() { - SearchString = Search.Current.Value ?? string.Empty, - PrimaryFilter = Tabs.Current, - SecondaryFilter = DisplayStyleControl.Dropdown.Current - }; + if (filter == null) + filter = new Bindable(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Search.Current.BindValueChanged(_ => updateFilter()); + Tabs.Current.BindValueChanged(_ => updateFilter(), true); + } + + private void updateFilter() + { + filter.Value = new FilterCriteria + { + SearchString = Search.Current.Value ?? string.Empty, + PrimaryFilter = Tabs.Current.Value, + SecondaryFilter = DisplayStyleControl.Dropdown.Current.Value + }; + } } public enum PrimaryFilter { Open, + [Description("Recently Ended")] RecentlyEnded, Participated, diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs index 0a1c8a3e84..666bc44a8d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterCriteria.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Multi.Lounge.Components { diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 34fc7fe886..40e59de25d 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -1,10 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -16,26 +14,24 @@ using osuTK; namespace osu.Game.Screens.Multi.Lounge.Components { - public class ParticipantInfo : Container + public class ParticipantInfo : MultiplayerComposite { - private readonly FillFlowContainer summaryContainer; - - public readonly IBindable Host = new Bindable(); - public readonly IBindable> Participants = new Bindable>(); - public readonly IBindable ParticipantCount = new Bindable(); - public ParticipantInfo() { - OsuSpriteText summary; RelativeSizeAxes = Axes.X; Height = 15f; + } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + OsuSpriteText summary; OsuSpriteText levelRangeHigher; OsuSpriteText levelRangeLower; Container flagContainer; LinkFlowContainer hostText; - Children = new Drawable[] + InternalChildren = new Drawable[] { new FillFlowContainer { @@ -73,46 +69,46 @@ namespace osu.Game.Screens.Multi.Lounge.Components } }, }, - summaryContainer = new FillFlowContainer + new FillFlowContainer { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Colour = colours.Gray9, Children = new[] { summary = new OsuSpriteText { Text = "0 participants", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) } }, }, }; - Host.BindValueChanged(v => + Host.BindValueChanged(host => { hostText.Clear(); - hostText.AddText("hosted by "); - hostText.AddLink(v.Username, null, LinkAction.OpenUserProfile, v.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic"); + flagContainer.Clear(); - flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; - }); + if (host.NewValue != null) + { + hostText.AddText("hosted by "); + hostText.AddLink(host.NewValue.Username, null, LinkAction.OpenUserProfile, host.NewValue.Id.ToString(), "Open profile", + s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); + flagContainer.Child = new DrawableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both }; + } + }, true); - ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}"); + ParticipantCount.BindValueChanged(count => summary.Text = "participant".ToQuantity(count.NewValue), true); - /*Participants.BindValueChanged(v => + /*Participants.BindValueChanged(e => { var ranks = v.Select(u => u.Statistics.Ranks.Global); levelRangeLower.Text = ranks.Min().ToString(); levelRangeHigher.Text = ranks.Max().ToString(); });*/ } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - summaryContainer.Colour = colours.Gray9; - } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 47f5182c39..5798fce457 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Linq; +using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -11,10 +11,10 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; using osu.Game.Users; @@ -23,235 +23,180 @@ using osuTK.Graphics; namespace osu.Game.Screens.Multi.Lounge.Components { - public class RoomInspector : Container + public class RoomInspector : MultiplayerComposite { private const float transition_duration = 100; - public readonly IBindable Room = new Bindable(); - private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; - private readonly RoomBindings bindings = new RoomBindings(); - - private OsuColour colours; - private Box statusStrip; - private UpdateableBeatmapBackgroundSprite background; private ParticipantCountDisplay participantCount; - private FillFlowContainer topFlow, participantsFlow; - private OsuSpriteText name, status; + private OsuSpriteText name; private BeatmapTypeInfo beatmapTypeInfo; - private ScrollContainer participantsScroll; private ParticipantInfo participantInfo; [Resolved] private BeatmapManager beatmaps { get; set; } + private readonly Bindable status = new Bindable(new RoomStatusNoneSelected()); + [BackgroundDependencyLoader] private void load(OsuColour colours) { - this.colours = colours; - - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex(@"343138"), }, - topFlow = new FillFlowContainer + new GridContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - new Container + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 200, - Masking = true, - Children = new Drawable[] + new FillFlowContainer { - background = new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, - new Box + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(20), - Children = new Drawable[] + new Container { - participantCount = new ParticipantCountDisplay + RelativeSizeAxes = Axes.X, + Height = 200, + Masking = true, + Children = new Drawable[] { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding(20), + Children = new Drawable[] + { + participantCount = new ParticipantCountDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + }, + name = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 30), + Current = Name + }, + }, + }, }, - name = new OsuSpriteText + }, + new StatusColouredContainer(transition_duration) + { + RelativeSizeAxes = Axes.X, + Height = 5, + Child = new Box { RelativeSizeAxes = Axes.Both } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - TextSize = 30, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d"), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + LayoutDuration = transition_duration, + Padding = contentPadding, + Spacing = new Vector2(0f, 5f), + Children = new Drawable[] + { + new StatusColouredContainer(transition_duration) + { + AutoSizeAxes = Axes.Both, + Child = new StatusText + { + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), + } + }, + beatmapTypeInfo = new BeatmapTypeInfo(), + }, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = contentPadding, + Children = new Drawable[] + { + participantInfo = new ParticipantInfo(), }, }, }, }, }, - statusStrip = new Box + new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 5, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + new MatchParticipants { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d"), - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - LayoutDuration = transition_duration, - Padding = contentPadding, - Spacing = new Vector2(0f, 5f), - Children = new Drawable[] - { - status = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, - beatmapTypeInfo = new BeatmapTypeInfo(), - }, - }, - }, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = contentPadding, - Children = new Drawable[] - { - participantInfo = new ParticipantInfo(), - }, - }, - }, - }, - participantsScroll = new OsuScrollContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Padding = new MarginPadding { Top = contentPadding.Top, Left = 38, Right = 37 }, - Children = new[] - { - participantsFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - LayoutDuration = transition_duration, - Spacing = new Vector2(5f), - }, - }, - }, + RelativeSizeAxes = Axes.Both, + } + } + } + } }; - participantInfo.Host.BindTo(bindings.Host); - participantInfo.ParticipantCount.BindTo(bindings.ParticipantCount); - participantInfo.Participants.BindTo(bindings.Participants); - - participantCount.Participants.BindTo(bindings.Participants); - participantCount.ParticipantCount.BindTo(bindings.ParticipantCount); - participantCount.MaxParticipants.BindTo(bindings.MaxParticipants); - - beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); - beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); - beatmapTypeInfo.Type.BindTo(bindings.Type); - background.Beatmap.BindTo(bindings.CurrentBeatmap); - - bindings.Status.BindValueChanged(displayStatus); - bindings.Participants.BindValueChanged(p => participantsFlow.ChildrenEnumerable = p.Select(u => new UserTile(u))); - bindings.Name.BindValueChanged(n => name.Text = n); - - Room.BindValueChanged(updateRoom, true); + Status.BindValueChanged(_ => updateStatus(), true); + RoomID.BindValueChanged(_ => updateStatus(), true); } - private void updateRoom(Room room) + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - bindings.Room = room; + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(status, new CacheInfo(nameof(Room.Status), typeof(Room))); + return dependencies; + } - if (room != null) + private void updateStatus() + { + if (RoomID.Value == null) { - participantsFlow.FadeIn(transition_duration); - participantCount.FadeIn(transition_duration); - beatmapTypeInfo.FadeIn(transition_duration); - name.FadeIn(transition_duration); - participantInfo.FadeIn(transition_duration); - } - else - { - participantsFlow.FadeOut(transition_duration); + status.Value = new RoomStatusNoneSelected(); + participantCount.FadeOut(transition_duration); beatmapTypeInfo.FadeOut(transition_duration); name.FadeOut(transition_duration); participantInfo.FadeOut(transition_duration); - - displayStatus(new RoomStatusNoneSelected()); } - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - participantsScroll.Height = DrawHeight - topFlow.DrawHeight; - } - - private void displayStatus(RoomStatus s) - { - status.Text = s.Message; - - Color4 c = s.GetAppropriateColour(colours); - statusStrip.FadeColour(c, transition_duration); - status.FadeColour(c, transition_duration); - } - - private class UserTile : Container, IHasTooltip - { - private readonly User user; - - public string TooltipText => user.Username; - - public UserTile(User user) + else { - this.user = user; - Size = new Vector2(70f); - CornerRadius = 5f; - Masking = true; + status.Value = Status.Value; - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"27252d"), - }, - new UpdateableAvatar - { - RelativeSizeAxes = Axes.Both, - User = user, - }, - }; + participantCount.FadeIn(transition_duration); + beatmapTypeInfo.FadeIn(transition_duration); + name.FadeIn(transition_duration); + participantInfo.FadeIn(transition_duration); } } @@ -260,5 +205,118 @@ namespace osu.Game.Screens.Multi.Lounge.Components public override string Message => @"No Room Selected"; public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8; } + + private class StatusText : OsuSpriteText + { + [Resolved(typeof(Room), nameof(Room.Status))] + private Bindable status { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + status.BindValueChanged(s => Text = s.NewValue.Message, true); + } + } + + private class MatchParticipants : MultiplayerComposite + { + private readonly FillFlowContainer fill; + + public MatchParticipants() + { + Padding = new MarginPadding { Horizontal = 10 }; + + InternalChild = new ScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = fill = new FillFlowContainer + { + Spacing = new Vector2(10), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + } + }; + } + + [BackgroundDependencyLoader] + private void load() + { + RoomID.BindValueChanged(_ => updateParticipants(), true); + } + + [Resolved] + private IAPIProvider api { get; set; } + + private GetRoomScoresRequest request; + + private void updateParticipants() + { + var roomId = RoomID.Value ?? 0; + + request?.Cancel(); + + // nice little progressive fade + int time = 500; + foreach (var c in fill.Children) + { + c.Delay(500 - time).FadeOut(time, Easing.Out); + time = Math.Max(20, time - 20); + c.Expire(); + } + + if (roomId == 0) return; + + request = new GetRoomScoresRequest(roomId); + request.Success += scores => + { + if (roomId != RoomID.Value) + return; + + fill.Clear(); + foreach (var s in scores) + fill.Add(new UserTile(s.User)); + + fill.FadeInFromZero(1000, Easing.OutQuint); + }; + + api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + request?.Cancel(); + base.Dispose(isDisposing); + } + + private class UserTile : CompositeDrawable, IHasTooltip + { + private readonly User user; + + public string TooltipText => user.Username; + + public UserTile(User user) + { + this.user = user; + Size = new Vector2(70f); + CornerRadius = 5f; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"27252d"), + }, + new UpdateableAvatar + { + RelativeSizeAxes = Axes.Both, + User = user, + }, + }; + } + } + } } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index 4ad8154090..99a6de0064 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,14 +19,14 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public Action JoinRequested; - private readonly Bindable selectedRoom = new Bindable(); - public IBindable SelectedRoom => selectedRoom; - private readonly IBindableList rooms = new BindableList(); private readonly FillFlowContainer roomFlow; public IReadOnlyList Rooms => roomFlow; + [Resolved] + private Bindable currentRoom { get; set; } + [Resolved] private IRoomManager roomManager { get; set; } @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updateSorting() { foreach (var room in roomFlow) - roomFlow.SetLayoutPosition(room, room.Room.Position); + roomFlow.SetLayoutPosition(room, room.Room.Position.Value); } private void selectRoom(Room room) @@ -121,7 +121,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components else roomFlow.Children.ForEach(r => r.State = r.Room == room ? SelectionState.Selected : SelectionState.NotSelected); - selectedRoom.Value = room; + currentRoom.Value = room; } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index d9633218eb..7cbae611ea 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -17,27 +17,19 @@ namespace osu.Game.Screens.Multi.Lounge { public class LoungeSubScreen : MultiplayerSubScreen { + public override string Title => "Lounge"; + protected readonly FilterControl Filter; private readonly Container content; - private readonly RoomsContainer rooms; - private readonly Action pushGameplayScreen; private readonly ProcessingOverlay processingOverlay; - [Resolved(CanBeNull = true)] - private IRoomManager roomManager { get; set; } + [Resolved] + private Bindable currentRoom { get; set; } - public override string Title => "Lounge"; - - protected override Drawable TransitionContent => content; - - public LoungeSubScreen(Action pushGameplayScreen) + public LoungeSubScreen() { - this.pushGameplayScreen = pushGameplayScreen; - - RoomInspector inspector; - - Children = new Drawable[] + InternalChildren = new Drawable[] { Filter = new FilterControl { Depth = -1 }, content = new Container @@ -60,13 +52,13 @@ namespace osu.Game.Screens.Multi.Lounge { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Child = rooms = new RoomsContainer { JoinRequested = joinRequested } + Child = new RoomsContainer { JoinRequested = joinRequested } }, }, processingOverlay = new ProcessingOverlay { Alpha = 0 } } }, - inspector = new RoomInspector + new RoomInspector { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -77,11 +69,7 @@ namespace osu.Game.Screens.Multi.Lounge }, }; - inspector.Room.BindTo(rooms.SelectedRoom); - - Filter.Search.Current.ValueChanged += s => filterRooms(); - Filter.Tabs.Current.ValueChanged += t => filterRooms(); - Filter.Search.Exit += Exit; + Filter.Search.Exit += this.Exit; } protected override void UpdateAfterChildren() @@ -91,47 +79,48 @@ namespace osu.Game.Screens.Multi.Lounge content.Padding = new MarginPadding { Top = Filter.DrawHeight, - Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH, - Right = SearchableListOverlay.WIDTH_PADDING, + Left = SearchableListOverlay.WIDTH_PADDING - DrawableRoom.SELECTION_BORDER_WIDTH + HORIZONTAL_OVERFLOW_PADDING, + Right = SearchableListOverlay.WIDTH_PADDING + HORIZONTAL_OVERFLOW_PADDING, }; } protected override void OnFocus(FocusEvent e) { - GetContainingInputManager().ChangeFocus(Filter.Search); + Filter.Search.TakeFocus(); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); Filter.Search.HoldFocus = true; } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { Filter.Search.HoldFocus = false; - // no base call; don't animate - return false; + return base.OnExiting(next); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); Filter.Search.HoldFocus = false; } - private void filterRooms() + public override void OnResuming(IScreen last) { - rooms.Filter(Filter.CreateCriteria()); - roomManager?.Filter(Filter.CreateCriteria()); + base.OnResuming(last); + + if (currentRoom.Value?.RoomID.Value == null) + currentRoom.Value = new Room(); } private void joinRequested(Room room) { processingOverlay.Show(); - roomManager?.JoinRoom(room, r => + RoomManager?.JoinRoom(room, r => { - Push(room); + Open(room); processingOverlay.Hide(); }, _ => processingOverlay.Hide()); } @@ -139,13 +128,15 @@ namespace osu.Game.Screens.Multi.Lounge /// /// Push a room as a new subscreen. /// - public void Push(Room room) + public void Open(Room room) { // Handles the case where a room is clicked 3 times in quick succession - if (!IsCurrentScreen) + if (!this.IsCurrentScreen()) return; - Push(new MatchSubScreen(room, s => pushGameplayScreen?.Invoke(s))); + currentRoom.Value = room; + + this.Push(new MatchSubScreen(room)); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs index caf686165f..ccb957734f 100644 --- a/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/GameTypePicker.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 4cb6d7a4e0..e1592532a3 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -13,6 +14,7 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Play.HUD; using osuTK; @@ -20,31 +22,27 @@ using osuTK.Graphics; namespace osu.Game.Screens.Multi.Match.Components { - public class Header : Container + public class Header : MultiplayerComposite { public const float HEIGHT = 200; - private readonly RoomBindings bindings = new RoomBindings(); + public MatchTabControl Tabs; - private readonly Box tabStrip; + public Action RequestBeatmapSelection; - public readonly MatchTabControl Tabs; - - public Action OnRequestSelectBeatmap; - - public Header(Room room) + public Header() { RelativeSizeAxes = Axes.X; Height = HEIGHT; + } - bindings.Room = room; - - BeatmapTypeInfo beatmapTypeInfo; + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { BeatmapSelectButton beatmapButton; - UpdateableBeatmapBackgroundSprite background; ModDisplay modDisplay; - Children = new Drawable[] + InternalChildren = new Drawable[] { new Container { @@ -52,7 +50,7 @@ namespace osu.Game.Screens.Multi.Match.Components Masking = true, Children = new Drawable[] { - background = new HeaderBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }, + new HeaderBackgroundSprite { RelativeSizeAxes = Axes.Both }, new Box { RelativeSizeAxes = Axes.Both, @@ -60,17 +58,18 @@ namespace osu.Game.Screens.Multi.Match.Components }, } }, - tabStrip = new Box + new Box { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, Height = 1, + Colour = colours.Yellow }, new Container { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { new FillFlowContainer @@ -80,7 +79,7 @@ namespace osu.Game.Screens.Multi.Match.Components Direction = FillDirection.Vertical, Children = new Drawable[] { - beatmapTypeInfo = new BeatmapTypeInfo(), + new BeatmapTypeInfo(), modDisplay = new ModDisplay { Scale = new Vector2(0.75f), @@ -95,13 +94,13 @@ namespace osu.Game.Screens.Multi.Match.Components RelativeSizeAxes = Axes.Y, Width = 200, Padding = new MarginPadding { Vertical = 10 }, - Child = beatmapButton = new BeatmapSelectButton(room) + Child = beatmapButton = new BeatmapSelectButton { RelativeSizeAxes = Axes.Both, Height = 1, }, }, - Tabs = new MatchTabControl(room) + Tabs = new MatchTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -111,37 +110,36 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - beatmapTypeInfo.Beatmap.BindTo(bindings.CurrentBeatmap); - beatmapTypeInfo.Ruleset.BindTo(bindings.CurrentRuleset); - beatmapTypeInfo.Type.BindTo(bindings.Type); - background.Beatmap.BindTo(bindings.CurrentBeatmap); - bindings.CurrentMods.BindValueChanged(m => modDisplay.Current.Value = m, true); + CurrentItem.BindValueChanged(item => modDisplay.Current.Value = item.NewValue?.RequiredMods ?? Enumerable.Empty(), true); - beatmapButton.Action = () => OnRequestSelectBeatmap?.Invoke(); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - tabStrip.Colour = colours.Yellow; + beatmapButton.Action = () => RequestBeatmapSelection?.Invoke(); } private class BeatmapSelectButton : HeaderButton { - private readonly IBindable roomIDBind = new Bindable(); + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } - public BeatmapSelectButton(Room room) + public BeatmapSelectButton() { Text = "Select beatmap"; + } - roomIDBind.BindTo(room.RoomID); - roomIDBind.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true); + [BackgroundDependencyLoader] + private void load() + { + roomId.BindValueChanged(id => this.FadeTo(id.NewValue.HasValue ? 0 : 1), true); } } - private class HeaderBeatmapBackgroundSprite : UpdateableBeatmapBackgroundSprite + private class HeaderBackgroundSprite : MultiplayerBackgroundSprite { - protected override double FadeDuration => 200; + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + + private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double FadeDuration => 200; + } } } } diff --git a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs index 30fe609ede..f3412d0be7 100644 --- a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -41,8 +41,7 @@ namespace osu.Game.Screens.Multi.Match.Components Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Font = @"Exo2.0-Light", - TextSize = 30, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), }; } } diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 993dccce44..02c8929f44 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; using osu.Game.Users; @@ -42,7 +43,7 @@ namespace osu.Game.Screens.Multi.Match.Components } }; - Host.BindValueChanged(updateHost); + Host.BindValueChanged(host => updateHost(host.NewValue)); } private void updateHost(User host) @@ -53,7 +54,8 @@ namespace osu.Game.Screens.Multi.Match.Components { linkContainer.AddText("hosted by"); linkContainer.NewLine(); - linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic"); + linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", + s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index 0aabc014c9..a944d965bd 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -1,36 +1,38 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Online.Multiplayer; using osu.Game.Overlays.SearchableList; using osu.Game.Screens.Multi.Components; using osuTK; namespace osu.Game.Screens.Multi.Match.Components { - public class Info : Container + public class Info : MultiplayerComposite { public Action OnStart; - private readonly RoomBindings bindings = new RoomBindings(); - - public Info(Room room) + public Info() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + } + [BackgroundDependencyLoader] + private void load() + { ReadyButton readyButton; ViewBeatmapButton viewBeatmapButton; HostInfo hostInfo; RoomStatusInfo statusInfo; - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { @@ -41,7 +43,7 @@ namespace osu.Game.Screens.Multi.Match.Components { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING + OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { new FillFlowContainer @@ -60,10 +62,10 @@ namespace osu.Game.Screens.Multi.Match.Components { new OsuSpriteText { - TextSize = 30, - Current = bindings.Name + Font = OsuFont.GetFont(size: 30), + Current = Name }, - new RoomStatusInfo(room), + new RoomStatusInfo(), } }, hostInfo = new HostInfo(), @@ -80,7 +82,7 @@ namespace osu.Game.Screens.Multi.Match.Components Children = new Drawable[] { viewBeatmapButton = new ViewBeatmapButton(), - readyButton = new ReadyButton(room) + readyButton = new ReadyButton { Action = () => OnStart?.Invoke() } @@ -90,11 +92,13 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - viewBeatmapButton.Beatmap.BindTo(bindings.CurrentBeatmap); - readyButton.Beatmap.BindTo(bindings.CurrentBeatmap); - hostInfo.Host.BindTo(bindings.Host); + CurrentItem.BindValueChanged(item => + { + viewBeatmapButton.Beatmap.Value = item.NewValue?.Beatmap; + readyButton.Beatmap.Value = item.NewValue?.Beatmap; + }, true); - bindings.Room = room; + hostInfo.Host.BindTo(Host); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs index 0d7221754f..f8b64a54ef 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Online.Chat; using osu.Game.Online.Multiplayer; @@ -9,28 +10,33 @@ namespace osu.Game.Screens.Multi.Match.Components { public class MatchChatDisplay : StandAloneChatDisplay { - private readonly Room room; + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } + + [Resolved(typeof(Room), nameof(Room.ChannelId))] + private Bindable channelId { get; set; } [Resolved(CanBeNull = true)] private ChannelManager channelManager { get; set; } - public MatchChatDisplay(Room room) + public MatchChatDisplay() : base(true) { - this.room = room; } protected override void LoadComplete() { base.LoadComplete(); - room.RoomID.BindValueChanged(v => updateChannel(), true); + channelId.BindValueChanged(_ => updateChannel(), true); } private void updateChannel() { - if (room.RoomID.Value != null) - Channel.Value = channelManager?.JoinChannel(new Channel { Id = room.ChannelId, Type = ChannelType.Multiplayer, Name = $"#mp_{room.RoomID}" }); + if (roomId.Value == null || channelId.Value == 0) + return; + + Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId.Value, Type = ChannelType.Multiplayer, Name = $"#lazermp_{roomId.Value}" }); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 864191105f..fff713f026 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -16,19 +17,15 @@ namespace osu.Game.Screens.Multi.Match.Components { public Action> ScoresLoaded; - private readonly Room room; - - public MatchLeaderboard(Room room) - { - this.room = room; - } + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } [BackgroundDependencyLoader] private void load() { - room.RoomID.BindValueChanged(id => + roomId.BindValueChanged(id => { - if (id == null) + if (id.NewValue == null) return; Scores = null; @@ -38,10 +35,10 @@ namespace osu.Game.Screens.Multi.Match.Components protected override APIRequest FetchScores(Action> scoresCallback) { - if (room.RoomID == null) + if (roomId.Value == null) return null; - var req = new GetRoomScoresRequest(room.RoomID.Value ?? 0); + var req = new GetRoomScoresRequest(roomId.Value ?? 0); req.Success += r => { diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs index ebd69b24fc..ed09203f96 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboardScore.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs index 54ba345934..fc98db157b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Multi.Match.Components { diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 69ca4b1deb..586a986111 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,43 +23,56 @@ namespace osu.Game.Screens.Multi.Match.Components { private const float transition_duration = 350; private const float field_padding = 45; - private const float disabled_alpha = 0.2f; - private readonly RoomBindings bindings = new RoomBindings(); + protected MatchSettings Settings { get; private set; } - private readonly Container content; - - private readonly OsuSpriteText typeLabel; - - protected readonly OsuTextBox NameField, MaxParticipantsField; - protected readonly OsuDropdown DurationField; - protected readonly RoomAvailabilityPicker AvailabilityPicker; - protected readonly GameTypePicker TypePicker; - protected readonly TriangleButton ApplyButton; - protected readonly OsuPasswordTextBox PasswordField; - - protected readonly OsuSpriteText ErrorText; - - private readonly ProcessingOverlay processingOverlay; - - private readonly Room room; - - [Resolved(CanBeNull = true)] - private IRoomManager manager { get; set; } - - public MatchSettingsOverlay(Room room) + [BackgroundDependencyLoader] + private void load() { - this.room = room; - - bindings.Room = room; - Masking = true; - Child = content = new Container + Child = Settings = new MatchSettings { RelativeSizeAxes = Axes.Both, - RelativePositionAxes = Axes.Y, - Children = new Drawable[] + RelativePositionAxes = Axes.Y + }; + } + + protected override void PopIn() + { + Settings.MoveToY(0, transition_duration, Easing.OutQuint); + } + + protected override void PopOut() + { + Settings.MoveToY(-1, transition_duration, Easing.InSine); + } + + protected class MatchSettings : MultiplayerComposite + { + private const float disabled_alpha = 0.2f; + + public OsuTextBox NameField, MaxParticipantsField; + public OsuDropdown DurationField; + public RoomAvailabilityPicker AvailabilityPicker; + public GameTypePicker TypePicker; + public TriangleButton ApplyButton; + + public OsuSpriteText ErrorText; + + private OsuSpriteText typeLabel; + private ProcessingOverlay processingOverlay; + + [Resolved(CanBeNull = true)] + private IRoomManager manager { get; set; } + + [Resolved] + private Bindable currentRoom { get; set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + InternalChildren = new Drawable[] { new Box { @@ -79,7 +93,11 @@ namespace osu.Game.Screens.Multi.Match.Components { new ScrollContainer { - Padding = new MarginPadding { Vertical = 10 }, + Padding = new MarginPadding + { + Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING, + Vertical = 10 + }, RelativeSizeAxes = Axes.Both, Children = new[] { @@ -107,7 +125,10 @@ namespace osu.Game.Screens.Multi.Match.Components new Section("Room visibility") { Alpha = disabled_alpha, - Child = AvailabilityPicker = new RoomAvailabilityPicker(), + Child = AvailabilityPicker = new RoomAvailabilityPicker + { + Enabled = { Value = false } + }, }, new Section("Game type") { @@ -123,10 +144,12 @@ namespace osu.Game.Screens.Multi.Match.Components TypePicker = new GameTypePicker { RelativeSizeAxes = Axes.X, + Enabled = { Value = false } }, typeLabel = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), + Colour = colours.Yellow }, }, }, @@ -147,7 +170,8 @@ namespace osu.Game.Screens.Multi.Match.Components { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), + ReadOnly = true, + OnCommit = (sender, text) => apply() }, }, new Section("Duration") @@ -173,10 +197,11 @@ namespace osu.Game.Screens.Multi.Match.Components new Section("Password (optional)") { Alpha = disabled_alpha, - Child = PasswordField = new SettingsPasswordTextBox + Child = new SettingsPasswordTextBox { RelativeSizeAxes = Axes.X, TabbableContentContainer = this, + ReadOnly = true, OnCommit = (sender, text) => apply() }, }, @@ -210,6 +235,7 @@ namespace osu.Game.Screens.Multi.Match.Components Direction = FillDirection.Vertical, Spacing = new Vector2(0, 20), Margin = new MarginPadding { Vertical = 20 }, + Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { ApplyButton = new CreateRoomButton @@ -217,6 +243,7 @@ namespace osu.Game.Screens.Multi.Match.Components Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Size = new Vector2(230, 55), + Enabled = { Value = false }, Action = apply, }, ErrorText = new OsuSpriteText @@ -224,7 +251,8 @@ namespace osu.Game.Screens.Multi.Match.Components Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Alpha = 0, - Depth = 1 + Depth = 1, + Colour = colours.RedDark } } } @@ -234,86 +262,66 @@ namespace osu.Game.Screens.Multi.Match.Components } }, processingOverlay = new ProcessingOverlay { Alpha = 0 } - }, - }; + }; - TypePicker.Current.ValueChanged += t => typeLabel.Text = t.Name; + TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); + Name.BindValueChanged(name => NameField.Text = name.NewValue, true); + Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true); + Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); + MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true); + Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue, true); + } - bindings.Name.BindValueChanged(n => NameField.Text = n, true); - bindings.Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true); - bindings.Type.BindValueChanged(t => TypePicker.Current.Value = t, true); - bindings.MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true); - bindings.Duration.BindValueChanged(d => DurationField.Current.Value = d, true); - } + protected override void Update() + { + base.Update(); - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - typeLabel.Colour = colours.Yellow; - ErrorText.Colour = colours.RedDark; + ApplyButton.Enabled.Value = hasValidSettings; + } - MaxParticipantsField.ReadOnly = true; - PasswordField.ReadOnly = true; - AvailabilityPicker.Enabled.Value = false; - TypePicker.Enabled.Value = false; - ApplyButton.Enabled.Value = false; - } + private bool hasValidSettings => RoomID.Value == null && NameField.Text.Length > 0 && Playlist.Count > 0; - protected override void Update() - { - base.Update(); + private void apply() + { + hideError(); - ApplyButton.Enabled.Value = hasValidSettings; - } + Name.Value = NameField.Text; + Availability.Value = AvailabilityPicker.Current.Value; + Type.Value = TypePicker.Current.Value; - private bool hasValidSettings => bindings.Room.RoomID.Value == null && NameField.Text.Length > 0 && bindings.Playlist.Count > 0; + if (int.TryParse(MaxParticipantsField.Text, out int max)) + MaxParticipants.Value = max; + else + MaxParticipants.Value = null; - protected override void PopIn() - { - content.MoveToY(0, transition_duration, Easing.OutQuint); - } + Duration.Value = DurationField.Current.Value; - protected override void PopOut() - { - content.MoveToY(-1, transition_duration, Easing.InSine); - } + manager?.CreateRoom(currentRoom.Value, onSuccess, onError); - private void apply() - { - hideError(); + processingOverlay.Show(); + } - bindings.Name.Value = NameField.Text; - bindings.Availability.Value = AvailabilityPicker.Current.Value; - bindings.Type.Value = TypePicker.Current.Value; + private void hideError() => ErrorText.FadeOut(50); - if (int.TryParse(MaxParticipantsField.Text, out int max)) - bindings.MaxParticipants.Value = max; - else - bindings.MaxParticipants.Value = null; + private void onSuccess(Room room) => processingOverlay.Hide(); - bindings.Duration.Value = DurationField.Current.Value; + private void onError(string text) + { + ErrorText.Text = text; + ErrorText.FadeIn(50); - manager?.CreateRoom(room, onSuccess, onError); - - processingOverlay.Show(); - } - - private void hideError() => ErrorText.FadeOut(50); - - private void onSuccess(Room room) => processingOverlay.Hide(); - - private void onError(string text) - { - ErrorText.Text = text; - ErrorText.FadeIn(50); - - processingOverlay.Hide(); + processingOverlay.Hide(); + } } private class SettingsTextBox : OsuTextBox { - protected override Color4 BackgroundUnfocused => Color4.Black; - protected override Color4 BackgroundFocused => Color4.Black; + [BackgroundDependencyLoader] + private void load() + { + BackgroundUnfocused = Color4.Black; + BackgroundFocused = Color4.Black; + } } private class SettingsNumberTextBox : SettingsTextBox @@ -323,8 +331,12 @@ namespace osu.Game.Screens.Multi.Match.Components private class SettingsPasswordTextBox : OsuPasswordTextBox { - protected override Color4 BackgroundUnfocused => Color4.Black; - protected override Color4 BackgroundFocused => Color4.Black; + [BackgroundDependencyLoader] + private void load() + { + BackgroundUnfocused = Color4.Black; + BackgroundFocused = Color4.Black; + } } private class SectionContainer : FillFlowContainer
@@ -360,8 +372,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new OsuSpriteText { - TextSize = 12, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Text = title.ToUpper(), }, content = new Container diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index a9932ee3c6..c700d7b88a 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -14,12 +14,11 @@ namespace osu.Game.Screens.Multi.Match.Components { public class MatchTabControl : PageTabControl { - private readonly IBindable roomIdBind = new Bindable(); + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } - public MatchTabControl(Room room) + public MatchTabControl() { - roomIdBind.BindTo(room.RoomID); - AddItem(new RoomMatchPage()); AddItem(new SettingsMatchPage()); } @@ -27,9 +26,9 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - roomIdBind.BindValueChanged(v => + roomId.BindValueChanged(id => { - if (v.HasValue) + if (id.NewValue.HasValue) { Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); Current.Value = new RoomMatchPage(); @@ -52,13 +51,14 @@ namespace osu.Game.Screens.Multi.Match.Components : base(value) { enabled.BindTo(value.Enabled); - enabled.BindValueChanged(v => Colour = v ? Color4.White : Color4.Gray); + enabled.BindValueChanged(enabled => Colour = enabled.NewValue ? Color4.White : Color4.Gray, true); } protected override bool OnClick(ClickEvent e) { if (!enabled.Value) return true; + return base.OnClick(e); } } diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs index 56c8c3e8fc..09d25572ec 100644 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -1,9 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.SearchableList; @@ -13,16 +12,12 @@ using osuTK; namespace osu.Game.Screens.Multi.Match.Components { - public class Participants : CompositeDrawable + public class Participants : MultiplayerComposite { - public readonly IBindable> Users = new Bindable>(); - public readonly IBindable ParticipantCount = new Bindable(); - public readonly IBindable MaxParticipants = new Bindable(); - - public Participants() + [BackgroundDependencyLoader] + private void load() { FillFlowContainer usersFlow; - ParticipantCountDisplay count; InternalChild = new Container { @@ -36,7 +31,7 @@ namespace osu.Game.Screens.Multi.Match.Components Padding = new MarginPadding { Top = 10 }, Children = new Drawable[] { - count = new ParticipantCountDisplay + new ParticipantCountDisplay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -55,20 +50,22 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - count.Participants.BindTo(Users); - count.ParticipantCount.BindTo(ParticipantCount); - count.MaxParticipants.BindTo(MaxParticipants); - - Users.BindValueChanged(v => + Participants.BindValueChanged(participants => { - usersFlow.Children = v.Select(u => new UserPanel(u) + usersFlow.Children = participants.NewValue.Select(u => { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 300, - OnLoadComplete = d => d.FadeInFromZero(60), + var panel = new UserPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Width = 300, + }; + + panel.OnLoadComplete += d => d.FadeInFromZero(60); + + return panel; }).ToList(); - }); + }, true); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index d3726da246..86b4cfbfa7 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; @@ -14,21 +14,21 @@ namespace osu.Game.Screens.Multi.Match.Components { public class ReadyButton : HeaderButton { - public readonly IBindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); - private readonly Room room; + [Resolved(typeof(Room), nameof(Room.EndDate))] + private Bindable endDate { get; set; } [Resolved] - private IBindableBeatmap gameBeatmap { get; set; } + private IBindable gameBeatmap { get; set; } [Resolved] private BeatmapManager beatmaps { get; set; } private bool hasBeatmap; - public ReadyButton(Room room) + public ReadyButton() { - this.room = room; RelativeSizeAxes = Axes.Y; Size = new Vector2(200, 1); @@ -39,8 +39,9 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { beatmaps.ItemAdded += beatmapAdded; + beatmaps.ItemRemoved += beatmapRemoved; - Beatmap.BindValueChanged(updateBeatmap, true); + Beatmap.BindValueChanged(b => updateBeatmap(b.NewValue), true); } private void updateBeatmap(BeatmapInfo beatmap) @@ -53,12 +54,24 @@ namespace osu.Game.Screens.Multi.Match.Components hasBeatmap = beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID) != null; } - private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) + private void beatmapAdded(BeatmapSetInfo model, bool existing) { + if (Beatmap.Value == null) + return; + if (model.Beatmaps.Any(b => b.OnlineBeatmapID == Beatmap.Value.OnlineBeatmapID)) Schedule(() => hasBeatmap = true); } + private void beatmapRemoved(BeatmapSetInfo model) + { + if (Beatmap.Value == null) + return; + + if (model.OnlineBeatmapSetID == Beatmap.Value.BeatmapSet.OnlineBeatmapSetID) + Schedule(() => hasBeatmap = false); + } + protected override void Update() { base.Update(); @@ -74,7 +87,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < room.EndDate; + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } diff --git a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs index 4ddc9b30e9..8751e27552 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions; @@ -39,7 +39,8 @@ namespace osu.Game.Screens.Multi.Match.Components private readonly Box hover, selection; - public RoomAvailabilityPickerItem(RoomAvailability value) : base(value) + public RoomAvailabilityPickerItem(RoomAvailability value) + : base(value) { RelativeSizeAxes = Axes.Y; Width = 102; @@ -68,7 +69,7 @@ namespace osu.Game.Screens.Multi.Match.Components { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = value.GetDescription(), }, }; diff --git a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs index 82d0761fbf..8d1ff21124 100644 --- a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osuTK; @@ -11,7 +11,7 @@ namespace osu.Game.Screens.Multi.Match.Components { public class ViewBeatmapButton : HeaderButton { - public readonly IBindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); [Resolved(CanBeNull = true)] private OsuGame osuGame { get; set; } @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { if (osuGame != null) - Beatmap.BindValueChanged(updateAction, true); + Beatmap.BindValueChanged(beatmap => updateAction(beatmap.NewValue), true); } private void updateAction(BeatmapInfo beatmap) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 55a5a2c85e..a71106872e 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -1,37 +1,49 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; -using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; -using osu.Game.Screens.Play; using osu.Game.Screens.Select; +using PlaylistItem = osu.Game.Online.Multiplayer.PlaylistItem; namespace osu.Game.Screens.Multi.Match { public class MatchSubScreen : MultiplayerSubScreen { - public override bool AllowBeatmapRulesetChange => false; - public override string Title => room.RoomID.Value == null ? "New room" : room.Name.Value; + public override bool DisallowExternalBeatmapRulesetChanges => true; + + public override string Title { get; } + public override string ShortTitle => "room"; - private readonly RoomBindings bindings = new RoomBindings(); + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } - private readonly MatchLeaderboard leaderboard; + [Resolved(typeof(Room), nameof(Room.Name))] + private Bindable name { get; set; } - private readonly Action pushGameplayScreen; + [Resolved(typeof(Room), nameof(Room.Type))] + private Bindable type { get; set; } - [Cached] - private readonly Room room; + [Resolved(typeof(Room))] + protected BindableList Playlist { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable CurrentItem { get; private set; } + + [Resolved] + protected Bindable> SelectedMods { get; private set; } [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -39,48 +51,77 @@ namespace osu.Game.Screens.Multi.Match [Resolved(CanBeNull = true)] private OsuGame game { get; set; } - [Resolved(CanBeNull = true)] - private IRoomManager manager { get; set; } + private MatchLeaderboard leaderboard; - public MatchSubScreen(Room room, Action pushGameplayScreen) + public MatchSubScreen(Room room) { - this.room = room; - this.pushGameplayScreen = pushGameplayScreen; - - bindings.Room = room; + Title = room.RoomID.Value == null ? "New room" : room.Name.Value; + } + [BackgroundDependencyLoader] + private void load() + { MatchChatDisplay chat; Components.Header header; + Info info; + GridContainer bottomRow; MatchSettingsOverlay settings; - Children = new Drawable[] + InternalChildren = new Drawable[] { new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { - new Drawable[] { header = new Components.Header(room) { Depth = -1 } }, - new Drawable[] { new Info(room) { OnStart = onStart } }, new Drawable[] { - new GridContainer + header = new Components.Header + { + Depth = -1, + RequestBeatmapSelection = () => + { + this.Push(new MatchSongSelect + { + Selected = item => + { + Playlist.Clear(); + Playlist.Add(item); + } + }); + } + } + }, + new Drawable[] { info = new Info { OnStart = onStart } }, + new Drawable[] + { + bottomRow = new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { new Drawable[] { - leaderboard = new MatchLeaderboard(room) + leaderboard = new MatchLeaderboard { - Padding = new MarginPadding(10), + Padding = new MarginPadding + { + Left = 10 + HORIZONTAL_OVERFLOW_PADDING, + Right = 10, + Vertical = 10, + }, RelativeSizeAxes = Axes.Both }, new Container { - Padding = new MarginPadding(10), + Padding = new MarginPadding + { + Left = 10, + Right = 10 + HORIZONTAL_OVERFLOW_PADDING, + Vertical = 10, + }, RelativeSizeAxes = Axes.Both, - Child = chat = new MatchChatDisplay(room) + Child = chat = new MatchChatDisplay { RelativeSizeAxes = Axes.Both } @@ -101,93 +142,96 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Components.Header.HEIGHT }, - Child = settings = new MatchSettingsOverlay(room) { RelativeSizeAxes = Axes.Both }, + Child = settings = new MatchSettingsOverlay { RelativeSizeAxes = Axes.Both }, }, }; - header.OnRequestSelectBeatmap = () => Push(new MatchSongSelect { Selected = addPlaylistItem }); - header.Tabs.Current.ValueChanged += t => + header.Tabs.Current.BindValueChanged(tab => { - if (t is SettingsMatchPage) + const float fade_duration = 500; + if (tab.NewValue is SettingsMatchPage) + { settings.Show(); + info.FadeOut(fade_duration, Easing.OutQuint); + bottomRow.FadeOut(fade_duration, Easing.OutQuint); + } else + { settings.Hide(); + info.FadeIn(fade_duration, Easing.OutQuint); + bottomRow.FadeIn(fade_duration, Easing.OutQuint); + } + }, true); + + chat.Exit += () => + { + if (this.IsCurrentScreen()) + this.Exit(); }; - chat.Exit += Exit; - } - - [BackgroundDependencyLoader] - private void load() - { beatmapManager.ItemAdded += beatmapAdded; } - protected override bool OnExiting(Screen next) - { - manager?.PartRoom(); - return base.OnExiting(next); - } - protected override void LoadComplete() { base.LoadComplete(); - bindings.CurrentBeatmap.BindValueChanged(setBeatmap, true); - bindings.CurrentRuleset.BindValueChanged(setRuleset, true); + CurrentItem.BindValueChanged(currentItemChanged, true); } - private void setBeatmap(BeatmapInfo beatmap) + public override bool OnExiting(IScreen next) + { + RoomManager?.PartRoom(); + return base.OnExiting(next); + } + + /// + /// Handles propagation of the current playlist item's content to game-wide mechanisms. + /// + private void currentItemChanged(ValueChangedEvent e) { // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info - var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); + var localBeatmap = e.NewValue?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == e.NewValue.Beatmap.OnlineBeatmapID); - game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); + SelectedMods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); + if (e.NewValue?.Ruleset != null) + Ruleset.Value = e.NewValue.Ruleset; } - private void setRuleset(RulesetInfo ruleset) - { - if (ruleset == null) - return; - - game?.ForcefullySetRuleset(ruleset); - } - - private void beatmapAdded(BeatmapSetInfo model, bool existing, bool silent) => Schedule(() => + /// + /// Handle the case where a beatmap is imported (and can be used by this match). + /// + private void beatmapAdded(BeatmapSetInfo model, bool existing) => Schedule(() => { if (Beatmap.Value != beatmapManager.DefaultBeatmap) return; - if (bindings.CurrentBeatmap.Value == null) + if (Beatmap.Value == null) return; // Try to retrieve the corresponding local beatmap - var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == bindings.CurrentBeatmap.Value.OnlineBeatmapID); + var localBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == CurrentItem.Value.Beatmap.OnlineBeatmapID); if (localBeatmap != null) - game?.ForcefullySetBeatmap(beatmapManager.GetWorkingBeatmap(localBeatmap)); + Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); }); - private void addPlaylistItem(PlaylistItem item) - { - bindings.Playlist.Clear(); - bindings.Playlist.Add(item); - } + [Resolved(canBeNull: true)] + private Multiplayer multiplayer { get; set; } private void onStart() { - Beatmap.Value.Mods.Value = bindings.CurrentMods.Value.ToArray(); + Beatmap.Value.Mods.Value = SelectedMods.Value.ToArray(); - switch (bindings.Type.Value) + switch (type.Value) { default: case GameTypeTimeshift _: - pushGameplayScreen?.Invoke(new PlayerLoader(() => { - var player = new TimeshiftPlayer(room, room.Playlist.First().ID); - player.Exited += _ => leaderboard.RefreshScores(); - - return player; - })); + multiplayer?.Start(() => new TimeshiftPlayer(CurrentItem.Value) + { + Exited = () => leaderboard.RefreshScores() + }); break; } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index ce0eddbee3..5e019a7b3a 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -18,7 +19,9 @@ using osu.Game.Online.Multiplayer; using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Menu; using osu.Game.Screens.Multi.Lounge; +using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match; +using osu.Game.Screens.Play; using osuTK; namespace osu.Game.Screens.Multi @@ -26,83 +29,100 @@ namespace osu.Game.Screens.Multi [Cached] public class Multiplayer : OsuScreen, IOnlineComponent { - private readonly MultiplayerWaveContainer waves; + public override bool CursorVisible => (screenStack.CurrentScreen as IMultiplayerSubScreen)?.CursorVisible ?? true; - public override bool AllowBeatmapRulesetChange => currentSubScreen?.AllowBeatmapRulesetChange ?? base.AllowBeatmapRulesetChange; + public override bool DisallowExternalBeatmapRulesetChanges => true; + + private readonly MultiplayerWaveContainer waves; private readonly OsuButton createButton; private readonly LoungeSubScreen loungeSubScreen; + private readonly ScreenStack screenStack; - private OsuScreen currentSubScreen; + private readonly IBindable isIdle = new BindableBool(); + + [Cached] + private readonly Bindable currentRoom = new Bindable(); + + [Cached] + private readonly Bindable currentFilter = new Bindable(new FilterCriteria()); [Cached(Type = typeof(IRoomManager))] private RoomManager roomManager; [Resolved] - private APIAccess api { get; set; } + private OsuGameBase game { get; set; } + + [Resolved] + private IAPIProvider api { get; set; } + + [Resolved(CanBeNull = true)] + private OsuLogo logo { get; set; } public Multiplayer() { - Child = waves = new MultiplayerWaveContainer + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + Padding = new MarginPadding { Horizontal = -HORIZONTAL_OVERFLOW_PADDING }; + + InternalChild = waves = new MultiplayerWaveContainer { RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"3e3a44"), + }, + new Triangles + { + RelativeSizeAxes = Axes.Both, + ColourLight = OsuColour.FromHex(@"3c3842"), + ColourDark = OsuColour.FromHex(@"393540"), + TriangleScale = 5, + }, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = Header.HEIGHT }, + Child = screenStack = new OsuScreenStack(loungeSubScreen = new LoungeSubScreen()) { RelativeSizeAxes = Axes.Both } + }, + new Header(screenStack), + createButton = new HeaderButton + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.None, + Size = new Vector2(150, Header.HEIGHT - 20), + Margin = new MarginPadding + { + Top = 10, + Right = 10 + HORIZONTAL_OVERFLOW_PADDING, + }, + Text = "Create room", + Action = () => loungeSubScreen.Open(new Room + { + Name = { Value = $"{api.LocalUser}'s awesome room" } + }), + }, + roomManager = new RoomManager() + } }; - waves.AddRange(new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"3e3a44"), - }, - new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourLight = OsuColour.FromHex(@"3c3842"), - ColourDark = OsuColour.FromHex(@"393540"), - TriangleScale = 5, - }, - }, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = loungeSubScreen = new LoungeSubScreen(Push), - }, - new Header(loungeSubScreen), - createButton = new HeaderButton - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.None, - Size = new Vector2(150, Header.HEIGHT - 20), - Margin = new MarginPadding - { - Top = 10, - Right = 10, - }, - Text = "Create room", - Action = () => loungeSubScreen.Push(new Room - { - Name = { Value = $"{api.LocalUser}'s awesome room" } - }), - }, - roomManager = new RoomManager() - }); - - screenAdded(loungeSubScreen); - loungeSubScreen.Exited += _ => Exit(); + screenStack.ScreenPushed += screenPushed; + screenStack.ScreenExited += screenExited; } - private readonly IBindable isIdle = new BindableBool(); - [BackgroundDependencyLoader(true)] private void load(IdleTracker idleTracker) { @@ -115,16 +135,35 @@ namespace osu.Game.Screens.Multi protected override void LoadComplete() { base.LoadComplete(); - isIdle.BindValueChanged(updatePollingRate, true); + isIdle.BindValueChanged(idle => updatePollingRate(idle.NewValue), true); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Model.BindTo(currentRoom); + return dependencies; } private void updatePollingRate(bool idle) { - roomManager.TimeBetweenPolls = !IsCurrentScreen || !(currentSubScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000); + roomManager.TimeBetweenPolls = !this.IsCurrentScreen() || !(screenStack.CurrentScreen is LoungeSubScreen) ? 0 : (idle ? 120000 : 15000); Logger.Log($"Polling adjusted to {roomManager.TimeBetweenPolls}"); } - public void APIStateChanged(APIAccess api, APIState state) + /// + /// Push a to the main screen stack to begin gameplay. + /// Generally called from a via DI resolution. + /// + public void Start(Func player) + { + if (!this.IsCurrentScreen()) + return; + + this.Push(new PlayerLoader(player)); + } + + public void APIStateChanged(IAPIProvider api, APIState state) { if (state != APIState.Online) forcefullyExit(); @@ -133,78 +172,80 @@ namespace osu.Game.Screens.Multi private void forcefullyExit() { // This is temporary since we don't currently have a way to force screens to be exited - if (IsCurrentScreen) - Exit(); + if (this.IsCurrentScreen()) + this.Exit(); else { - MakeCurrent(); + this.MakeCurrent(); Schedule(forcefullyExit); } } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { - Content.FadeIn(); - - base.OnEntering(last); + this.FadeIn(); waves.Show(); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { waves.Hide(); - Content.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); + this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut(); cancelLooping(); - loungeSubScreen.MakeCurrent(); - updatePollingRate(isIdle.Value); - return base.OnExiting(next); - } - - protected override void OnResuming(Screen last) - { - base.OnResuming(last); - - Content.FadeIn(250); - Content.ScaleTo(1, 250, Easing.OutSine); + if (screenStack.CurrentScreen != null) + loungeSubScreen.MakeCurrent(); updatePollingRate(isIdle.Value); - } - protected override void OnSuspending(Screen next) - { - Content.ScaleTo(1.1f, 250, Easing.InSine); - Content.FadeOut(250); - - cancelLooping(); - roomManager.TimeBetweenPolls = 0; - - base.OnSuspending(next); - } - - private void cancelLooping() - { - var track = Beatmap.Value.Track; - if (track != null) - track.Looping = false; + base.OnExiting(next); + return false; } protected override void LogoExiting(OsuLogo logo) { + base.LogoExiting(logo); + // the wave overlay transition takes longer than expected to run. logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut(); - base.LogoExiting(logo); + } + + public override void OnResuming(IScreen last) + { + this.FadeIn(250); + this.ScaleTo(1, 250, Easing.OutSine); + + base.OnResuming(last); + + updatePollingRate(isIdle.Value); + } + + public override void OnSuspending(IScreen next) + { + this.ScaleTo(1.1f, 250, Easing.InSine); + this.FadeOut(250); + + cancelLooping(); + roomManager.TimeBetweenPolls = 0; + } + + private void cancelLooping() + { + var track = Beatmap?.Value?.Track; + + if (track != null) + track.Looping = false; } protected override void Update() { base.Update(); - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; - if (currentSubScreen is MatchSubScreen) + if (screenStack.CurrentScreen is MatchSubScreen) { var track = Beatmap.Value.Track; if (track != null) @@ -213,7 +254,7 @@ namespace osu.Game.Screens.Multi if (!track.IsRunning) { - Game.Audio.AddItemToList(track); + game.Audio.AddItemToList(track); track.Seek(Beatmap.Value.Metadata.PreviewTime); track.Start(); } @@ -221,26 +262,22 @@ namespace osu.Game.Screens.Multi createButton.Hide(); } - else if (currentSubScreen is LoungeSubScreen) + else if (screenStack.CurrentScreen is LoungeSubScreen) createButton.Show(); } - private void screenAdded(Screen newScreen) - { - currentSubScreen = (OsuScreen)newScreen; - updatePollingRate(isIdle.Value); + private void screenPushed(IScreen lastScreen, IScreen newScreen) + => updatePollingRate(isIdle.Value); - newScreen.ModePushed += screenAdded; - newScreen.Exited += screenRemoved; - } - - private void screenRemoved(Screen newScreen) + private void screenExited(IScreen lastScreen, IScreen newScreen) { - if (currentSubScreen is MatchSubScreen) + if (lastScreen is MatchSubScreen) cancelLooping(); - currentSubScreen = (OsuScreen)newScreen; updatePollingRate(isIdle.Value); + + if (screenStack.CurrentScreen == null) + this.Exit(); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/Multi/MultiplayerComposite.cs b/osu.Game/Screens/Multi/MultiplayerComposite.cs new file mode 100644 index 0000000000..da6bba7865 --- /dev/null +++ b/osu.Game/Screens/Multi/MultiplayerComposite.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Game.Online.Multiplayer; +using osu.Game.Users; + +namespace osu.Game.Screens.Multi +{ + public class MultiplayerComposite : CompositeDrawable + { + [Resolved(typeof(Room))] + protected Bindable RoomID { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Name { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Host { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Status { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Type { get; private set; } + + [Resolved(typeof(Room))] + protected BindableList Playlist { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable CurrentItem { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable> Participants { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable ParticipantCount { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable MaxParticipants { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable EndDate { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Availability { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable Duration { get; private set; } + } +} diff --git a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs index 5a7eaafba5..ad72072981 100644 --- a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs @@ -1,49 +1,78 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; namespace osu.Game.Screens.Multi { - public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen + public abstract class MultiplayerSubScreen : OsuScreen, IMultiplayerSubScreen, IKeyBindingHandler { - protected virtual Drawable TransitionContent => Content; + public override bool DisallowExternalBeatmapRulesetChanges => false; + + public override bool RemoveWhenNotAlive => false; public virtual string ShortTitle => Title; - protected override void OnEntering(Screen last) - { - base.OnEntering(last); + [Resolved(CanBeNull = true)] + protected OsuGame Game { get; private set; } - Content.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - TransitionContent.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - TransitionContent.MoveToX(200).MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + [Resolved(CanBeNull = true)] + protected IRoomManager RoomManager { get; private set; } + + protected MultiplayerSubScreen() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; } - protected override bool OnExiting(Screen next) + public override void OnEntering(IScreen last) { - Content.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - TransitionContent.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - - return base.OnExiting(next); + this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); + this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); + this.MoveToX(200).MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); } - protected override void OnResuming(Screen last) + public override bool OnExiting(IScreen next) { - base.OnResuming(last); + this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + this.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - Content.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - TransitionContent.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + return false; } - protected override void OnSuspending(Screen next) + public override void OnResuming(IScreen last) { - base.OnSuspending(next); - - Content.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - TransitionContent.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + this.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); + this.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); } + + public override void OnSuspending(IScreen next) + { + this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + this.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + } + + public override bool OnPressed(GlobalAction action) + { + if (!this.IsCurrentScreen()) return false; + + if (action == GlobalAction.Back) + { + this.Exit(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => action == GlobalAction.Back; + + public override string ToString() => Title; } } diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 84d0ca3621..d5b8f1f0c8 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -1,14 +1,20 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Threading; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking; using osu.Game.Screens.Play; @@ -18,16 +24,25 @@ namespace osu.Game.Screens.Multi.Play { public class TimeshiftPlayer : Player { - private readonly Room room; - private readonly int playlistItemId; + public Action Exited; + + [Resolved(typeof(Room), nameof(Room.RoomID))] + private Bindable roomId { get; set; } + + private readonly PlaylistItem playlistItem; [Resolved] - private APIAccess api { get; set; } + private IAPIProvider api { get; set; } - public TimeshiftPlayer(Room room, int playlistItemId) + [Resolved] + private IBindable ruleset { get; set; } + + [Resolved] + private Bindable> selectedMods { get; set; } + + public TimeshiftPlayer(PlaylistItem playlistItem) { - this.room = room; - this.playlistItemId = playlistItemId; + this.playlistItem = playlistItem; } private int? token; @@ -39,7 +54,17 @@ namespace osu.Game.Screens.Multi.Play bool failed = false; - var req = new CreateRoomScoreRequest(room.RoomID.Value ?? 0, playlistItemId); + // Sanity checks to ensure that TimeshiftPlayer matches the settings for the current PlaylistItem + if (Beatmap.Value.BeatmapInfo.OnlineBeatmapID != playlistItem.Beatmap.OnlineBeatmapID) + throw new InvalidOperationException("Current Beatmap does not match PlaylistItem's Beatmap"); + + if (ruleset.Value.ID != playlistItem.Ruleset.ID) + throw new InvalidOperationException("Current Ruleset does not match PlaylistItem's Ruleset"); + + if (!playlistItem.RequiredMods.All(m => selectedMods.Value.Contains(m))) + throw new InvalidOperationException("Current Mods do not match PlaylistItem's RequiredMods"); + + var req = new CreateRoomScoreRequest(roomId.Value ?? 0, playlistItem.ID); req.Success += r => token = r.ID; req.Failure += e => { @@ -50,7 +75,7 @@ namespace osu.Game.Screens.Multi.Play Schedule(() => { ValidForResume = false; - Exit(); + this.Exit(); }); }; @@ -60,6 +85,16 @@ namespace osu.Game.Screens.Multi.Play Thread.Sleep(1000); } + public override bool OnExiting(IScreen next) + { + if (base.OnExiting(next)) + return true; + + Exited?.Invoke(); + + return false; + } + protected override ScoreInfo CreateScore() { submitScore(); @@ -74,11 +109,18 @@ namespace osu.Game.Screens.Multi.Play Debug.Assert(token != null); - var request = new SubmitRoomScoreRequest(token.Value, room.RoomID.Value ?? 0, playlistItemId, score); + var request = new SubmitRoomScoreRequest(token.Value, roomId.Value ?? 0, playlistItem.ID, score); request.Failure += e => Logger.Error(e, "Failed to submit score"); api.Queue(request); } - protected override Results CreateResults(ScoreInfo score) => new MatchResults(score, room); + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + Exited = null; + } + + protected override Results CreateResults(ScoreInfo score) => new MatchResults(score); } } diff --git a/osu.Game/Screens/Multi/Ranking/MatchResults.cs b/osu.Game/Screens/Multi/Ranking/MatchResults.cs index 018eb60564..fe68d7e849 100644 --- a/osu.Game/Screens/Multi/Ranking/MatchResults.cs +++ b/osu.Game/Screens/Multi/Ranking/MatchResults.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking.Types; using osu.Game.Screens.Ranking; @@ -12,19 +11,16 @@ namespace osu.Game.Screens.Multi.Ranking { public class MatchResults : Results { - private readonly Room room; - - public MatchResults(ScoreInfo score, Room room) + public MatchResults(ScoreInfo score) : base(score) { - this.room = room; } protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { - new ScoreOverviewPageInfo(Score, Beatmap), - new LocalLeaderboardPageInfo(Score, Beatmap), - new RoomLeaderboardPageInfo(Score, Beatmap, room), + new ScoreOverviewPageInfo(Score, Beatmap.Value), + new LocalLeaderboardPageInfo(Score, Beatmap.Value), + new RoomLeaderboardPageInfo(Score, Beatmap.Value), }; } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index 54528e5503..d20b021fc6 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -1,10 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -23,16 +24,15 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { public class RoomLeaderboardPage : ResultsPage { - private readonly Room room; - private OsuColour colours; - private TextFlowContainer rankText; - public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap, Room room) + [Resolved(typeof(Room), nameof(Room.Name))] + private Bindable name { get; set; } + + public RoomLeaderboardPage(ScoreInfo score, WorkingBeatmap beatmap) : base(score, beatmap) { - this.room = room; } [BackgroundDependencyLoader] @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages { RelativeSizeAxes = Axes.Both, BackgroundColour = colours.Gray6, - Child = leaderboard = CreateLeaderboard(room) + Child = leaderboard = CreateLeaderboard() }, rankText = new TextFlowContainer { @@ -80,33 +80,28 @@ namespace osu.Game.Screens.Multi.Ranking.Pages Action gray = s => s.Colour = colours.GrayC; Action white = s => { - s.TextSize *= 1.4f; + s.Font = s.Font.With(size: s.Font.Size * 1.4f); s.Colour = colours.GrayF; }; - rankText.AddText(room.Name + "\n", white); + rankText.AddText(name + "\n", white); rankText.AddText("You are placed ", gray); int index = scores.IndexOf(new APIRoomScoreInfo { User = Score.User }, new FuncEqualityComparer((s1, s2) => s1.User.Id.Equals(s2.User.Id))); rankText.AddText($"#{index + 1} ", s => { - s.Font = "Exo2.0-Bold"; + s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold); s.Colour = colours.YellowDark; }); rankText.AddText("in the room!", gray); } - protected virtual MatchLeaderboard CreateLeaderboard(Room room) => new ResultsMatchLeaderboard(room); + protected virtual MatchLeaderboard CreateLeaderboard() => new ResultsMatchLeaderboard(); public class ResultsMatchLeaderboard : MatchLeaderboard { - public ResultsMatchLeaderboard(Room room) - : base(room) - { - } - protected override bool FadeTop => true; protected override LeaderboardScore CreateDrawableScore(APIRoomScoreInfo model, int index) diff --git a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs index bc78210484..6cc13f88a5 100644 --- a/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Multi/Ranking/Types/RoomLeaderboardPageInfo.cs @@ -1,9 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Multi.Ranking.Pages; using osu.Game.Screens.Ranking; @@ -14,19 +13,17 @@ namespace osu.Game.Screens.Multi.Ranking.Types { private readonly ScoreInfo score; private readonly WorkingBeatmap beatmap; - private readonly Room room; - public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap, Room room) + public RoomLeaderboardPageInfo(ScoreInfo score, WorkingBeatmap beatmap) { this.score = score; this.beatmap = beatmap; - this.room = room; } public FontAwesome Icon => FontAwesome.fa_users; public string Name => "Room Leaderboard"; - public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap, room); + public virtual ResultsPage CreatePage() => new RoomLeaderboardPage(score, beatmap); } } diff --git a/osu.Game/Screens/Multi/RoomBindings.cs b/osu.Game/Screens/Multi/RoomBindings.cs deleted file mode 100644 index cdbb6dbea6..0000000000 --- a/osu.Game/Screens/Multi/RoomBindings.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Framework.Configuration; -using osu.Game.Beatmaps; -using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Users; - -namespace osu.Game.Screens.Multi -{ - /// - /// Helper class which binds to values from a . - /// - public class RoomBindings - { - public RoomBindings() - { - Playlist.ItemsAdded += _ => updatePlaylist(); - Playlist.ItemsRemoved += _ => updatePlaylist(); - } - - private Room room; - - /// - /// The to bind to. - /// - public Room Room - { - get => room; - set - { - if (room == value) - return; - - if (room != null) - { - Name.UnbindFrom(room.Name); - Host.UnbindFrom(room.Host); - Status.UnbindFrom(room.Status); - Type.UnbindFrom(room.Type); - Playlist.UnbindFrom(room.Playlist); - Participants.UnbindFrom(room.Participants); - ParticipantCount.UnbindFrom(room.ParticipantCount); - MaxParticipants.UnbindFrom(room.MaxParticipants); - EndDate.UnbindFrom(room.EndDate); - Availability.UnbindFrom(room.Availability); - Duration.UnbindFrom(room.Duration); - } - - room = value; - - if (room != null) - { - Name.BindTo(room.Name); - Host.BindTo(room.Host); - Status.BindTo(room.Status); - Type.BindTo(room.Type); - Playlist.BindTo(room.Playlist); - Participants.BindTo(room.Participants); - ParticipantCount.BindTo(room.ParticipantCount); - MaxParticipants.BindTo(room.MaxParticipants); - EndDate.BindTo(room.EndDate); - Availability.BindTo(room.Availability); - Duration.BindTo(room.Duration); - } - } - } - - private void updatePlaylist() - { - // Todo: We only ever have one playlist item for now. In the future, this will be user-settable - - var playlistItem = Playlist.FirstOrDefault(); - - currentBeatmap.Value = playlistItem?.Beatmap; - currentMods.Value = playlistItem?.RequiredMods ?? Enumerable.Empty(); - currentRuleset.Value = playlistItem?.Ruleset; - } - - public readonly Bindable Name = new Bindable(); - public readonly Bindable Host = new Bindable(); - public readonly Bindable Status = new Bindable(); - public readonly Bindable Type = new Bindable(); - public readonly BindableList Playlist = new BindableList(); - public readonly Bindable> Participants = new Bindable>(); - public readonly Bindable ParticipantCount = new Bindable(); - public readonly Bindable MaxParticipants = new Bindable(); - public readonly Bindable EndDate = new Bindable(); - public readonly Bindable Availability = new Bindable(); - public readonly Bindable Duration = new Bindable(); - - private readonly Bindable currentBeatmap = new Bindable(); - public IBindable CurrentBeatmap => currentBeatmap; - - private readonly Bindable> currentMods = new Bindable>(); - public IBindable> CurrentMods => currentMods; - - private readonly Bindable currentRuleset = new Bindable(); - public IBindable CurrentRuleset => currentRuleset; - } -} diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 1f95401905..385cbe20e5 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online; @@ -24,12 +24,13 @@ namespace osu.Game.Screens.Multi private readonly BindableList rooms = new BindableList(); public IBindableList Rooms => rooms; - private Room currentRoom; - - private FilterCriteria currentFilter = new FilterCriteria(); + private Room joinedRoom; [Resolved] - private APIAccess api { get; set; } + private Bindable currentFilter { get; set; } + + [Resolved] + private IAPIProvider api { get; set; } [Resolved] private RulesetStore rulesets { get; set; } @@ -37,6 +38,16 @@ namespace osu.Game.Screens.Multi [Resolved] private BeatmapManager beatmaps { get; set; } + [BackgroundDependencyLoader] + private void load() + { + currentFilter.BindValueChanged(_ => + { + if (IsLoaded) + PollImmediately(); + }); + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -45,17 +56,18 @@ namespace osu.Game.Screens.Multi public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { - room.Host.Value = api.LocalUser; + room.Host.Value = api.LocalUser.Value; var req = new CreateRoomRequest(room); req.Success += result => { + joinedRoom = room; + update(room, result); addRoom(room); RoomsUpdated?.Invoke(); - onSuccess?.Invoke(room); }; @@ -80,7 +92,7 @@ namespace osu.Game.Screens.Multi currentJoinRoomRequest = new JoinRoomRequest(room, api.LocalUser.Value); currentJoinRoomRequest.Success += () => { - currentRoom = room; + joinedRoom = room; onSuccess?.Invoke(room); }; @@ -95,17 +107,11 @@ namespace osu.Game.Screens.Multi public void PartRoom() { - if (currentRoom == null) + if (joinedRoom == null) return; - api.Queue(new PartRoomRequest(currentRoom, api.LocalUser.Value)); - currentRoom = null; - } - - public void Filter(FilterCriteria criteria) - { - currentFilter = criteria; - PollImmediately(); + api.Queue(new PartRoomRequest(joinedRoom, api.LocalUser.Value)); + joinedRoom = null; } private GetRoomsRequest pollReq; @@ -118,7 +124,7 @@ namespace osu.Game.Screens.Multi var tcs = new TaskCompletionSource(); pollReq?.Cancel(); - pollReq = new GetRoomsRequest(currentFilter.PrimaryFilter); + pollReq = new GetRoomsRequest(currentFilter.Value.PrimaryFilter); pollReq.Success += result => { @@ -132,14 +138,13 @@ namespace osu.Game.Screens.Multi for (int i = 0; i < result.Count; i++) { var r = result[i]; - r.Position = i; + r.Position.Value = i; update(r, r); addRoom(r); } RoomsUpdated?.Invoke(); - tcs.SetResult(true); }; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 69f2b6ef9d..5034385969 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -1,29 +1,29 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Graphics.Containers; using osu.Game.Input.Bindings; using osu.Game.Rulesets; using osu.Game.Screens.Menu; -using osuTK; using osu.Game.Overlays; -using osu.Framework.Graphics.Containers; namespace osu.Game.Screens { - public abstract class OsuScreen : Screen, IKeyBindingHandler, IHasDescription + public abstract class OsuScreen : Screen, IOsuScreen, IKeyBindingHandler, IHasDescription { - public BackgroundScreen Background { get; private set; } + /// + /// The amount of negative padding that should be applied to game background content which touches both the left and right sides of the screen. + /// This allows for the game content to be pushed byt he options/notification overlays without causing black areas to appear. + /// + public const float HORIZONTAL_OVERFLOW_PADDING = 50; /// /// A user-facing title for this screen. @@ -36,80 +36,72 @@ namespace osu.Game.Screens public virtual bool AllowExternalScreenChange => false; - /// - /// Override to create a BackgroundMode for the current screen. - /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause. - /// - protected virtual BackgroundScreen CreateBackground() => null; - - private Action updateOverlayStates; - /// /// Whether all overlays should be hidden when this screen is entered or resumed. /// - protected virtual bool HideOverlaysOnEnter => false; - - protected readonly Bindable OverlayActivationMode = new Bindable(); + public virtual bool HideOverlaysOnEnter => false; /// /// Whether overlays should be able to be opened once this screen is entered or resumed. /// - protected virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; + public virtual OverlayActivation InitialOverlayActivationMode => OverlayActivation.All; - /// - /// Whether this allows the cursor to be displayed. - /// public virtual bool CursorVisible => true; protected new OsuGameBase Game => base.Game as OsuGameBase; - private OsuLogo logo; - /// - /// Whether the beatmap or ruleset should be allowed to be changed by the user or game. - /// Used to mark exclusive areas where this is strongly prohibited, like gameplay. + /// Whether to disallow changes to game-wise Beatmap/Ruleset bindables for this screen (and all children). /// - public virtual bool AllowBeatmapRulesetChange => true; - - protected readonly Bindable Beatmap = new Bindable(); - - protected virtual float BackgroundParallaxAmount => 1; - - private ParallaxContainer backgroundParallaxContainer; - - protected readonly Bindable Ruleset = new Bindable(); + public virtual bool DisallowExternalBeatmapRulesetChanges => false; private SampleChannel sampleExit; - [BackgroundDependencyLoader(true)] - private void load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable ruleset) + public virtual float BackgroundParallaxAmount => 1; + + public Bindable Beatmap { get; set; } + + public Bindable Ruleset { get; set; } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - Beatmap.BindTo(beatmap); - Ruleset.BindTo(ruleset); + var deps = new OsuScreenDependencies(DisallowExternalBeatmapRulesetChanges, base.CreateChildDependencies(parent)); - if (osu != null) - { - OverlayActivationMode.BindTo(osu.OverlayActivationMode); + Beatmap = deps.Beatmap; + Ruleset = deps.Ruleset; - updateOverlayStates = () => - { - if (HideOverlaysOnEnter) - osu.CloseAllOverlays(); - else - osu.Toolbar.State = Visibility.Visible; - }; - } + return deps; + } + protected BackgroundScreen Background => backgroundStack?.CurrentScreen as BackgroundScreen; + + private BackgroundScreen localBackground; + + [Resolved(canBeNull: true)] + private BackgroundScreenStack backgroundStack { get; set; } + + [Resolved(canBeNull: true)] + private OsuLogo logo { get; set; } + + protected OsuScreen() + { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader(true)] + private void load(OsuGame osu, AudioManager audio) + { sampleExit = audio.Sample.Get(@"UI/screen-back"); } public virtual bool OnPressed(GlobalAction action) { - if (!IsCurrentScreen) return false; + if (!this.IsCurrentScreen()) return false; if (action == GlobalAction.Back && AllowBackButton) { - Exit(); + this.Exit(); return true; } @@ -118,7 +110,7 @@ namespace osu.Game.Screens public bool OnReleased(GlobalAction action) => action == GlobalAction.Back && AllowBackButton; - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { sampleExit?.Play(); applyArrivingDefaults(true); @@ -126,72 +118,32 @@ namespace osu.Game.Screens base.OnResuming(last); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); onSuspendingLogo(); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { - OsuScreen lastOsu = last as OsuScreen; - - BackgroundScreen bg = CreateBackground(); - - if (lastOsu?.Background != null) - { - backgroundParallaxContainer = lastOsu.backgroundParallaxContainer; - - if (bg == null || lastOsu.Background.Equals(bg)) - //we can keep the previous mode's background. - Background = lastOsu.Background; - else - { - lastOsu.Background.Push(Background = bg); - } - } - else if (bg != null) - { - // this makes up for the fact our padding changes when the global toolbar is visible. - bg.Scale = new Vector2(1.06f); - - AddInternal(backgroundParallaxContainer = new ParallaxContainer - { - Depth = float.MaxValue, - Children = new[] - { - Background = bg - } - }); - } - - if ((logo = lastOsu?.logo) == null) - LoadComponentAsync(logo = new OsuLogo { Alpha = 0 }, AddInternal); - applyArrivingDefaults(false); + backgroundStack?.Push(localBackground = CreateBackground()); + base.OnEntering(last); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { if (ValidForResume && logo != null) onExitingLogo(); - OsuScreen nextOsu = next as OsuScreen; - - if (Background != null && !Background.Equals(nextOsu?.Background)) - { - Background.Exit(); - - //We need to use MakeCurrent in case we are jumping up multiple game screens. - nextOsu?.Background?.MakeCurrent(); - } - if (base.OnExiting(next)) return true; - Beatmap.UnbindAll(); + if (localBackground != null && backgroundStack?.CurrentScreen == localBackground) + backgroundStack?.Exit(); + return false; } @@ -199,35 +151,38 @@ namespace osu.Game.Screens /// Fired when this screen was entered or resumed and the logo state is required to be adjusted. /// protected virtual void LogoArriving(OsuLogo logo, bool resuming) + { + ApplyLogoArrivingDefaults(logo); + } + + private void applyArrivingDefaults(bool isResuming) + { + logo?.AppendAnimatingAction(() => + { + if (this.IsCurrentScreen()) LogoArriving(logo, isResuming); + }, true); + } + + /// + /// Applies default animations to an arriving logo. + /// Todo: This should not exist. + /// + /// The logo to apply animations to. + public static void ApplyLogoArrivingDefaults(OsuLogo logo) { logo.Action = null; logo.FadeOut(300, Easing.OutQuint); logo.Anchor = Anchor.TopLeft; logo.Origin = Anchor.Centre; - logo.RelativePositionAxes = Axes.None; + logo.RelativePositionAxes = Axes.Both; logo.BeatMatching = true; logo.Triangles = true; logo.Ripple = true; } - private void applyArrivingDefaults(bool isResuming) - { - logo.AppendAnimatingAction(() => - { - if (IsCurrentScreen) LogoArriving(logo, isResuming); - }, true); - - if (backgroundParallaxContainer != null) - backgroundParallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * BackgroundParallaxAmount; - - OverlayActivationMode.Value = InitialOverlayActivationMode; - - updateOverlayStates?.Invoke(); - } - private void onExitingLogo() { - logo.AppendAnimatingAction(() => { LogoExiting(logo); }, false); + logo?.AppendAnimatingAction(() => LogoExiting(logo), false); } /// @@ -239,7 +194,7 @@ namespace osu.Game.Screens private void onSuspendingLogo() { - logo.AppendAnimatingAction(() => { LogoSuspending(logo); }, false); + logo?.AppendAnimatingAction(() => LogoSuspending(logo), false); } /// @@ -248,5 +203,11 @@ namespace osu.Game.Screens protected virtual void LogoSuspending(OsuLogo logo) { } + + /// + /// Override to create a BackgroundMode for the current screen. + /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause. + /// + protected virtual BackgroundScreen CreateBackground() => null; } } diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs new file mode 100644 index 0000000000..84e5de76de --- /dev/null +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; + +namespace osu.Game.Screens +{ + public class OsuScreenDependencies : DependencyContainer + { + public Bindable Beatmap { get; } + + public Bindable Ruleset { get; } + + public OsuScreenDependencies(bool requireLease, IReadOnlyDependencyContainer parent) + : base(parent) + { + if (requireLease) + { + Beatmap = parent.Get>()?.GetBoundCopy(); + if (Beatmap == null) + { + Cache(Beatmap = parent.Get>().BeginLease(false)); + } + + Ruleset = parent.Get>()?.GetBoundCopy(); + if (Ruleset == null) + { + Cache(Ruleset = parent.Get>().BeginLease(true)); + } + } + else + { + Beatmap = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); + Ruleset = (parent.Get>() ?? parent.Get>()).GetBoundCopy(); + } + } + } +} diff --git a/osu.Game/Screens/OsuScreenStack.cs b/osu.Game/Screens/OsuScreenStack.cs new file mode 100644 index 0000000000..0844e32d46 --- /dev/null +++ b/osu.Game/Screens/OsuScreenStack.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens +{ + public class OsuScreenStack : ScreenStack + { + [Cached] + private BackgroundScreenStack backgroundScreenStack; + + private ParallaxContainer parallaxContainer; + + protected float ParallaxAmount => parallaxContainer.ParallaxAmount; + + public OsuScreenStack() + { + initializeStack(); + } + + public OsuScreenStack(IScreen baseScreen) + : base(baseScreen) + { + initializeStack(); + } + + private void initializeStack() + { + InternalChild = parallaxContainer = new ParallaxContainer + { + RelativeSizeAxes = Axes.Both, + Child = backgroundScreenStack = new BackgroundScreenStack { RelativeSizeAxes = Axes.Both }, + }; + + ScreenPushed += onScreenChange; + ScreenExited += onScreenChange; + } + + private void onScreenChange(IScreen prev, IScreen next) + { + parallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * ((IOsuScreen)next)?.BackgroundParallaxAmount ?? 1.0f; + } + } +} diff --git a/osu.Game/Screens/Play/Break/BlurredIcon.cs b/osu.Game/Screens/Play/Break/BlurredIcon.cs index 6d14c94f13..53b968959c 100644 --- a/osu.Game/Screens/Play/Break/BlurredIcon.cs +++ b/osu.Game/Screens/Play/Break/BlurredIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -15,8 +15,8 @@ namespace osu.Game.Screens.Play.Break public FontAwesome Icon { - set { icon.Icon = value; } - get { return icon.Icon; } + set => icon.Icon = value; + get => icon.Icon; } public override Vector2 Size @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play.Break base.Size = value + BlurSigma * 2.5f; ForceRedraw(); } - get { return base.Size; } + get => base.Size; } public BlurredIcon() diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index d5b710a29e..9d9f0ab898 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index 22e19ac8e2..a3d64d05a3 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; using osuTK; @@ -29,8 +30,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "current progress".ToUpperInvariant(), - TextSize = 15, - Font = "Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black, size: 15), }, new FillFlowContainer { diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 49b4cb3206..4b07405812 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreRight, Text = name, - TextSize = 17, + Font = OsuFont.GetFont(size: 17), Margin = new MarginPadding { Right = margin } }, valueText = new OsuSpriteText @@ -42,8 +42,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, Text = prefix + @"-", - TextSize = 17, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = margin } } }; @@ -51,9 +50,9 @@ namespace osu.Game.Screens.Play.Break Current.ValueChanged += currentValueChanged; } - private void currentValueChanged(T newValue) + private void currentValueChanged(ValueChangedEvent e) { - var newText = prefix + Format(newValue); + var newText = prefix + Format(e.NewValue); if (valueText.Text == newText) return; @@ -73,7 +72,8 @@ namespace osu.Game.Screens.Play.Break public class PercentageBreakInfoLine : BreakInfoLine { - public PercentageBreakInfoLine(string name, string prefix = "") : base(name, prefix) + public PercentageBreakInfoLine(string name, string prefix = "") + : base(name, prefix) { } diff --git a/osu.Game/Screens/Play/Break/GlowIcon.cs b/osu.Game/Screens/Play/Break/GlowIcon.cs index d412f3e103..8d918cd225 100644 --- a/osu.Game/Screens/Play/Break/GlowIcon.cs +++ b/osu.Game/Screens/Play/Break/GlowIcon.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Play.Break public override Vector2 Size { - get { return base.Size; } + get => base.Size; set { blurredIcon.Size = spriteIcon.Size = value; @@ -26,14 +26,14 @@ namespace osu.Game.Screens.Play.Break public Vector2 BlurSigma { - get { return blurredIcon.BlurSigma; } - set { blurredIcon.BlurSigma = value; } + get => blurredIcon.BlurSigma; + set => blurredIcon.BlurSigma = value; } public FontAwesome Icon { - get { return spriteIcon.Icon; } - set { spriteIcon.Icon = blurredIcon.Icon = value; } + get => spriteIcon.Icon; + set => spriteIcon.Icon = blurredIcon.Icon = value; } public GlowIcon() diff --git a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs index 8bfa0e632a..2d7163b5fe 100644 --- a/osu.Game/Screens/Play/Break/LetterboxOverlay.cs +++ b/osu.Game/Screens/Play/Break/LetterboxOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; diff --git a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs index 914809ea40..2f5e43aebf 100644 --- a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.Break @@ -19,8 +20,7 @@ namespace osu.Game.Screens.Play.Break { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 33, - Font = "Venera", + Font = OsuFont.Numeric.With(size: 33), }; } diff --git a/osu.Game/Screens/Play/BreakOverlay.cs b/osu.Game/Screens/Play/BreakOverlay.cs index b2df996d35..d390787090 100644 --- a/osu.Game/Screens/Play/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreakOverlay.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -40,13 +41,7 @@ namespace osu.Game.Screens.Play private readonly BreakInfo info; private readonly BreakArrows breakArrows; - public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor) - : this(letterboxing) - { - bindProcessor(scoreProcessor); - } - - public BreakOverlay(bool letterboxing) + public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor = null) { RelativeSizeAxes = Axes.Both; Child = fadeContainer = new Container @@ -98,6 +93,14 @@ namespace osu.Game.Screens.Play } } }; + + if (scoreProcessor != null) bindProcessor(scoreProcessor); + } + + [BackgroundDependencyLoader(true)] + private void load(GameplayClock clock) + { + if (clock != null) Clock = clock; } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 947fa1734a..b67f45c4f2 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; using osuTK.Graphics; diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs new file mode 100644 index 0000000000..0400bfbc27 --- /dev/null +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Timing; + +namespace osu.Game.Screens.Play +{ + /// + /// A clock which is used for gameplay elements that need to follow audio time 1:1. + /// Exposed via DI by . + /// + /// The main purpose of this clock is to stop components using it from accidentally processing the main + /// , as this should only be done once to ensure accuracy. + /// + /// + public class GameplayClock : IFrameBasedClock + { + private readonly IFrameBasedClock underlyingClock; + + public GameplayClock(IFrameBasedClock underlyingClock) + { + this.underlyingClock = underlyingClock; + } + + public double CurrentTime => underlyingClock.CurrentTime; + + public double Rate => underlyingClock.Rate; + + public bool IsRunning => underlyingClock.IsRunning; + + public void ProcessFrame() + { + // we do not want to process the underlying clock. + // this is handled by PauseContainer. + } + + public double ElapsedFrameTime => underlyingClock.ElapsedFrameTime; + + public double FramesPerSecond => underlyingClock.FramesPerSecond; + + public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo; + } +} diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs new file mode 100644 index 0000000000..deac5e02bf --- /dev/null +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -0,0 +1,161 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Screens.Play +{ + /// + /// Encapsulates gameplay timing logic and provides a for children. + /// + public class GameplayClockContainer : Container + { + private readonly WorkingBeatmap beatmap; + + /// + /// The original source (usually a 's track). + /// + private readonly IAdjustableClock sourceClock; + + public readonly BindableBool IsPaused = new BindableBool(); + + /// + /// The decoupled clock used for gameplay. Should be used for seeks and clock control. + /// + private readonly DecoupleableInterpolatingFramedClock adjustableClock; + + public readonly Bindable UserPlaybackRate = new BindableDouble(1) + { + Default = 1, + MinValue = 0.5, + MaxValue = 2, + Precision = 0.1, + }; + + /// + /// The final clock which is exposed to underlying components. + /// + [Cached] + public readonly GameplayClock GameplayClock; + + private Bindable userAudioOffset; + + private readonly FramedOffsetClock offsetClock; + + public GameplayClockContainer(WorkingBeatmap beatmap, bool allowLeadIn, double gameplayStartTime) + { + this.beatmap = beatmap; + + RelativeSizeAxes = Axes.Both; + + sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); + + adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; + + adjustableClock.Seek(allowLeadIn + ? Math.Min(0, gameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn) + : gameplayStartTime); + + adjustableClock.ProcessFrame(); + + // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. + // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck. + var platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; + + // the final usable gameplay clock with user-set offsets applied. + offsetClock = new FramedOffsetClock(platformOffsetClock); + + // the clock to be exposed via DI to children. + GameplayClock = new GameplayClock(offsetClock); + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); + userAudioOffset.BindValueChanged(offset => offsetClock.Offset = offset.NewValue, true); + + UserPlaybackRate.ValueChanged += _ => updateRate(); + } + + public void Restart() + { + Task.Run(() => + { + sourceClock.Reset(); + + Schedule(() => + { + adjustableClock.ChangeSource(sourceClock); + updateRate(); + + this.Delay(750).Schedule(() => + { + if (!IsPaused.Value) + { + adjustableClock.Start(); + } + }); + }); + }); + } + + public void Start() + { + // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time + // This accounts for the audio clock source potentially taking time to enter a completely stopped state + adjustableClock.Seek(adjustableClock.CurrentTime); + adjustableClock.Start(); + IsPaused.Value = false; + } + + public void Seek(double time) => adjustableClock.Seek(time); + + public void Stop() + { + adjustableClock.Stop(); + IsPaused.Value = true; + } + + public void ResetLocalAdjustments() + { + // In the case of replays, we may have changed the playback rate. + UserPlaybackRate.Value = 1; + } + + protected override void Update() + { + if (!IsPaused.Value) + offsetClock.ProcessFrame(); + + base.Update(); + } + + private void updateRate() + { + if (sourceClock == null) return; + + sourceClock.ResetSpeedAdjustments(); + + if (sourceClock is IHasTempoAdjust tempo) + tempo.TempoAdjust = UserPlaybackRate.Value; + else + sourceClock.Rate = UserPlaybackRate.Value; + + foreach (var mod in beatmap.Mods.Value.OfType()) + mod.ApplyToClock(sourceClock); + } + } +} diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index d934759474..2fac8de799 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; @@ -18,6 +18,7 @@ using System.Linq; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Input.Bindings; +using Humanizer; namespace osu.Game.Screens.Play { @@ -37,9 +38,15 @@ namespace osu.Game.Screens.Play /// /// Action that is invoked when is triggered. /// - protected virtual Action BackAction => () => InternalButtons.Children.Last().Click(); + protected virtual Action BackAction => () => InternalButtons.Children.LastOrDefault()?.Click(); + + /// + /// Action that is invoked when is triggered. + /// + protected virtual Action SelectAction => () => InternalButtons.Children.FirstOrDefault(f => f.Selected.Value)?.Click(); public abstract string Header { get; } + public abstract string Description { get; } protected internal FillFlowContainer InternalButtons; @@ -88,11 +95,10 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = Header, - Font = @"Exo2.0-Medium", + Font = OsuFont.GetFont(size: 30), Spacing = new Vector2(5, 0), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - TextSize = 30, Colour = colours.Yellow, Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f) @@ -176,7 +182,7 @@ namespace osu.Game.Screens.Play } }; - button.Selected.ValueChanged += s => buttonSelectionChanged(button, s); + button.Selected.ValueChanged += selected => buttonSelectionChanged(button, selected.NewValue); InternalButtons.Add(button); } @@ -185,7 +191,7 @@ namespace osu.Game.Screens.Play private int selectionIndex { - get { return _selectionIndex; } + get => _selectionIndex; set { if (_selectionIndex == value) @@ -229,16 +235,30 @@ namespace osu.Game.Screens.Play public bool OnPressed(GlobalAction action) { - if (action == GlobalAction.Back) + switch (action) { - BackAction.Invoke(); - return true; + case GlobalAction.Back: + BackAction.Invoke(); + return true; + case GlobalAction.Select: + SelectAction.Invoke(); + return true; } return false; } - public bool OnReleased(GlobalAction action) => action == GlobalAction.Back; + public bool OnReleased(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + case GlobalAction.Select: + return true; + } + + return false; + } private void buttonSelectionChanged(DialogButton button, bool isSelected) { @@ -260,22 +280,21 @@ namespace osu.Game.Screens.Play Text = "You've retried ", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 + Font = OsuFont.GetFont(size: 18), }, new OsuSpriteText { - Text = $"{retries:n0}", - Font = @"Exo2.0-Bold", + Text = "time".ToQuantity(retries), + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 }, new OsuSpriteText { - Text = $" time{(retries == 1 ? "" : "s")} in this session", + Text = " in this session", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 + Font = OsuFont.GetFont(size: 18), } }; } @@ -289,15 +308,6 @@ namespace osu.Game.Screens.Play Selected.Value = true; return base.OnMouseMove(e); } - - protected override bool OnKeyDown(KeyDownEvent e) - { - if (e.Repeat || e.Key != Key.Enter || !Selected) - return false; - - Click(); - return true; - } } } } diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index a6a33702ba..5ac3dac5f7 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -63,14 +63,14 @@ namespace osu.Game.Screens.Play.HUD TextSize = 80; - Current.ValueChanged += newValue => updateCount(newValue == 0); + Current.ValueChanged += combo => updateCount(combo.NewValue == 0); } protected override void LoadComplete() { base.LoadComplete(); - DisplayedCountSpriteText.Text = FormatCount(Current); + DisplayedCountSpriteText.Text = FormatCount(Current.Value); DisplayedCountSpriteText.Anchor = Anchor; DisplayedCountSpriteText.Origin = Origin; @@ -78,29 +78,33 @@ namespace osu.Game.Screens.Play.HUD } private int displayedCount; + /// /// Value shown at the current moment. /// public virtual int DisplayedCount { - get { return displayedCount; } + get => displayedCount; protected set { if (displayedCount.Equals(value)) return; + updateDisplayedCount(displayedCount, value, IsRolling); } } private float textSize; + public float TextSize { - get { return textSize; } + get => textSize; set { textSize = value; - DisplayedCountSpriteText.TextSize = TextSize; - PopOutCount.TextSize = TextSize; + + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(size: TextSize); + PopOutCount.Font = PopOutCount.Font.With(size: TextSize); } } @@ -110,7 +114,7 @@ namespace osu.Game.Screens.Play.HUD /// public void Increment(int amount = 1) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } /// @@ -161,7 +165,7 @@ namespace osu.Game.Screens.Play.HUD private void updateCount(bool rolling) { int prev = previousValue; - previousValue = Current; + previousValue = Current.Value; if (!IsLoaded) return; @@ -172,14 +176,14 @@ namespace osu.Game.Screens.Play.HUD IsRolling = false; DisplayedCount = prev; - if (prev + 1 == Current) - OnCountIncrement(prev, Current); + if (prev + 1 == Current.Value) + OnCountIncrement(prev, Current.Value); else - OnCountChange(prev, Current); + OnCountChange(prev, Current.Value); } else { - OnCountRolling(displayedCount, Current); + OnCountRolling(displayedCount, Current.Value); IsRolling = true; } } diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index cc24af0394..3f6b1e29e6 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD public override void Increment(long amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index fc651fc4b4..acd8656fb2 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; namespace osu.Game.Screens.Play.HUD @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Play.HUD protected HealthDisplay() { - Current.ValueChanged += newValue => SetHealth((float)newValue); + Current.ValueChanged += health => SetHealth((float)health.NewValue); } protected abstract void SetHealth(float value); diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index 9625c4338b..50bc34726a 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play.HUD text = new OsuSpriteText { Text = "hold for menu", - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, @@ -92,30 +92,6 @@ namespace osu.Game.Screens.Play.HUD public Action HoverGained; public Action HoverLost; - public bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - BeginConfirm(); - return true; - } - - return false; - } - - public bool OnReleased(GlobalAction action) - { - switch (action) - { - case GlobalAction.Back: - AbortConfirm(); - return true; - } - - return false; - } - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -163,7 +139,7 @@ namespace osu.Game.Screens.Play.HUD private void bind() { circularProgress.Current.BindTo(Progress); - Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.2f); + Progress.ValueChanged += progress => icon.Scale = new Vector2(1 + (float)progress.NewValue * 0.2f); } private bool pendingAnimation; @@ -178,7 +154,7 @@ namespace osu.Game.Screens.Play.HUD // avoid starting a new confirm call until we finish animating. pendingAnimation = true; - Progress.Value = 0; + AbortConfirm(); overlayCircle.ScaleTo(0, 100) .Then().FadeOut().ScaleTo(1).FadeIn(500) @@ -207,6 +183,31 @@ namespace osu.Game.Screens.Play.HUD base.OnHoverLost(e); } + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + if (!pendingAnimation) + BeginConfirm(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) + { + switch (action) + { + case GlobalAction.Back: + AbortConfirm(); + return true; + } + + return false; + } + protected override bool OnMouseDown(MouseDownEvent e) { if (!pendingAnimation && e.CurrentState.Mouse.Buttons.Count() == 1) diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 8e9b0a0a5c..2c1293833f 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -14,6 +14,7 @@ using osu.Game.Rulesets.UI; using osuTK; using osu.Game.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Game.Graphics; namespace osu.Game.Screens.Play.HUD { @@ -60,15 +61,14 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.BottomCentre, Origin = Anchor.TopCentre, Text = @"/ UNRANKED /", - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12) } }; Current.ValueChanged += mods => { iconsContainer.Clear(); - foreach (Mod mod in mods) + foreach (Mod mod in mods.NewValue) { iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) }); } diff --git a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index 2249e743e6..e99f6d836e 100644 --- a/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,8 +17,11 @@ namespace osu.Game.Screens.Play.HUD public bool ReplayLoaded; public readonly PlaybackSettings PlaybackSettings; + public readonly VisualSettings VisualSettings; + //public readonly CollectionSettings CollectionSettings; + //public readonly DiscussionSettings DiscussionSettings; public PlayerSettingsOverlay() @@ -50,7 +53,7 @@ namespace osu.Game.Screens.Play.HUD protected override void PopOut() => this.FadeOut(fade_duration); //We want to handle keyboard inputs all the time in order to trigger ToggleVisibility() when not visible - public override bool HandleNonPositionalInput => true; + public override bool PropagateNonPositionalInputSubTree => true; protected override bool OnKeyDown(KeyDownEvent e) { diff --git a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs index 3ca4476969..7301300b8d 100644 --- a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs index 9eedde5269..8f09c2b2bf 100644 --- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -44,18 +44,20 @@ namespace osu.Game.Screens.Play.HUD public Color4 AccentColour { - get { return fill.Colour; } - set { fill.Colour = value; } + get => fill.Colour; + set => fill.Colour = value; } private Color4 glowColour; + public Color4 GlowColour { - get { return glowColour; } + get => glowColour; set { if (glowColour == value) return; + glowColour = value; fill.EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 11cee98bdf..285e6eab23 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; @@ -24,8 +24,6 @@ namespace osu.Game.Screens.Play { private const int duration = 100; - private readonly Container content; - public readonly KeyCounterCollection KeyCounter; public readonly RollingCounter ComboCounter; public readonly ScoreCounter ScoreCounter; @@ -37,64 +35,78 @@ namespace osu.Game.Screens.Play public readonly PlayerSettingsOverlay PlayerSettingsOverlay; private Bindable showHud; + private readonly Container visibilityContainer; private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; - public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContainer, WorkingBeatmap working, IClock offsetClock, IAdjustableClock adjustableClock) + public Action RequestSeek; + + public HUDOverlay(ScoreProcessor scoreProcessor, DrawableRuleset drawableRuleset, WorkingBeatmap working) { RelativeSizeAxes = Axes.Both; - Add(content = new Container + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, // The hud may be hidden but certain elements may need to still be updated - Children = new Drawable[] + visibilityContainer = new Container { - ComboCounter = CreateComboCounter(), - ScoreCounter = CreateScoreCounter(), - AccuracyCounter = CreateAccuracyCounter(), - HealthDisplay = CreateHealthDisplay(), - Progress = CreateProgress(), - ModDisplay = CreateModsContainer(), - PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), - new FillFlowContainer + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new Container { - KeyCounter = CreateKeyCounter(adjustableClock as IFrameBasedClock), - HoldToQuit = CreateHoldForMenuButton(), - } + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Y = 30, + AutoSizeAxes = Axes.Both, + AutoSizeDuration = 200, + AutoSizeEasing = Easing.Out, + Children = new Drawable[] + { + AccuracyCounter = CreateAccuracyCounter(), + ScoreCounter = CreateScoreCounter(), + ComboCounter = CreateComboCounter(), + }, + }, + HealthDisplay = CreateHealthDisplay(), + Progress = CreateProgress(), + ModDisplay = CreateModsContainer(), + } + }, + PlayerSettingsOverlay = CreatePlayerSettingsOverlay(), + new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Position = -new Vector2(5, TwoLayerButton.SIZE_RETRACTED.Y), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + KeyCounter = CreateKeyCounter(), + HoldToQuit = CreateHoldForMenuButton(), } } - }); + }; BindProcessor(scoreProcessor); - BindRulesetContainer(rulesetContainer); + BindDrawableRuleset(drawableRuleset); - Progress.Objects = rulesetContainer.Objects; - Progress.AudioClock = offsetClock; - Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; - Progress.OnSeek = pos => adjustableClock.Seek(pos); + Progress.Objects = drawableRuleset.Objects; + Progress.AllowSeeking = drawableRuleset.HasReplayLoaded.Value; + Progress.RequestSeek = time => RequestSeek(time); ModDisplay.Current.BindTo(working.Mods); - - PlayerSettingsOverlay.PlaybackSettings.AdjustableClock = adjustableClock; } [BackgroundDependencyLoader(true)] private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) { showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += hudVisibility => content.FadeTo(hudVisibility ? 1 : 0, duration); + showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); showHud.TriggerChange(); - if (!showHud && !hasShownNotificationOnce) + if (!showHud.Value && !hasShownNotificationOnce) { hasShownNotificationOnce = true; @@ -113,11 +125,11 @@ namespace osu.Game.Screens.Play replayLoaded.TriggerChange(); } - private void replayLoadedValueChanged(bool loaded) + private void replayLoadedValueChanged(ValueChangedEvent e) { - PlayerSettingsOverlay.ReplayLoaded = loaded; + PlayerSettingsOverlay.ReplayLoaded = e.NewValue; - if (loaded) + if (e.NewValue) { PlayerSettingsOverlay.Show(); ModDisplay.FadeIn(200); @@ -131,13 +143,13 @@ namespace osu.Game.Screens.Play } } - protected virtual void BindRulesetContainer(RulesetContainer rulesetContainer) + protected virtual void BindDrawableRuleset(DrawableRuleset drawableRuleset) { - (rulesetContainer.KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(KeyCounter); + (drawableRuleset as ICanAttachKeyCounter)?.Attach(KeyCounter); - replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); + replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); - Progress.BindRulestContainer(rulesetContainer); + Progress.BindDrawableRuleset(drawableRuleset); } protected override bool OnKeyDown(KeyDownEvent e) @@ -159,20 +171,27 @@ namespace osu.Game.Screens.Play protected virtual RollingCounter CreateAccuracyCounter() => new PercentageCounter { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopRight, - Position = new Vector2(0, 35), TextSize = 20, - Margin = new MarginPadding { Right = 140 }, + BypassAutoSizeAxes = Axes.X, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Top = 5, Right = 20 }, + }; + + protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6) + { + TextSize = 40, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, }; protected virtual RollingCounter CreateComboCounter() => new SimpleComboCounter { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopLeft, - Position = new Vector2(0, 35), - Margin = new MarginPadding { Left = 140 }, TextSize = 20, + BypassAutoSizeAxes = Axes.X, + Anchor = Anchor.TopRight, + Origin = Anchor.TopLeft, + Margin = new MarginPadding { Top = 5, Left = 20 }, }; protected virtual HealthDisplay CreateHealthDisplay() => new StandardHealthDisplay @@ -182,21 +201,12 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20 } }; - protected virtual KeyCounterCollection CreateKeyCounter(IFrameBasedClock offsetClock) => new KeyCounterCollection + protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection { FadeTime = 50, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), - AudioClock = offsetClock - }; - - protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextSize = 40, - Position = new Vector2(0, 30), }; protected virtual SongProgress CreateProgress() => new SongProgress @@ -229,8 +239,7 @@ namespace osu.Game.Screens.Play ComboCounter?.Current.BindTo(processor.Combo); HealthDisplay?.Current.BindTo(processor.Health); - var shd = HealthDisplay as StandardHealthDisplay; - if (shd != null) + if (HealthDisplay is StandardHealthDisplay shd) processor.NewJudgement += shd.Flash; } } diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 926a96eb6c..f1b851f2d5 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index b494b84ee4..0626c40334 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; using osuTK.Graphics; @@ -26,9 +27,10 @@ namespace osu.Game.Screens.Play public bool IsCounting { get; set; } = true; private int countPresses; + public int CountPresses { - get { return countPresses; } + get => countPresses; private set { if (countPresses != value) @@ -40,9 +42,10 @@ namespace osu.Game.Screens.Play } private bool isLit; + public bool IsLit { - get { return isLit; } + get => isLit; protected set { if (isLit != value) @@ -68,9 +71,12 @@ namespace osu.Game.Screens.Play Name = name; } - [BackgroundDependencyLoader] - private void load(TextureStore textures) + [BackgroundDependencyLoader(true)] + private void load(TextureStore textures, GameplayClock clock) { + if (clock != null) + Clock = clock; + Children = new Drawable[] { buttonSprite = new Sprite @@ -96,8 +102,7 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = Name, - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 6fde0734f6..8deac653ad 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Bindings; @@ -10,7 +10,8 @@ namespace osu.Game.Screens.Play { public T Action { get; } - public KeyCounterAction(T action) : base($"B{(int)(object)action + 1}") + public KeyCounterAction(T action) + : base($"B{(int)(object)action + 1}") { Action = action; } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index ce0e98d032..1b43737731 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -1,14 +1,13 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Framework.Timing; using osu.Game.Configuration; using osuTK; using osuTK.Graphics; @@ -37,9 +36,6 @@ namespace osu.Game.Screens.Play key.FadeTime = FadeTime; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; - // Use the same clock object as SongProgress for saving KeyCounter state - if (AudioClock != null) - key.Clock = AudioClock; } public void ResetCount() @@ -58,9 +54,10 @@ namespace osu.Game.Screens.Play } private bool isCounting = true; + public bool IsCounting { - get { return isCounting; } + get => isCounting; set { if (value == isCounting) return; @@ -72,9 +69,10 @@ namespace osu.Game.Screens.Play } private int fadeTime; + public int FadeTime { - get { return fadeTime; } + get => fadeTime; set { if (value != fadeTime) @@ -87,9 +85,10 @@ namespace osu.Game.Screens.Play } private Color4 keyDownTextColor = Color4.DarkGray; + public Color4 KeyDownTextColor { - get { return keyDownTextColor; } + get => keyDownTextColor; set { if (value != keyDownTextColor) @@ -102,9 +101,10 @@ namespace osu.Game.Screens.Play } private Color4 keyUpTextColor = Color4.White; + public Color4 KeyUpTextColor { - get { return keyUpTextColor; } + get => keyUpTextColor; set { if (value != keyUpTextColor) @@ -121,8 +121,6 @@ namespace osu.Game.Screens.Play public override bool HandleNonPositionalInput => receptor == null; public override bool HandlePositionalInput => receptor == null; - public IFrameBasedClock AudioClock { get; set; } - private Receptor receptor; public Receptor GetReceptor() @@ -161,6 +159,7 @@ namespace osu.Game.Screens.Play case MouseUpEvent _: return Target.Children.Any(c => c.TriggerEvent(e)); } + return base.Handle(e); } } diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 521f7d4e84..d9b6dca79d 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Events; using osuTK.Input; @@ -9,7 +9,9 @@ namespace osu.Game.Screens.Play public class KeyCounterKeyboard : KeyCounter { public Key Key { get; } - public KeyCounterKeyboard(Key key) : base(key.ToString()) + + public KeyCounterKeyboard(Key key) + : base(key.ToString()) { Key = key; } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 3f7aaa6076..13dbe40a8b 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Events; using osuTK.Input; @@ -11,7 +11,8 @@ namespace osu.Game.Screens.Play { public MouseButton Button { get; } - public KeyCounterMouse(MouseButton button) : base(getStringRepresentation(button)) + public KeyCounterMouse(MouseButton button) + : base(getStringRepresentation(button)) { Button = button; } diff --git a/osu.Game/Screens/Play/KeyCounterState.cs b/osu.Game/Screens/Play/KeyCounterState.cs index e5c0703319..0bceae9f85 100644 --- a/osu.Game/Screens/Play/KeyCounterState.cs +++ b/osu.Game/Screens/Play/KeyCounterState.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Play { diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs deleted file mode 100644 index 19a05e8eed..0000000000 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; -using osu.Game.Graphics; -using osuTK.Graphics; - -namespace osu.Game.Screens.Play -{ - /// - /// A container which handles pausing children, displaying a pause overlay with choices etc. - /// This alleviates a lot of the intricate pause logic from being in - /// - public class PauseContainer : Container - { - public readonly BindableBool IsPaused = new BindableBool(); - - public Func CheckCanPause; - - private const double pause_cooldown = 1000; - private double lastPauseActionTime; - - private readonly PauseOverlay pauseOverlay; - - private readonly Container content; - - protected override Container Content => content; - - public int Retries { set { pauseOverlay.Retries = value; } } - - public bool CanPause => (CheckCanPause?.Invoke() ?? true) && Time.Current >= lastPauseActionTime + pause_cooldown; - public bool IsResuming { get; private set; } - - public Action OnRetry; - public Action OnQuit; - - private readonly FramedClock framedClock; - private readonly DecoupleableInterpolatingFramedClock decoupledClock; - - /// - /// Creates a new . - /// - /// The gameplay clock. This is the clock that will process frames. - /// The seekable clock. This is the clock that will be paused and resumed. - public PauseContainer(FramedClock framedClock, DecoupleableInterpolatingFramedClock decoupledClock) - { - this.framedClock = framedClock; - this.decoupledClock = decoupledClock; - - RelativeSizeAxes = Axes.Both; - - AddInternal(content = new Container - { - Clock = this.framedClock, - ProcessCustomClock = false, - RelativeSizeAxes = Axes.Both - }); - - AddInternal(pauseOverlay = new PauseOverlay - { - OnResume = () => - { - IsResuming = true; - this.Delay(400).Schedule(Resume); - }, - OnRetry = () => OnRetry(), - OnQuit = () => OnQuit(), - }); - } - - public void Pause(bool force = false) => Schedule(() => // Scheduled to ensure a stable position in execution order, no matter how it was called. - { - if (!CanPause && !force) return; - - if (IsPaused) return; - - // stop the seekable clock (stops the audio eventually) - decoupledClock.Stop(); - IsPaused.Value = true; - - pauseOverlay.Show(); - - lastPauseActionTime = Time.Current; - }); - - public void Resume() - { - if (!IsPaused) return; - - IsPaused.Value = false; - IsResuming = false; - lastPauseActionTime = Time.Current; - - // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time - // This accounts for the audio clock source potentially taking time to enter a completely stopped state - decoupledClock.Seek(decoupledClock.CurrentTime); - decoupledClock.Start(); - - pauseOverlay.Hide(); - } - - private OsuGameBase game; - - [BackgroundDependencyLoader] - private void load(OsuGameBase game) - { - this.game = game; - } - - protected override void Update() - { - // eagerly pause when we lose window focus (if we are locally playing). - if (!game.IsActive && CanPause) - Pause(); - - if (!IsPaused) - framedClock.ProcessFrame(); - - base.Update(); - } - - public class PauseOverlay : GameplayMenuOverlay - { - public Action OnResume; - - public override string Header => "paused"; - public override string Description => "you're not going to do what i think you're going to do, are ya?"; - - protected override Action BackAction => () => InternalButtons.Children.First().Click(); - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AddButton("Continue", colours.Green, () => OnResume?.Invoke()); - AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); - AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); - } - } - } -} diff --git a/osu.Game/Screens/Play/PauseOverlay.cs b/osu.Game/Screens/Play/PauseOverlay.cs new file mode 100644 index 0000000000..6cc6027a03 --- /dev/null +++ b/osu.Game/Screens/Play/PauseOverlay.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osuTK.Graphics; + +namespace osu.Game.Screens.Play +{ + public class PauseOverlay : GameplayMenuOverlay + { + public Action OnResume; + + public override string Header => "paused"; + public override string Description => "you're not going to do what i think you're going to do, are ya?"; + + protected override Action BackAction => () => InternalButtons.Children.First().Click(); + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddButton("Continue", colours.Green, () => OnResume?.Invoke()); + AddButton("Retry", colours.YellowDark, () => OnRetry?.Invoke()); + AddButton("Quit", new Color4(170, 27, 39, 255), () => OnQuit?.Invoke()); + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d5c99f5729..7b1cdd21a6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1,27 +1,21 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; -using System.Threading.Tasks; -using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Threading; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Cursor; using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Rulesets; @@ -35,15 +29,15 @@ using osu.Game.Storyboards.Drawables; namespace osu.Game.Screens.Play { - public class Player : ScreenWithBeatmapBackground, IProvideCursor + public class Player : ScreenWithBeatmapBackground { protected override bool AllowBackButton => false; // handled by HoldForMenuButton - protected override float BackgroundParallaxAmount => 0.1f; + public override float BackgroundParallaxAmount => 0.1f; - protected override bool HideOverlaysOnEnter => true; + public override bool HideOverlaysOnEnter => true; - protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; + public override OverlayActivation InitialOverlayActivationMode => OverlayActivation.UserTriggered; public Action RestartRequested; @@ -54,169 +48,91 @@ namespace osu.Game.Screens.Play public bool AllowResults { get; set; } = true; private Bindable mouseWheelDisabled; - private Bindable userAudioOffset; + + private readonly Bindable storyboardReplacesBackground = new Bindable(); public int RestartCount; - public CursorContainer Cursor => RulesetContainer.Cursor; - public bool ProvidingUserCursor => RulesetContainer?.Cursor != null && !RulesetContainer.HasReplayLoaded.Value; - - private IAdjustableClock sourceClock; - - /// - /// The decoupled clock used for gameplay. Should be used for seeks and clock control. - /// - private DecoupleableInterpolatingFramedClock adjustableClock; - [Resolved] private ScoreManager scoreManager { get; set; } - private PauseContainer pauseContainer; - private RulesetInfo ruleset; - private APIAccess api; + private IAPIProvider api; private SampleChannel sampleRestart; - protected ScoreProcessor ScoreProcessor; - protected RulesetContainer RulesetContainer; + protected ScoreProcessor ScoreProcessor { get; private set; } + protected DrawableRuleset DrawableRuleset { get; private set; } - private HUDOverlay hudOverlay; - private FailOverlay failOverlay; + protected HUDOverlay HUDOverlay { get; private set; } - private DrawableStoryboard storyboard; - private Container storyboardContainer; + public bool LoadedBeatmapSuccessfully => DrawableRuleset?.Objects.Any() == true; - public bool LoadedBeatmapSuccessfully => RulesetContainer?.Objects.Any() == true; + protected GameplayClockContainer GameplayClockContainer { get; private set; } [BackgroundDependencyLoader] - private void load(AudioManager audio, APIAccess api, OsuConfigManager config) + private void load(AudioManager audio, IAPIProvider api, OsuConfigManager config) { this.api = api; - WorkingBeatmap working = Beatmap.Value; - if (working is DummyWorkingBeatmap) + WorkingBeatmap working = loadBeatmap(); + + if (working == null) return; sampleRestart = audio.Sample.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); - userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); + showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); - IBeatmap beatmap; - - try - { - beatmap = working.Beatmap; - - if (beatmap == null) - throw new InvalidOperationException("Beatmap was not loaded"); - - ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; - var rulesetInstance = ruleset.CreateInstance(); - - try - { - RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working); - } - catch (BeatmapInvalidForRulesetException) - { - // we may fail to create a RulesetContainer if the beatmap cannot be loaded with the user's preferred ruleset - // let's try again forcing the beatmap's ruleset. - ruleset = beatmap.BeatmapInfo.Ruleset; - rulesetInstance = ruleset.CreateInstance(); - RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap.Value); - } - - if (!RulesetContainer.Objects.Any()) - { - Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); - return; - } - } - catch (Exception e) - { - Logger.Error(e, "Could not load beatmap sucessfully!"); - //couldn't load, hard abort! - return; - } - - sourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock(); - adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; - - adjustableClock.Seek(AllowLeadIn - ? Math.Min(0, RulesetContainer.GameplayStartTime - beatmap.BeatmapInfo.AudioLeadIn) - : RulesetContainer.GameplayStartTime); - - adjustableClock.ProcessFrame(); - - // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. - // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck. - var platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; - - // the final usable gameplay clock with user-set offsets applied. - var offsetClock = new FramedOffsetClock(platformOffsetClock); - - userAudioOffset.ValueChanged += v => offsetClock.Offset = v; - userAudioOffset.TriggerChange(); - - ScoreProcessor = RulesetContainer.CreateScoreProcessor(); + ScoreProcessor = DrawableRuleset.CreateScoreProcessor(); if (!ScoreProcessor.Mode.Disabled) config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); - Children = new Drawable[] + InternalChild = GameplayClockContainer = new GameplayClockContainer(working, AllowLeadIn, DrawableRuleset.GameplayStartTime); + + GameplayClockContainer.Children = new[] { - pauseContainer = new PauseContainer(offsetClock, adjustableClock) + StoryboardContainer = CreateStoryboardContainer(), + new ScalingContainer(ScalingMode.Gameplay) { - Retries = RestartCount, - OnRetry = Restart, - OnQuit = performUserRequestedExit, - CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, - Children = new[] + Child = new LocalSkinOverrideContainer(working.Skin) { - storyboardContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - }, - new ScalingContainer(ScalingMode.Gameplay) - { - Child = new LocalSkinOverrideContainer(working.Skin) - { - RelativeSizeAxes = Axes.Both, - Child = RulesetContainer - } - }, - new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - ProcessCustomClock = false, - Breaks = beatmap.Breaks - }, - new ScalingContainer(ScalingMode.Gameplay) - { - Child = RulesetContainer.Cursor?.CreateProxy() ?? new Container(), - }, - hudOverlay = new HUDOverlay(ScoreProcessor, RulesetContainer, working, offsetClock, adjustableClock) - { - Clock = Clock, // hud overlay doesn't want to use the audio clock directly - ProcessCustomClock = false, - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }, - new SkipOverlay(RulesetContainer.GameplayStartTime) - { - Clock = Clock, // skip button doesn't want to use the audio clock directly - ProcessCustomClock = false, - AdjustableClock = adjustableClock, - FramedClock = offsetClock, - }, + RelativeSizeAxes = Axes.Both, + Child = DrawableRuleset } }, - failOverlay = new FailOverlay + new BreakOverlay(working.Beatmap.BeatmapInfo.LetterboxInBreaks, ScoreProcessor) { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Breaks = working.Beatmap.Breaks + }, + // display the cursor above some HUD elements. + DrawableRuleset.Cursor?.CreateProxy() ?? new Container(), + HUDOverlay = new HUDOverlay(ScoreProcessor, DrawableRuleset, working) + { + HoldToQuit = { Action = performUserRequestedExit }, + PlayerSettingsOverlay = { PlaybackSettings = { UserPlaybackRate = { BindTarget = GameplayClockContainer.UserPlaybackRate } } }, + KeyCounter = { Visible = { BindTarget = DrawableRuleset.HasReplayLoaded } }, + RequestSeek = GameplayClockContainer.Seek, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }, + new SkipOverlay(DrawableRuleset.GameplayStartTime) + { + RequestSeek = GameplayClockContainer.Seek + }, + FailOverlay = new FailOverlay + { + OnRetry = Restart, + OnQuit = performUserRequestedExit, + }, + PauseOverlay = new PauseOverlay + { + OnResume = Resume, + Retries = RestartCount, OnRetry = Restart, OnQuit = performUserRequestedExit, }, @@ -224,7 +140,7 @@ namespace osu.Game.Screens.Play { Action = () => { - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; fadeOut(true); Restart(); @@ -232,13 +148,11 @@ namespace osu.Game.Screens.Play } }; - hudOverlay.HoldToQuit.Action = performUserRequestedExit; - hudOverlay.KeyCounter.Visible.BindTo(RulesetContainer.HasReplayLoaded); + // bind clock into components that require it + DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused); - RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); - - if (ShowStoryboard) - initializeStoryboard(false); + // load storyboard as part of player's load if we can + initializeStoryboard(false); // Bind ScoreProcessor to ourselves ScoreProcessor.AllJudged += onCompletion; @@ -248,29 +162,66 @@ namespace osu.Game.Screens.Play mod.ApplyToScoreProcessor(ScoreProcessor); } - private void applyRateFromMods() + private WorkingBeatmap loadBeatmap() { - if (sourceClock == null) return; + WorkingBeatmap working = Beatmap.Value; + if (working is DummyWorkingBeatmap) + return null; - sourceClock.Rate = 1; - foreach (var mod in Beatmap.Value.Mods.Value.OfType()) - mod.ApplyToClock(sourceClock); + try + { + var beatmap = working.Beatmap; + + if (beatmap == null) + throw new InvalidOperationException("Beatmap was not loaded"); + + ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; + var rulesetInstance = ruleset.CreateInstance(); + + try + { + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(working); + } + catch (BeatmapInvalidForRulesetException) + { + // we may fail to create a DrawableRuleset if the beatmap cannot be loaded with the user's preferred ruleset + // let's try again forcing the beatmap's ruleset. + ruleset = beatmap.BeatmapInfo.Ruleset; + rulesetInstance = ruleset.CreateInstance(); + DrawableRuleset = rulesetInstance.CreateDrawableRulesetWith(Beatmap.Value); + } + + if (!DrawableRuleset.Objects.Any()) + { + Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); + return null; + } + } + catch (Exception e) + { + Logger.Error(e, "Could not load beatmap sucessfully!"); + //couldn't load, hard abort! + return null; + } + + return working; } private void performUserRequestedExit() { - if (!IsCurrentScreen) return; - Exit(); + if (!this.IsCurrentScreen()) return; + + this.Exit(); } public void Restart() { - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; sampleRestart?.Play(); ValidForResume = false; RestartRequested?.Invoke(); - Exit(); + this.Exit(); } private ScheduledDelegate onCompletionEvent; @@ -289,13 +240,13 @@ namespace osu.Game.Screens.Play { onCompletionEvent = Schedule(delegate { - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; var score = CreateScore(); - if (RulesetContainer.ReplayScore == null) - scoreManager.Import(score, true); + if (DrawableRuleset.ReplayScore == null) + scoreManager.Import(score); - Push(CreateResults(score)); + this.Push(CreateResults(score)); onCompletionEvent = null; }); @@ -304,7 +255,7 @@ namespace osu.Game.Screens.Play protected virtual ScoreInfo CreateScore() { - var score = RulesetContainer.ReplayScore?.ScoreInfo ?? new ScoreInfo + var score = DrawableRuleset.ReplayScore?.ScoreInfo ?? new ScoreInfo { Beatmap = Beatmap.Value.BeatmapInfo, Ruleset = ruleset, @@ -317,97 +268,30 @@ namespace osu.Game.Screens.Play return score; } - private bool onFail() + protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !GameplayClockContainer.IsPaused.Value; + + protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score); + + #region Storyboard + + private DrawableStoryboard storyboard; + protected UserDimContainer StoryboardContainer { get; private set; } + + protected virtual UserDimContainer CreateStoryboardContainer() => new UserDimContainer(true) { - if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) - return false; + RelativeSizeAxes = Axes.Both, + Alpha = 1, + EnableUserDim = { Value = true } + }; - adjustableClock.Stop(); - - HasFailed = true; - failOverlay.Retries = RestartCount; - failOverlay.Show(); - return true; - } - - protected override void OnEntering(Screen last) - { - base.OnEntering(last); - - if (!LoadedBeatmapSuccessfully) - return; - - Content.Alpha = 0; - Content - .ScaleTo(0.7f) - .ScaleTo(1, 750, Easing.OutQuint) - .Delay(250) - .FadeIn(250); - - Task.Run(() => - { - sourceClock.Reset(); - - Schedule(() => - { - adjustableClock.ChangeSource(sourceClock); - applyRateFromMods(); - - this.Delay(750).Schedule(() => - { - if (!pauseContainer.IsPaused) - { - adjustableClock.Start(); - } - }); - }); - }); - - pauseContainer.Alpha = 0; - pauseContainer.FadeIn(750, Easing.OutQuint); - } - - protected override void OnSuspending(Screen next) - { - fadeOut(); - base.OnSuspending(next); - } - - protected override bool OnExiting(Screen next) - { - if (onCompletionEvent != null) - { - // Proceed to result screen if beatmap already finished playing - onCompletionEvent.RunTask(); - return true; - } - - if ((!AllowPause || HasFailed || !ValidForResume || pauseContainer?.IsPaused != false || RulesetContainer?.HasReplayLoaded != false) && (!pauseContainer?.IsResuming ?? true)) - { - // In the case of replays, we may have changed the playback rate. - applyRateFromMods(); - - fadeOut(); - return base.OnExiting(next); - } - - if (LoadedBeatmapSuccessfully) - pauseContainer?.Pause(); - - return true; - } - - private void fadeOut(bool instant = false) - { - float fadeOutDuration = instant ? 0 : 250; - Content.FadeOut(fadeOutDuration); - } - - protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !pauseContainer.IsPaused; + private Bindable showStoryboard; private void initializeStoryboard(bool asyncLoad) { - if (storyboardContainer == null) + if (StoryboardContainer == null || storyboard != null) + return; + + if (!showStoryboard.Value) return; var beatmap = Beatmap.Value; @@ -416,31 +300,184 @@ namespace osu.Game.Screens.Play storyboard.Masking = true; if (asyncLoad) - LoadComponentAsync(storyboard, storyboardContainer.Add); + LoadComponentAsync(storyboard, StoryboardContainer.Add); else - storyboardContainer.Add(storyboard); + StoryboardContainer.Add(storyboard); } - protected override void UpdateBackgroundElements() + #endregion + + #region Fail Logic + + protected FailOverlay FailOverlay { get; private set; } + + private bool onFail() { - if (!IsCurrentScreen) return; + if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) + return false; - base.UpdateBackgroundElements(); + GameplayClockContainer.Stop(); - if (ShowStoryboard && storyboard == null) - initializeStoryboard(true); + HasFailed = true; - var beatmap = Beatmap.Value; - var storyboardVisible = ShowStoryboard && beatmap.Storyboard.HasDrawable; + // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) + // could process an extra frame after the GameplayClock is stopped. + // In such cases we want the fail state to precede a user triggered pause. + if (PauseOverlay.State == Visibility.Visible) + PauseOverlay.Hide(); - storyboardContainer? - .FadeColour(OsuColour.Gray(BackgroundOpacity), BACKGROUND_FADE_DURATION, Easing.OutQuint) - .FadeTo(storyboardVisible && BackgroundOpacity > 0 ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint); - - if (storyboardVisible && beatmap.Storyboard.ReplacesBackground) - Background?.FadeTo(0, BACKGROUND_FADE_DURATION, Easing.OutQuint); + FailOverlay.Retries = RestartCount; + FailOverlay.Show(); + return true; } - protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score); + #endregion + + #region Pause Logic + + public bool IsResuming { get; private set; } + + /// + /// The amount of gameplay time after which a second pause is allowed. + /// + private const double pause_cooldown = 1000; + + protected PauseOverlay PauseOverlay { get; private set; } + + private double? lastPauseActionTime; + + private bool canPause => + // must pass basic screen conditions (beatmap loaded, instance allows pause) + LoadedBeatmapSuccessfully && AllowPause && ValidForResume + // replays cannot be paused and exit immediately + && !DrawableRuleset.HasReplayLoaded.Value + // cannot pause if we are already in a fail state + && !HasFailed + // cannot pause if already paused (or in a cooldown state) unless we are in a resuming state. + && (IsResuming || (GameplayClockContainer.IsPaused.Value == false && !pauseCooldownActive)); + + private bool pauseCooldownActive => + lastPauseActionTime.HasValue && GameplayClockContainer.GameplayClock.CurrentTime < lastPauseActionTime + pause_cooldown; + + private bool canResume => + // cannot resume from a non-paused state + GameplayClockContainer.IsPaused.Value + // cannot resume if we are already in a fail state + && !HasFailed + // already resuming + && !IsResuming; + + protected override void Update() + { + base.Update(); + + // eagerly pause when we lose window focus (if we are locally playing). + if (!Game.IsActive.Value) + Pause(); + } + + public void Pause() + { + if (!canPause) return; + + IsResuming = false; + GameplayClockContainer.Stop(); + PauseOverlay.Show(); + lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; + } + + public void Resume() + { + if (!canResume) return; + + IsResuming = true; + PauseOverlay.Hide(); + + // time-based conditions may allow instant resume. + if (GameplayClockContainer.GameplayClock.CurrentTime < Beatmap.Value.Beatmap.HitObjects.First().StartTime) + completeResume(); + else + DrawableRuleset.RequestResume(completeResume); + + void completeResume() + { + GameplayClockContainer.Start(); + IsResuming = false; + } + } + + #endregion + + #region Screen Logic + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + + if (!LoadedBeatmapSuccessfully) + return; + + Alpha = 0; + this + .ScaleTo(0.7f) + .ScaleTo(1, 750, Easing.OutQuint) + .Delay(250) + .FadeIn(250); + + showStoryboard.ValueChanged += _ => initializeStoryboard(true); + + Background.EnableUserDim.Value = true; + Background.BlurAmount.Value = 0; + + Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); + StoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground); + + storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable; + + GameplayClockContainer.Restart(); + GameplayClockContainer.FadeInFromZero(750, Easing.OutQuint); + } + + public override void OnSuspending(IScreen next) + { + fadeOut(); + base.OnSuspending(next); + } + + public override bool OnExiting(IScreen next) + { + if (onCompletionEvent != null) + { + // Proceed to result screen if beatmap already finished playing + onCompletionEvent.RunTask(); + return true; + } + + if (canPause) + { + Pause(); + return true; + } + + if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) + // still want to block if we are within the cooldown period and not already paused. + return true; + + GameplayClockContainer.ResetLocalAdjustments(); + + fadeOut(); + return base.OnExiting(next); + } + + private void fadeOut(bool instant = false) + { + float fadeOutDuration = instant ? 0 : 250; + this.FadeOut(fadeOutDuration); + + Background.EnableUserDim.Value = false; + storyboardReplacesBackground.Value = false; + } + + #endregion } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index ded25f013a..e9ee5d3fa8 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -8,7 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; +using osu.Framework.Input; using osu.Framework.Localisation; using osu.Framework.Screens; using osu.Framework.Threading; @@ -17,6 +17,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Menu; +using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.PlayerSettings; using osuTK; using osuTK.Graphics; @@ -25,18 +26,25 @@ namespace osu.Game.Screens.Play { public class PlayerLoader : ScreenWithBeatmapBackground { + protected const float BACKGROUND_BLUR = 15; + private readonly Func createPlayer; - private static readonly Vector2 background_blur = new Vector2(15); private Player player; + private Container content; + private BeatmapMetadataDisplay info; private bool hideOverlays; - protected override bool HideOverlaysOnEnter => hideOverlays; + public override bool HideOverlaysOnEnter => hideOverlays; + + public override bool DisallowExternalBeatmapRulesetChanges => true; private Task loadTask; + private InputManager inputManager; + public PlayerLoader(Func createPlayer) { this.createPlayer = createPlayer; @@ -51,34 +59,42 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - Add(info = new BeatmapMetadataDisplay(Beatmap.Value) + InternalChild = content = new Container { - Alpha = 0, Anchor = Anchor.Centre, Origin = Anchor.Centre, - }); - - Add(new FillFlowContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Margin = new MarginPadding(25), - Children = new PlayerSettingsGroup[] + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - visualSettings = new VisualSettings(), - new InputSettings() + info = new BeatmapMetadataDisplay(Beatmap.Value) + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding(25), + Children = new PlayerSettingsGroup[] + { + VisualSettings = new VisualSettings(), + new InputSettings() + } + } } - }); + }; loadNewPlayer(); } private void playerLoaded(Player player) => info.Loading = false; - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { base.OnResuming(last); @@ -105,21 +121,22 @@ namespace osu.Game.Screens.Play private void contentIn() { - Content.ScaleTo(1, 650, Easing.OutQuint); - Content.FadeInFromZero(400); + content.ScaleTo(1, 650, Easing.OutQuint); + content.FadeInFromZero(400); } private void contentOut() { - Content.ScaleTo(0.7f, 300, Easing.InQuint); - Content.FadeOut(250); + content.ScaleTo(0.7f, 300, Easing.InQuint); + content.FadeOut(250); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - Content.ScaleTo(0.7f); + content.ScaleTo(0.7f); + Background?.FadeColour(Color4.White, 800, Easing.OutQuint); contentIn(); @@ -131,8 +148,6 @@ namespace osu.Game.Screens.Play { base.LogoArriving(logo, resuming); - logo.RelativePositionAxes = Axes.Both; - logo.ScaleTo(new Vector2(0.15f), 300, Easing.In); logo.MoveTo(new Vector2(0.5f), 300, Easing.In); logo.FadeIn(350); @@ -140,37 +155,23 @@ namespace osu.Game.Screens.Play logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo); } + protected override void LoadComplete() + { + inputManager = GetContainingInputManager(); + base.LoadComplete(); + } + private ScheduledDelegate pushDebounce; - private VisualSettings visualSettings; + protected VisualSettings VisualSettings; + + // Hhere because IsHovered will not update unless we do so. + public override bool HandlePositionalInput => true; private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && GetContainingInputManager()?.DraggedDrawable == null; - protected override bool OnHover(HoverEvent e) - { - // restore our screen defaults - InitializeBackgroundElements(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - if (GetContainingInputManager().HoveredDrawables.Contains(visualSettings)) - { - // show user setting preview - UpdateBackgroundElements(); - } - base.OnHoverLost(e); - } - - protected override void InitializeBackgroundElements() - { - Background?.FadeTo(1, BACKGROUND_FADE_DURATION, Easing.OutQuint); - Background?.BlurTo(background_blur, BACKGROUND_FADE_DURATION, Easing.OutQuint); - } - private void pushWhenLoaded() { - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; try { @@ -191,7 +192,7 @@ namespace osu.Game.Screens.Play this.Delay(250).Schedule(() => { - if (!IsCurrentScreen) return; + if (!this.IsCurrentScreen()) return; loadTask = null; @@ -200,9 +201,9 @@ namespace osu.Game.Screens.Play ValidForResume = false; if (player.LoadedBeatmapSuccessfully) - Push(player); + this.Push(player); else - Exit(); + this.Exit(); }); }, 500); } @@ -218,18 +219,20 @@ namespace osu.Game.Screens.Play pushDebounce = null; } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); cancelLoad(); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { - Content.ScaleTo(0.7f, 150, Easing.InQuint); + content.ScaleTo(0.7f, 150, Easing.InQuint); this.FadeOut(150); cancelLoad(); + Background.EnableUserDim.Value = false; + return base.OnExiting(next); } @@ -244,6 +247,29 @@ namespace osu.Game.Screens.Play } } + protected override void Update() + { + base.Update(); + + if (!this.IsCurrentScreen()) + return; + + // We need to perform this check here rather than in OnHover as any number of children of VisualSettings + // may also be handling the hover events. + if (inputManager.HoveredDrawables.Contains(VisualSettings)) + { + // Preview user-defined background dim and blur when hovered on the visual settings panel. + Background.EnableUserDim.Value = true; + Background.BlurAmount.Value = 0; + } + else + { + // Returns background dim and blur to the values specified by PlayerLoader. + Background.EnableUserDim.Value = false; + Background.BlurAmount.Value = BACKGROUND_BLUR; + } + } + private class BeatmapMetadataDisplay : Container { private class MetadataLine : Container @@ -275,6 +301,7 @@ namespace osu.Game.Screens.Play private readonly WorkingBeatmap beatmap; private LoadingAnimation loading; private Sprite backgroundSprite; + private ModDisplay modDisplay; public bool Loading { @@ -301,7 +328,7 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load() { - var metadata = beatmap?.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); + var metadata = beatmap.BeatmapInfo?.Metadata ?? new BeatmapMetadata(); AutoSizeAxes = Axes.Both; Children = new Drawable[] @@ -317,16 +344,14 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), - TextSize = 36, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 36, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, new OsuSpriteText { Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)), - TextSize = 26, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 26, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, @@ -354,8 +379,7 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = beatmap?.BeatmapInfo?.Version, - TextSize = 26, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 26, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Margin = new MarginPadding @@ -373,6 +397,14 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, + new ModDisplay + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Top = 20 }, + Current = beatmap.Mods + } }, } }; diff --git a/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs index da47de8a9b..d3570a8d2d 100644 --- a/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index 31d390effe..5963352e5b 100644 --- a/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs index 755ba468cc..826be792bd 100644 --- a/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/InputSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 13e403e899..c691d161ed 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.PlayerSettings @@ -15,14 +15,20 @@ namespace osu.Game.Screens.Play.PlayerSettings protected override string Title => @"playback"; - public IAdjustableClock AdjustableClock { set; get; } + public readonly Bindable UserPlaybackRate = new BindableDouble(1) + { + Default = 1, + MinValue = 0.5, + MaxValue = 2, + Precision = 0.1, + }; - private readonly PlayerSliderBar sliderbar; + private readonly PlayerSliderBar rateSlider; + + private readonly OsuSpriteText multiplierText; public PlaybackSettings() { - OsuSpriteText multiplierText; - Children = new Drawable[] { new Container @@ -42,35 +48,18 @@ namespace osu.Game.Screens.Play.PlayerSettings { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), } }, }, - sliderbar = new PlayerSliderBar - { - Bindable = new BindableDouble(1) - { - Default = 1, - MinValue = 0.5, - MaxValue = 2, - Precision = 0.1, - }, - } + rateSlider = new PlayerSliderBar { Bindable = UserPlaybackRate } }; - - sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{sliderbar.Bar.TooltipText}x"; - sliderbar.Bindable.TriggerChange(); } protected override void LoadComplete() { base.LoadComplete(); - - if (AdjustableClock == null) - return; - - var clockRate = AdjustableClock.Rate; - sliderbar.Bindable.ValueChanged += rateMultiplier => AdjustableClock.Rate = clockRate * rateMultiplier; + rateSlider.Bindable.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier.NewValue:0.0}x", true); } } } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index 2a9da9c6e1..8a4acacb24 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index 833a22556e..efaeeea79f 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -34,10 +34,11 @@ namespace osu.Game.Screens.Play.PlayerSettings public bool Expanded { - get { return expanded; } + get => expanded; set { if (expanded == value) return; + expanded = value; content.ClearTransforms(); @@ -94,8 +95,7 @@ namespace osu.Game.Screens.Play.PlayerSettings Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = Title.ToUpperInvariant(), - TextSize = 17, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = 10 }, }, button = new IconButton diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index d2c7677f7c..28fe1f35ca 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index f762597e81..aec42eb024 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play.PlayerSettings }, showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboards" }, beatmapSkinsToggle = new PlayerCheckbox { LabelText = "Beatmap skins" }, - beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hit sounds" } + beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hitsounds" } }; } diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 04cf922d74..949b08d98d 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Scoring; @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { base.LoadComplete(); - RulesetContainer.SetReplayScore(score); + DrawableRuleset?.SetReplayScore(score); } protected override ScoreInfo CreateScore() => score.ScoreInfo; diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 3846b45d2f..d7d2c97598 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -1,13 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Screens; -using osu.Game.Configuration; using osu.Game.Screens.Backgrounds; -using osuTK; namespace osu.Game.Screens.Play { @@ -16,59 +10,5 @@ namespace osu.Game.Screens.Play protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); protected new BackgroundScreenBeatmap Background => (BackgroundScreenBeatmap)base.Background; - - public override bool AllowBeatmapRulesetChange => false; - - protected const float BACKGROUND_FADE_DURATION = 800; - - protected float BackgroundOpacity => 1 - (float)DimLevel; - - #region User Settings - - protected Bindable DimLevel; - protected Bindable BlurLevel; - protected Bindable ShowStoryboard; - - #endregion - - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - DimLevel = config.GetBindable(OsuSetting.DimLevel); - BlurLevel = config.GetBindable(OsuSetting.BlurLevel); - ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); - } - - protected override void OnEntering(Screen last) - { - base.OnEntering(last); - DimLevel.ValueChanged += _ => UpdateBackgroundElements(); - BlurLevel.ValueChanged += _ => UpdateBackgroundElements(); - ShowStoryboard.ValueChanged += _ => UpdateBackgroundElements(); - InitializeBackgroundElements(); - } - - protected override void OnResuming(Screen last) - { - base.OnResuming(last); - InitializeBackgroundElements(); - } - - /// - /// Called once on entering screen. By Default, performs a full call. - /// - protected virtual void InitializeBackgroundElements() => UpdateBackgroundElements(); - - /// - /// Called wen background elements require updates, usually due to a user changing a setting. - /// - /// - protected virtual void UpdateBackgroundElements() - { - if (!IsCurrentScreen) return; - - Background?.FadeTo(BackgroundOpacity, BACKGROUND_FADE_DURATION, Easing.OutQuint); - Background?.BlurTo(new Vector2((float)BlurLevel.Value * 25), BACKGROUND_FADE_DURATION, Easing.OutQuint); - } } } diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index e5a6dd2db1..a6e6009b95 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; @@ -9,7 +9,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; -using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Ranking; @@ -27,8 +26,7 @@ namespace osu.Game.Screens.Play { private readonly double startTime; - public IAdjustableClock AdjustableClock; - public IFrameBasedClock FramedClock; + public Action RequestSeek; private Button button; private Box remainingTimeBox; @@ -46,24 +44,21 @@ namespace osu.Game.Screens.Play State = Visibility.Visible; RelativePositionAxes = Axes.Both; - RelativeSizeAxes = Axes.Both; + RelativeSizeAxes = Axes.X; Position = new Vector2(0.5f, 0.7f); - Size = new Vector2(1, 0.14f); + Size = new Vector2(1, 100); Origin = Anchor.Centre; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, GameplayClock clock) { var baseClock = Clock; - if (FramedClock != null) - { - Clock = FramedClock; - ProcessCustomClock = false; - } + if (clock != null) + Clock = clock; Children = new Drawable[] { @@ -111,7 +106,7 @@ namespace osu.Game.Screens.Play using (BeginAbsoluteSequence(beginFadeTime)) this.FadeOut(fade_time); - button.Action = () => AdjustableClock?.Seek(startTime - skip_required_cutoff - fade_time); + button.Action = () => RequestSeek?.Invoke(startTime - skip_required_cutoff - fade_time); displayTime = Time.Current; @@ -158,7 +153,7 @@ namespace osu.Game.Screens.Play public Visibility State { - get { return state; } + get => state; set { bool stateChanged = value != state; @@ -273,8 +268,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, RelativePositionAxes = Axes.Y, Y = 0.7f, - TextSize = 12, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Origin = Anchor.Centre, Text = @"SKIP", }, @@ -313,7 +307,7 @@ namespace osu.Game.Screens.Play protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return false; sampleConfirm.Play(); diff --git a/osu.Game/Screens/Play/SoloResults.cs b/osu.Game/Screens/Play/SoloResults.cs index c06a5c3f68..2b9aec257c 100644 --- a/osu.Game/Screens/Play/SoloResults.cs +++ b/osu.Game/Screens/Play/SoloResults.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Scoring; @@ -17,8 +17,8 @@ namespace osu.Game.Screens.Play protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { - new ScoreOverviewPageInfo(Score, Beatmap), - new LocalLeaderboardPageInfo(Score, Beatmap) + new ScoreOverviewPageInfo(Score, Beatmap.Value), + new LocalLeaderboardPageInfo(Score, Beatmap.Value) }; } } diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 336f9cc430..94b25e04a3 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -9,8 +9,7 @@ using System.Collections.Generic; using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; -using osu.Framework.Configuration; -using osu.Framework.Timing; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; @@ -29,14 +28,11 @@ namespace osu.Game.Screens.Play private readonly SongProgressGraph graph; private readonly SongProgressInfo info; - public Action OnSeek; + public Action RequestSeek; public override bool HandleNonPositionalInput => AllowSeeking; public override bool HandlePositionalInput => AllowSeeking; - private IClock audioClock; - public IClock AudioClock { set { audioClock = info.AudioClock = value; } } - private double lastHitTime => ((objects.Last() as IHasEndTime)?.EndTime ?? objects.Last().StartTime) + 1; private double firstHitTime => objects.First().StartTime; @@ -59,9 +55,14 @@ namespace osu.Game.Screens.Play private readonly BindableBool replayLoaded = new BindableBool(); - [BackgroundDependencyLoader] - private void load(OsuColour colours) + private GameplayClock gameplayClock; + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, GameplayClock clock) { + if (clock != null) + gameplayClock = clock; + graph.FillColour = bar.FillColour = colours.BlueLighter; } @@ -94,8 +95,8 @@ namespace osu.Game.Screens.Play { Alpha = 0, Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - OnSeek = position => OnSeek?.Invoke(position), + Origin = Anchor.BottomLeft, + OnSeek = time => RequestSeek?.Invoke(time), }, }; } @@ -104,24 +105,20 @@ namespace osu.Game.Screens.Play { State = Visibility.Visible; - replayLoaded.ValueChanged += v => AllowSeeking = v; + replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; replayLoaded.TriggerChange(); } - public void BindRulestContainer(RulesetContainer rulesetContainer) + public void BindDrawableRuleset(DrawableRuleset drawableRuleset) { - replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); + replayLoaded.BindTo(drawableRuleset.HasReplayLoaded); } private bool allowSeeking; public bool AllowSeeking { - get - { - return allowSeeking; - } - + get => allowSeeking; set { if (allowSeeking == value) return; @@ -157,14 +154,11 @@ namespace osu.Game.Screens.Play if (objects == null) return; - double position = audioClock?.CurrentTime ?? Time.Current; - double progress = (position - firstHitTime) / (lastHitTime - firstHitTime); + double position = gameplayClock?.CurrentTime ?? Time.Current; + double progress = Math.Min(1, (position - firstHitTime) / (lastHitTime - firstHitTime)); - if (progress < 1) - { - bar.CurrentTime = position; - graph.Progress = (int)(graph.ColumnCount * progress); - } + bar.CurrentTime = position; + graph.Progress = (int)(graph.ColumnCount * progress); } } } diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index b06a34e603..2e7d452fe7 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -20,22 +20,22 @@ namespace osu.Game.Screens.Play public Color4 FillColour { - set { fill.Colour = value; } + set => fill.Colour = value; } public double StartTime { - set { CurrentNumber.MinValue = value; } + set => CurrentNumber.MinValue = value; } public double EndTime { - set { CurrentNumber.MaxValue = value; } + set => CurrentNumber.MaxValue = value; } public double CurrentTime { - set { CurrentNumber.Value = value; } + set => CurrentNumber.Value = value; } public SongProgressBar(float barHeight, float handleBarHeight, Vector2 handleSize) diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 6b83c82033..e480c5b502 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using System.Collections.Generic; diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 3156a646db..7441c335d2 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using System; @@ -27,14 +26,24 @@ namespace osu.Game.Screens.Play private const int margin = 10; - public IClock AudioClock; - - public double StartTime { set { startTime = value; } } - public double EndTime { set { endTime = value; } } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public double StartTime { + set => startTime = value; + } + + public double EndTime + { + set => endTime = value; + } + + private GameplayClock gameplayClock; + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, GameplayClock clock) + { + if (clock != null) + gameplayClock = clock; + Children = new Drawable[] { timeCurrent = new OsuSpriteText @@ -42,7 +51,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, Margin = new MarginPadding { Left = margin, @@ -53,14 +62,14 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, }, timeLeft = new OsuSpriteText { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, Margin = new MarginPadding { Right = margin, @@ -73,7 +82,9 @@ namespace osu.Game.Screens.Play { base.Update(); - double songCurrentTime = AudioClock.CurrentTime - startTime; + var time = gameplayClock?.CurrentTime ?? Time.Current; + + double songCurrentTime = time - startTime; int currentPercent = Math.Max(0, Math.Min(100, (int)(songCurrentTime / songLength * 100))); int currentSecond = (int)Math.Floor(songCurrentTime / 1000.0); @@ -86,7 +97,7 @@ namespace osu.Game.Screens.Play if (currentSecond != previousSecond && songCurrentTime < songLength) { timeCurrent.Text = formatTime(TimeSpan.FromSeconds(currentSecond)); - timeLeft.Text = formatTime(TimeSpan.FromMilliseconds(endTime - AudioClock.CurrentTime)); + timeLeft.Text = formatTime(TimeSpan.FromMilliseconds(endTime - time)); previousSecond = currentSecond; } diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index c0ee0079b9..d10034d552 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using osu.Framework; using osu.Framework.Caching; using osu.Framework.Extensions.Color4Extensions; @@ -12,22 +13,26 @@ using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Framework.Threading; namespace osu.Game.Screens.Play { - public class SquareGraph : BufferedContainer + public class SquareGraph : Container { - private Column[] columns = { }; + private BufferedContainer columns; - public int ColumnCount => columns.Length; + public int ColumnCount => columns?.Children.Count ?? 0; private int progress; + public int Progress { - get { return progress; } + get => progress; set { if (value == progress) return; + progress = value; redrawProgress(); } @@ -36,36 +41,33 @@ namespace osu.Game.Screens.Play private float[] calculatedValues = { }; // values but adjusted to fit the amount of columns private int[] values; + public int[] Values { - get { return values; } + get => values; set { if (value == values) return; + values = value; layout.Invalidate(); } } private Color4 fillColour; + public Color4 FillColour { - get { return fillColour; } + get => fillColour; set { if (value == fillColour) return; + fillColour = value; redrawFilled(); } } - public SquareGraph() - { - CacheDrawnFrameBuffer = true; - } - - private Cached layout = new Cached(); - public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { if ((invalidation & Invalidation.DrawSize) > 0) @@ -73,25 +75,70 @@ namespace osu.Game.Screens.Play return base.Invalidate(invalidation, source, shallPropagate); } + private Cached layout = new Cached(); + private ScheduledDelegate scheduledCreate; + protected override void Update() { base.Update(); - if (!layout.IsValid) + if (values != null && !layout.IsValid) { - recreateGraph(); + columns?.FadeOut(500, Easing.OutQuint).Expire(); + + scheduledCreate?.Cancel(); + scheduledCreate = Scheduler.AddDelayed(RecreateGraph, 500); + layout.Validate(); } } + private CancellationTokenSource cts; + + /// + /// Recreates the entire graph. + /// + protected virtual void RecreateGraph() + { + var newColumns = new BufferedContainer + { + CacheDrawnFrameBuffer = true, + RelativeSizeAxes = Axes.Both, + }; + + for (float x = 0; x < DrawWidth; x += Column.WIDTH) + { + newColumns.Add(new Column(DrawHeight) + { + LitColour = fillColour, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Position = new Vector2(x, 0), + State = ColumnState.Dimmed, + }); + } + + cts?.Cancel(); + + LoadComponentAsync(newColumns, c => + { + Child = columns = c; + columns.FadeInFromZero(500, Easing.OutQuint); + + recalculateValues(); + redrawFilled(); + redrawProgress(); + }, (cts = new CancellationTokenSource()).Token); + } + /// /// Redraws all the columns to match their lit/dimmed state. /// private void redrawProgress() { - for (int i = 0; i < columns.Length; i++) + for (int i = 0; i < ColumnCount; i++) columns[i].State = i <= progress ? ColumnState.Lit : ColumnState.Dimmed; - ForceRedraw(); + columns?.ForceRedraw(); } /// @@ -101,7 +148,7 @@ namespace osu.Game.Screens.Play { for (int i = 0; i < ColumnCount; i++) columns[i].Filled = calculatedValues.ElementAtOrDefault(i); - ForceRedraw(); + columns?.ForceRedraw(); } /// @@ -130,34 +177,6 @@ namespace osu.Game.Screens.Play calculatedValues = newValues.ToArray(); } - /// - /// Recreates the entire graph. - /// - private void recreateGraph() - { - var newColumns = new List(); - - for (float x = 0; x < DrawWidth; x += Column.WIDTH) - { - newColumns.Add(new Column - { - LitColour = fillColour, - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Height = DrawHeight, - Position = new Vector2(x, 0), - State = ColumnState.Dimmed, - }); - } - - columns = newColumns.ToArray(); - Children = columns; - - recalculateValues(); - redrawFilled(); - redrawProgress(); - } - public class Column : Container, IStateful { protected readonly Color4 EmptyColour = Color4.White.Opacity(20); @@ -174,14 +193,15 @@ namespace osu.Game.Screens.Play private readonly List drawableRows = new List(); private float filled; + public float Filled { - get { return filled; } + get => filled; set { if (value == filled) return; - filled = value; + filled = value; fillActive(); } } @@ -190,12 +210,12 @@ namespace osu.Game.Screens.Play public ColumnState State { - get { return state; } + get => state; set { if (value == state) return; - state = value; + state = value; if (IsLoaded) fillActive(); @@ -203,27 +223,30 @@ namespace osu.Game.Screens.Play } } - public Column() + public Column(float height) { Width = WIDTH; + Height = height; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load() { - for (int r = 0; r < cubeCount; r++) + drawableRows.AddRange(Enumerable.Range(0, (int)cubeCount).Select(r => new Box { - drawableRows.Add(new Box - { - Size = new Vector2(cube_size), - Position = new Vector2(0, r * WIDTH + padding), - }); - } + Size = new Vector2(cube_size), + Position = new Vector2(0, r * WIDTH + padding), + })); Children = drawableRows; // Reverse drawableRows so when iterating through them they start at the bottom drawableRows.Reverse(); + } + protected override void LoadComplete() + { + base.LoadComplete(); fillActive(); } diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs index 48b40e7ebe..84329d2a04 100644 --- a/osu.Game/Screens/Ranking/AspectContainer.cs +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Ranking/IResultPageInfo.cs b/osu.Game/Screens/Ranking/IResultPageInfo.cs index 5c6d08d883..5e0bec21f3 100644 --- a/osu.Game/Screens/Ranking/IResultPageInfo.cs +++ b/osu.Game/Screens/Ranking/IResultPageInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Graphics; diff --git a/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs b/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs index 8ab45f2f1f..c997dd6d30 100644 --- a/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs +++ b/osu.Game/Screens/Ranking/Pages/LocalLeaderboardPage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 8f5b21a7cb..043bf55d2b 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -111,8 +111,7 @@ namespace osu.Game.Screens.Ranking.Pages Origin = Anchor.TopCentre, Colour = colours.PinkDarker, Shadow = false, - Font = @"Exo2.0-Bold", - TextSize = 16, + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = "total score", Margin = new MarginPadding { Bottom = 15 }, }, @@ -214,17 +213,19 @@ namespace osu.Game.Screens.Ranking.Pages { Children = new Drawable[] { - new OsuSpriteText { + new OsuSpriteText + { Text = statistic.Value.ToString().PadLeft(4, '0'), Colour = colours.Gray7, - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, - new OsuSpriteText { + new OsuSpriteText + { Text = statistic.Key.GetDescription(), Colour = colours.Gray7, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Y = 26, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -307,24 +308,21 @@ namespace osu.Game.Screens.Ranking.Pages Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 24, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24, italics: true), }, artist = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 20, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 20, italics: true), }, versionMapper = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 16, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), }, } } @@ -338,7 +336,8 @@ namespace osu.Game.Screens.Ranking.Pages versionMapper.Colour = colours.Gray8; var creator = beatmap.Metadata.Author?.Username; - if (!string.IsNullOrEmpty(creator)) { + if (!string.IsNullOrEmpty(creator)) + { versionMapper.Text = $"mapped by {creator}"; if (!string.IsNullOrEmpty(beatmap.Version)) @@ -369,11 +368,10 @@ namespace osu.Game.Screens.Ranking.Pages }, new OsuSpriteText { - Font = @"Exo2.0-RegularItalic", - Text = user.Username, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - TextSize = 30, + Text = user.Username, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, italics: true), Padding = new MarginPadding { Bottom = 10 }, } }; @@ -393,10 +391,11 @@ namespace osu.Game.Screens.Ranking.Pages protected override Easing RollingEasing => Easing.OutPow10; - public SlowScoreCounter(uint leading = 0) : base(leading) + public SlowScoreCounter(uint leading = 0) + : base(leading) { DisplayedCountSpriteText.Shadow = false; - DisplayedCountSpriteText.Font = @"Venera-Light"; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(Typeface.Venera, weight: FontWeight.Light); UseCommaSeparator = true; } } diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index f6a886418c..b1fd8f9fde 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Ranking/ResultModeTabControl.cs b/osu.Game/Screens/Ranking/ResultModeTabControl.cs index e87749d8dd..b0d94a4be6 100644 --- a/osu.Game/Screens/Ranking/ResultModeTabControl.cs +++ b/osu.Game/Screens/Ranking/ResultModeTabControl.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index bf9e3bcd27..dafb4c0aad 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -24,6 +24,8 @@ namespace osu.Game.Screens.Ranking { public abstract class Results : OsuScreen { + protected const float BACKGROUND_BLUR = 20; + private Container circleOuterBackground; private Container circleOuter; private Container circleInner; @@ -32,14 +34,12 @@ namespace osu.Game.Screens.Ranking private ResultModeTabControl modeChangeButtons; - public override bool AllowBeatmapRulesetChange => false; + public override bool DisallowExternalBeatmapRulesetChanges => true; protected readonly ScoreInfo Score; private Container currentPage; - private static readonly Vector2 background_blur = new Vector2(20); - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); private const float overscan = 1.3f; @@ -55,10 +55,10 @@ namespace osu.Game.Screens.Ranking private IEnumerable allCircles => new Drawable[] { circleOuterBackground, circleInner, circleOuter }; - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 2500, Easing.OutQuint); + ((BackgroundScreenBeatmap)Background).BlurAmount.Value = BACKGROUND_BLUR; Background.ScaleTo(1.1f, transition_time, Easing.OutQuint); allCircles.ForEach(c => @@ -98,7 +98,7 @@ namespace osu.Game.Screens.Ranking } } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { allCircles.ForEach(c => { @@ -107,7 +107,7 @@ namespace osu.Game.Screens.Ranking Background.ScaleTo(1f, transition_time / 4, Easing.OutQuint); - Content.FadeOut(transition_time / 4); + this.FadeOut(transition_time / 4); return base.OnExiting(next); } @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Ranking [BackgroundDependencyLoader] private void load(OsuColour colours) { - Children = new Drawable[] + InternalChildren = new Drawable[] { new AspectContainer { @@ -190,45 +190,43 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, Text = $"{Score.MaxCombo}x", - TextSize = 40, RelativePositionAxes = Axes.X, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), X = 0.1f, Colour = colours.BlueDarker, - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomCentre, }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, Text = "max combo", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), RelativePositionAxes = Axes.X, X = 0.1f, Colour = colours.Gray6, - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, }, new OsuSpriteText { - Text = $"{Score.Accuracy:P2}", - TextSize = 40, - RelativePositionAxes = Axes.X, - Font = @"Exo2.0-Bold", - X = 0.9f, - Colour = colours.BlueDarker, Anchor = Anchor.CentreLeft, Origin = Anchor.BottomCentre, + Text = $"{Score.Accuracy:P2}", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), + RelativePositionAxes = Axes.X, + X = 0.9f, + Colour = colours.BlueDarker, }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, Text = "accuracy", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), RelativePositionAxes = Axes.X, X = 0.9f, Colour = colours.Gray6, - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, }, } }, @@ -260,7 +258,7 @@ namespace osu.Game.Screens.Ranking { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Action = Exit + Action = this.Exit }, }; @@ -268,12 +266,12 @@ namespace osu.Game.Screens.Ranking modeChangeButtons.AddItem(t); modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); - modeChangeButtons.Current.BindValueChanged(m => + modeChangeButtons.Current.BindValueChanged(page => { currentPage?.FadeOut(); currentPage?.Expire(); - currentPage = m?.CreatePage(); + currentPage = page.NewValue?.CreatePage(); if (currentPage != null) circleInner.Add(currentPage); diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index 08c6155557..1b17dda563 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs index 20eb75ff6f..e8a11ab1a4 100644 --- a/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/LocalLeaderboardPageInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs index 03998d2840..d8e5e9b135 100644 --- a/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs +++ b/osu.Game/Screens/Ranking/Types/ScoreOverviewPageInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Graphics; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 1131152d5f..b222b91221 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -30,7 +30,7 @@ namespace osu.Game.Screens protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg2"); - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); @@ -38,51 +38,51 @@ namespace osu.Game.Screens if (last != null) popButton.Alpha = 1; - Content.Alpha = 0; + Alpha = 0; textContainer.Position = new Vector2(DrawSize.X / 16, 0); boxContainer.ScaleTo(0.2f); boxContainer.RotateTo(-20); - using (Content.BeginDelayedSequence(300, true)) + using (BeginDelayedSequence(300, true)) { boxContainer.ScaleTo(1, transition_time, Easing.OutElastic); boxContainer.RotateTo(0, transition_time / 2, Easing.OutQuint); textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); - Content.FadeIn(transition_time, Easing.OutExpo); + this.FadeIn(transition_time, Easing.OutExpo); } } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { textContainer.MoveTo(new Vector2(DrawSize.X / 16, 0), transition_time, Easing.OutExpo); - Content.FadeOut(transition_time, Easing.OutExpo); + this.FadeOut(transition_time, Easing.OutExpo); return base.OnExiting(next); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { base.OnSuspending(next); textContainer.MoveTo(new Vector2(-(DrawSize.X / 16), 0), transition_time, Easing.OutExpo); - Content.FadeOut(transition_time, Easing.OutExpo); + this.FadeOut(transition_time, Easing.OutExpo); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { base.OnResuming(last); textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); - Content.FadeIn(transition_time, Easing.OutExpo); + this.FadeIn(transition_time, Easing.OutExpo); } public ScreenWhiteBox() { FillFlowContainer childModeButtons; - Children = new Drawable[] + InternalChildren = new Drawable[] { boxContainer = new Container { @@ -119,25 +119,25 @@ namespace osu.Game.Screens }, new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Text = GetType().Name, Colour = getColourFor(GetType()).Lighten(0.8f), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextSize = 50, + Font = OsuFont.GetFont(size: 50), }, new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Text = "is not yet ready for use!", - TextSize = 20, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 20), }, new OsuSpriteText { - Text = "please check back a bit later.", - TextSize = 14, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Text = "please check back a bit later.", + Font = OsuFont.GetFont(size: 14), }, } }, @@ -148,7 +148,7 @@ namespace osu.Game.Screens Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Alpha = 0, - Action = Exit + Action = this.Exit }, childModeButtons = new FillFlowContainer { @@ -169,10 +169,7 @@ namespace osu.Game.Screens Text = $@"{t.Name}", BackgroundColour = getColourFor(t), HoverColour = getColourFor(t).Lighten(0.2f), - Action = delegate - { - Push(Activator.CreateInstance(t) as Screen); - } + Action = delegate { this.Push(Activator.CreateInstance(t) as Screen); } }); } } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 348394c1f5..d7240a40ad 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -13,9 +13,9 @@ using osu.Framework.MathUtils; using System.Diagnostics; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Threading; -using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input.Events; using osu.Game.Beatmaps; @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select /// public BeatmapInfo SelectedBeatmap => selectedBeatmap?.Beatmap; - private CarouselBeatmap selectedBeatmap => selectedBeatmapSet?.Beatmaps.FirstOrDefault(s => s.State == CarouselItemState.Selected); + private CarouselBeatmap selectedBeatmap => selectedBeatmapSet?.Beatmaps.FirstOrDefault(s => s.State.Value == CarouselItemState.Selected); /// /// The currently selected beatmap set. @@ -55,9 +55,9 @@ namespace osu.Game.Screens.Select public override bool HandlePositionalInput => AllowSelection; /// - /// Used to avoid firing null selections before the initial beatmaps have been loaded via . + /// Whether carousel items have completed asynchronously loaded. /// - private bool initialLoadComplete; + public bool BeatmapSetsLoaded { get; private set; } private IEnumerable beatmapSets => root.Children.OfType(); @@ -90,7 +90,7 @@ namespace osu.Game.Screens.Select Schedule(() => { BeatmapSetsChanged?.Invoke(); - initialLoadComplete = true; + BeatmapSetsLoaded = true; }); })); } @@ -101,7 +101,6 @@ namespace osu.Game.Screens.Select private readonly Container scrollableContent; - public Bindable RightClickScrollingEnabled = new Bindable(); public Bindable RandomAlgorithm = new Bindable(); @@ -131,7 +130,7 @@ namespace osu.Game.Screens.Select config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm); config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled); - RightClickScrollingEnabled.ValueChanged += v => RightMouseScrollbar = v; + RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue; RightClickScrollingEnabled.TriggerChange(); } @@ -197,7 +196,7 @@ namespace osu.Game.Screens.Select foreach (CarouselBeatmapSet set in beatmapSets) { - if (!bypassFilters && set.Filtered) + if (!bypassFilters && set.Filtered.Value) continue; var item = set.Beatmaps.FirstOrDefault(p => p.Beatmap.Equals(beatmap)); @@ -206,9 +205,9 @@ namespace osu.Game.Screens.Select // The beatmap that needs to be selected doesn't exist in this set continue; - if (!bypassFilters && item.Filtered) + if (!bypassFilters && item.Filtered.Value) // The beatmap exists in this set but is filtered, so look for the first unfiltered map in the set - item = set.Beatmaps.FirstOrDefault(b => !b.Filtered); + item = set.Beatmaps.FirstOrDefault(b => !b.Filtered.Value); if (item != null) { @@ -227,7 +226,7 @@ namespace osu.Game.Screens.Select /// Whether to skip individual difficulties and only increment over full groups. public void SelectNext(int direction = 1, bool skipDifficulties = true) { - var visibleItems = Items.Where(s => !s.Item.Filtered).ToList(); + var visibleItems = Items.Where(s => !s.Item.Filtered.Value).ToList(); if (!visibleItems.Any()) return; @@ -249,19 +248,20 @@ namespace osu.Game.Screens.Select { var item = visibleItems[currentIndex].Item; - if (item.Filtered || item.State == CarouselItemState.Selected) continue; + if (item.Filtered.Value || item.State.Value == CarouselItemState.Selected) continue; switch (item) { case CarouselBeatmap beatmap: if (skipDifficulties) continue; + select(beatmap); return; case CarouselBeatmapSet set: if (skipDifficulties) select(set); else - select(direction > 0 ? set.Beatmaps.First(b => !b.Filtered) : set.Beatmaps.Last(b => !b.Filtered)); + select(direction > 0 ? set.Beatmaps.First(b => !b.Filtered.Value) : set.Beatmaps.Last(b => !b.Filtered.Value)); return; } } @@ -273,7 +273,7 @@ namespace osu.Game.Screens.Select /// True if a selection could be made, else False. public bool SelectNextRandom() { - var visibleSets = beatmapSets.Where(s => !s.Filtered).ToList(); + var visibleSets = beatmapSets.Where(s => !s.Filtered.Value).ToList(); if (!visibleSets.Any()) return false; @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Select CarouselBeatmapSet set; - if (RandomAlgorithm == RandomSelectAlgorithm.RandomPermutation) + if (RandomAlgorithm.Value == RandomSelectAlgorithm.RandomPermutation) { var notYetVisitedSets = visibleSets.Except(previouslyVisitedRandomSets).ToList(); if (!notYetVisitedSets.Any()) @@ -304,7 +304,7 @@ namespace osu.Game.Screens.Select else set = visibleSets.ElementAt(RNG.Next(visibleSets.Count)); - var visibleBeatmaps = set.Beatmaps.Where(s => !s.Filtered).ToList(); + var visibleBeatmaps = set.Beatmaps.Where(s => !s.Filtered.Value).ToList(); select(visibleBeatmaps[RNG.Next(visibleBeatmaps.Count)]); return true; } @@ -315,9 +315,9 @@ namespace osu.Game.Screens.Select { var beatmap = randomSelectedBeatmaps.Pop(); - if (!beatmap.Filtered) + if (!beatmap.Filtered.Value) { - if (RandomAlgorithm == RandomSelectAlgorithm.RandomPermutation) + if (RandomAlgorithm.Value == RandomSelectAlgorithm.RandomPermutation) previouslyVisitedRandomSets.Remove(selectedBeatmapSet); select(beatmap); break; @@ -327,7 +327,11 @@ namespace osu.Game.Screens.Select private void select(CarouselItem item) { + if (!AllowSelection) + return; + if (item == null) return; + item.State.Value = CarouselItemState.Selected; } @@ -510,9 +514,9 @@ namespace osu.Game.Screens.Select foreach (var c in set.Beatmaps) { - c.State.ValueChanged += v => + c.State.ValueChanged += state => { - if (v == CarouselItemState.Selected) + if (state.NewValue == CarouselItemState.Selected) { selectedBeatmapSet = set; SelectionChanged?.Invoke(c.Beatmap); @@ -550,7 +554,7 @@ namespace osu.Game.Screens.Select case DrawableCarouselBeatmapSet set: lastSet = set; - set.MoveToX(set.Item.State == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); + set.MoveToX(set.Item.State.Value == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); set.MoveToY(currentY, 750, Easing.OutExpo); break; case DrawableCarouselBeatmap beatmap: @@ -560,7 +564,7 @@ namespace osu.Game.Screens.Select void performMove(float y, float? startY = null) { if (startY != null) beatmap.MoveTo(new Vector2(0, startY.Value)); - beatmap.MoveToX(beatmap.Item.State == CarouselItemState.Selected ? -50 : 0, 500, Easing.OutExpo); + beatmap.MoveToX(beatmap.Item.State.Value == CarouselItemState.Selected ? -50 : 0, 500, Easing.OutExpo); beatmap.MoveToY(y, 750, Easing.OutExpo); } @@ -576,7 +580,7 @@ namespace osu.Game.Screens.Select else { float y = currentY; - d.OnLoadComplete = _ => performMove(y, setY); + d.OnLoadComplete += _ => performMove(y, setY); } break; @@ -592,7 +596,7 @@ namespace osu.Game.Screens.Select currentY += DrawHeight / 2; scrollableContent.Height = currentY; - if (initialLoadComplete && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) + if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)) { selectedBeatmapSet = null; SelectionChanged?.Invoke(null); diff --git a/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs new file mode 100644 index 0000000000..a37327f2c3 --- /dev/null +++ b/osu.Game/Screens/Select/BeatmapClearScoresDialog.cs @@ -0,0 +1,48 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Overlays.Dialog; +using osu.Game.Scoring; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace osu.Game.Screens.Select +{ + public class BeatmapClearScoresDialog : PopupDialog + { + private ScoreManager scoreManager; + + public BeatmapClearScoresDialog(BeatmapInfo beatmap, Action onCompletion) + { + BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}"; + Icon = FontAwesome.fa_eraser; + HeaderText = @"Clearing all local scores. Are you sure?"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Please.", + Action = () => + { + Task.Run(() => scoreManager.Delete(scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == beatmap.ID).ToList())) + .ContinueWith(_ => onCompletion); + } + }, + new PopupDialogCancelButton + { + Text = @"No, I'm still attached.", + }, + }; + } + + [BackgroundDependencyLoader] + private void load(ScoreManager scoreManager) + { + this.scoreManager = scoreManager; + } + } +} diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index bf7ed73f39..f2c1940ed8 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index c5c4960ed4..477037355c 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; @@ -20,12 +20,10 @@ namespace osu.Game.Screens.Select public readonly BeatmapLeaderboard Leaderboard; private WorkingBeatmap beatmap; + public WorkingBeatmap Beatmap { - get - { - return beatmap; - } + get => beatmap; set { beatmap = value; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index e18b70a0e0..f66cd2b29a 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Select private void invokeOnFilter() { - OnFilter?.Invoke(tabs.Current, modsCheckbox.Current); + OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); } [BackgroundDependencyLoader] @@ -69,8 +69,8 @@ namespace osu.Game.Screens.Select }, }; - tabs.Current.ValueChanged += item => invokeOnFilter(); - modsCheckbox.Current.ValueChanged += item => invokeOnFilter(); + tabs.Current.ValueChanged += _ => invokeOnFilter(); + modsCheckbox.Current.ValueChanged += _ => invokeOnFilter(); } } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 9b87bbaa7b..a78ab97960 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Screens.Select.Details; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select @@ -35,17 +36,19 @@ namespace osu.Game.Screens.Select private readonly FailRetryGraph failRetryGraph; private readonly DimmedLoadingAnimation loading; - private APIAccess api; + private IAPIProvider api; private ScheduledDelegate pendingBeatmapSwitch; private BeatmapInfo beatmap; + public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (value == beatmap) return; + beatmap = value; pendingBeatmapSwitch?.Cancel(); @@ -115,6 +118,7 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, LayoutDuration = transition_duration, + LayoutEasing = Easing.OutQuad, Spacing = new Vector2(spacing * 2), Margin = new MarginPadding { Top = spacing * 2 }, Children = new[] @@ -137,8 +141,7 @@ namespace osu.Game.Screens.Select new OsuSpriteText { Text = "Points of Failure", - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, failRetryGraph = new FailRetryGraph { @@ -157,7 +160,7 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader] - private void load(APIAccess api) + private void load(IAPIProvider api) { this.api = api; } @@ -172,21 +175,22 @@ namespace osu.Game.Screens.Select private void updateStatistics() { - if (Beatmap == null) + advanced.Beatmap = Beatmap; + description.Text = Beatmap?.Version; + source.Text = Beatmap?.Metadata?.Source; + tags.Text = Beatmap?.Metadata?.Tags; + + // metrics may have been previously fetched + if (Beatmap?.Metrics != null) { - clearStats(); + updateMetrics(Beatmap.Metrics); return; } - ratingsContainer.FadeIn(transition_duration); - advanced.Beatmap = Beatmap; - description.Text = Beatmap.Version; - source.Text = Beatmap.Metadata.Source; - tags.Text = Beatmap.Metadata.Tags; - - var requestedBeatmap = Beatmap; - if (requestedBeatmap.Metrics == null) + // metrics may not be fetched but can be + if (Beatmap?.OnlineBeatmapID != null) { + var requestedBeatmap = Beatmap; var lookup = new GetBeatmapDetailsRequest(requestedBeatmap); lookup.Success += res => { @@ -195,39 +199,34 @@ namespace osu.Game.Screens.Select return; requestedBeatmap.Metrics = res; - Schedule(() => displayMetrics(res)); + Schedule(() => updateMetrics(res)); }; - lookup.Failure += e => Schedule(() => displayMetrics(null)); - + lookup.Failure += e => Schedule(() => updateMetrics()); api.Queue(lookup); loading.Show(); + return; } - displayMetrics(requestedBeatmap.Metrics, false); + updateMetrics(); } - private void displayMetrics(BeatmapMetrics metrics, bool failOnMissing = true) + private void updateMetrics(BeatmapMetrics metrics = null) { var hasRatings = metrics?.Ratings?.Any() ?? false; var hasRetriesFails = (metrics?.Retries?.Any() ?? false) && (metrics.Fails?.Any() ?? false); - if (failOnMissing) loading.Hide(); - if (hasRatings) { ratings.Metrics = metrics; - ratings.FadeIn(transition_duration); + ratingsContainer.FadeIn(transition_duration); } - else if (failOnMissing) + else { ratings.Metrics = new BeatmapMetrics { Ratings = new int[10], }; - } - else - { - ratings.FadeTo(0.25f, transition_duration); + ratingsContainer.FadeTo(0.25f, transition_duration); } if (hasRetriesFails) @@ -235,41 +234,17 @@ namespace osu.Game.Screens.Select failRetryGraph.Metrics = metrics; failRetryContainer.FadeIn(transition_duration); } - else if (failOnMissing) + else { failRetryGraph.Metrics = new BeatmapMetrics { Fails = new int[100], Retries = new int[100], }; + failRetryContainer.FadeOut(transition_duration); } - else - { - failRetryContainer.FadeTo(0.25f, transition_duration); - } - } - - private void clearStats() - { - description.Text = null; - source.Text = null; - tags.Text = null; - - advanced.Beatmap = new BeatmapInfo - { - StarDifficulty = 0, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 0, - DrainRate = 0, - OverallDifficulty = 0, - ApproachRate = 0, - }, - }; loading.Hide(); - ratingsContainer.FadeOut(transition_duration); - failRetryContainer.FadeOut(transition_duration); } private class DetailBox : Container @@ -323,8 +298,7 @@ namespace osu.Game.Screens.Select Child = new OsuSpriteText { Text = title, - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, }, }, @@ -337,17 +311,19 @@ namespace osu.Game.Screens.Select { if (string.IsNullOrEmpty(value)) { - textContainer.FadeOut(transition_duration); + this.FadeOut(transition_duration); return; } + this.FadeIn(transition_duration); + setTextAsync(value); } } private void setTextAsync(string text) { - LoadComponentAsync(new OsuTextFlowContainer(s => s.TextSize = 14) + LoadComponentAsync(new OsuTextFlowContainer(s => s.Font = s.Font.With(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c72701d3cb..32e7215e69 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using JetBrains.Annotations; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -203,9 +203,8 @@ namespace osu.Game.Screens.Select { VersionLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", Text = beatmapInfo.Version, - TextSize = 24, + Font = OsuFont.GetFont(size: 24, italics: true), }, } }, @@ -240,13 +239,11 @@ namespace osu.Game.Screens.Select { TitleLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", - TextSize = 28, + Font = OsuFont.GetFont(size: 28, italics: true), }, ArtistLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", - TextSize = 17, + Font = OsuFont.GetFont(size: 17, italics: true), }, MapperContainer = new FillFlowContainer { @@ -266,8 +263,8 @@ namespace osu.Game.Screens.Select } }; - titleBinding.BindValueChanged(value => setMetadata(metadata.Source)); - artistBinding.BindValueChanged(value => setMetadata(metadata.Source), true); + titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); + artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) @@ -345,16 +342,13 @@ namespace osu.Game.Screens.Select { new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = "mapped by ", - TextSize = 15, + Font = OsuFont.GetFont(size: 15), }, new OsuSpriteText { - Font = @"Exo2.0-Bold", - // ReSharper disable once PossibleNullReferenceException (resharper broken?) Text = metadata.Author.Username, - TextSize = 15, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15), } }; } @@ -402,10 +396,9 @@ namespace osu.Game.Screens.Select Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Colour = new Color4(255, 221, 85, 255), - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = 30 }, Text = statistic.Content, - TextSize = 17, } }; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 49779f5e11..712ab7b571 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 246e634b74..8e7ea8f964 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel public override void Filter(FilterCriteria criteria) { base.Filter(criteria); - Filtered.Value = InternalChildren.All(i => i.Filtered); + Filtered.Value = InternalChildren.All(i => i.Filtered.Value); } public override string ToString() => BeatmapSet.ToString(); diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index ea461e7bd5..5d8f4f0ec6 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.Carousel public virtual void AddChild(CarouselItem i) { - i.State.ValueChanged += v => ChildItemStateChanged(i, v); + i.State.ValueChanged += state => ChildItemStateChanged(i, state.NewValue); i.ChildID = ++currentChildID; InternalChildren.Add(i); } @@ -58,9 +58,9 @@ namespace osu.Game.Screens.Select.Carousel { if (items != null) InternalChildren = items; - State.ValueChanged += v => + State.ValueChanged += state => { - switch (v) + switch (state.NewValue) { case CarouselItemState.Collapsed: case CarouselItemState.NotSelected: @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select.Carousel case CarouselItemState.Selected: InternalChildren.ForEach(c => { - if (c.State == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected; + if (c.State.Value == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected; }); break; } @@ -96,6 +96,7 @@ namespace osu.Game.Screens.Select.Carousel foreach (var b in InternalChildren) { if (item == b) continue; + b.State.Value = CarouselItemState.NotSelected; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index 0ac869f484..67e8282b76 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -13,9 +13,9 @@ namespace osu.Game.Screens.Select.Carousel { public CarouselGroupEagerSelect() { - State.ValueChanged += v => + State.ValueChanged += state => { - if (v == CarouselItemState.Selected) + if (state.NewValue == CarouselItemState.Selected) attemptSelection(); }; } @@ -81,10 +81,10 @@ namespace osu.Game.Screens.Select.Carousel if (filteringChildren) return; // we only perform eager selection if we are a currently selected group. - if (State != CarouselItemState.Selected) return; + if (State.Value != CarouselItemState.Selected) return; // we only perform eager selection if none of our children are in a selected state already. - if (Children.Any(i => i.State == CarouselItemState.Selected)) return; + if (Children.Any(i => i.State.Value == CarouselItemState.Selected)) return; PerformSelection(); } @@ -92,8 +92,8 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void PerformSelection() { CarouselItem nextToSelect = - Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered) ?? - Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered); + Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value) ?? + Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value); if (nextToSelect != null) nextToSelect.State.Value = CarouselItemState.Selected; diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index c0781f09c0..a0f5969b3c 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Select.Carousel { @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// This item is not in a hidden state. /// - public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered; + public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered.Value; public virtual List Drawables { @@ -37,9 +37,9 @@ namespace osu.Game.Screens.Select.Carousel { DrawableRepresentation = new Lazy(CreateDrawableRepresentation); - Filtered.ValueChanged += v => + Filtered.ValueChanged += filtered => { - if (v && State == CarouselItemState.Selected) + if (filtered.NewValue && State.Value == CarouselItemState.Selected) State.Value = CarouselItemState.NotSelected; }; } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 8216fc0e33..38ca9a9aed 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; @@ -38,7 +38,8 @@ namespace osu.Game.Screens.Select.Carousel private BeatmapSetOverlay beatmapOverlay; - public DrawableCarouselBeatmap(CarouselBeatmap panel) : base(panel) + public DrawableCarouselBeatmap(CarouselBeatmap panel) + : base(panel) { beatmap = panel.Beatmap; Height *= 0.60f; @@ -100,25 +101,21 @@ namespace osu.Game.Screens.Select.Carousel { new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = beatmap.Version, - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = "mapped by", - TextSize = 16, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", Text = $"{(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author.Username}", - TextSize = 16, + Font = OsuFont.GetFont(italics: true), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, @@ -157,7 +154,7 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { - if (Item.State == CarouselItemState.Selected) + if (Item.State.Value == CarouselItemState.Selected) startRequested?.Invoke(beatmap); return base.OnClick(e); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 2e5f01fe29..51ca9902d2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -15,6 +15,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; @@ -48,10 +49,15 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { new DelayedLoadUnloadWrapper(() => - new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { - RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint), + var background = new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) + { + RelativeSizeAxes = Axes.Both, + }; + + background.OnLoadComplete += d => d.FadeInFromZero(1000, Easing.OutQuint); + + return background; }, 300, 5000 ), new FillFlowContainer @@ -63,16 +69,14 @@ namespace osu.Game.Screens.Select.Carousel { new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", Text = new LocalisedString((beatmapSet.Metadata.TitleUnicode, beatmapSet.Metadata.Title)), - TextSize = 22, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true), Shadow = true, }, new OsuSpriteText { - Font = @"Exo2.0-SemiBoldItalic", Text = new LocalisedString((beatmapSet.Metadata.ArtistUnicode, beatmapSet.Metadata.Artist)), - TextSize = 17, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true), Shadow = true, }, new FillFlowContainer @@ -109,7 +113,7 @@ namespace osu.Game.Screens.Select.Carousel { List items = new List(); - if (Item.State == CarouselItemState.NotSelected) + if (Item.State.Value == CarouselItemState.NotSelected) items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => Item.State.Value = CarouselItemState.Selected)); if (beatmapSet.OnlineBeatmapSetID != null) @@ -189,7 +193,7 @@ namespace osu.Game.Screens.Select.Carousel : base(item.Beatmap) { filtered.BindTo(item.Filtered); - filtered.ValueChanged += v => Schedule(() => this.FadeTo(v ? 0.1f : 1, 100)); + filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); } } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 3ec980602d..3c1b7cc831 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Audio; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 88fd9ca032..52a57dd506 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; @@ -20,12 +20,14 @@ namespace osu.Game.Screens.Select.Details private readonly StatisticRow firstValue, hpDrain, accuracy, approachRate, starDifficulty; private BeatmapInfo beatmap; + public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (value == beatmap) return; + beatmap = value; //mania specific @@ -83,14 +85,15 @@ namespace osu.Game.Screens.Select.Details public string Title { - get { return name.Text; } - set { name.Text = value; } + get => name.Text; + set => name.Text = value; } private float difficultyValue; + public float Value { - get { return difficultyValue; } + get => difficultyValue; set { difficultyValue = value; @@ -101,8 +104,8 @@ namespace osu.Game.Screens.Select.Details public Color4 AccentColour { - get { return bar.AccentColour; } - set { bar.AccentColour = value; } + get => bar.AccentColour; + set => bar.AccentColour = value; } public StatisticRow(float maxValue = 10, bool forceDecimalPlaces = false) @@ -120,7 +123,7 @@ namespace osu.Game.Screens.Select.Details AutoSizeAxes = Axes.Y, Child = name = new OsuSpriteText { - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, bar = new Bar @@ -142,7 +145,7 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, }; diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index b5a6a26807..34297d89a4 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -17,12 +17,14 @@ namespace osu.Game.Screens.Select.Details private readonly BarGraph retryGraph, failGraph; private BeatmapMetrics metrics; + public BeatmapMetrics Metrics { - get { return metrics; } + get => metrics; set { if (value == metrics) return; + metrics = value; var retries = Metrics?.Retries ?? new int[0]; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index 787b22f965..b17a3f79e9 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -24,10 +24,11 @@ namespace osu.Game.Screens.Select.Details public BeatmapMetrics Metrics { - get { return metrics; } + get => metrics; set { if (value == metrics) return; + metrics = value; const int rating_range = 10; @@ -70,7 +71,7 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "User Rating", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, ratingsBar = new Bar { @@ -87,14 +88,14 @@ namespace osu.Game.Screens.Select.Details negativeRatings = new OsuSpriteText { Text = "0", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, positiveRatings = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Text = @"0", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, }, @@ -103,7 +104,7 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Rating Spread", - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Margin = new MarginPadding { Top = 10, Bottom = 5 }, }, }, diff --git a/osu.Game/Screens/Select/EditSongSelect.cs b/osu.Game/Screens/Select/EditSongSelect.cs index e1d71fdd05..bdf5f905fe 100644 --- a/osu.Game/Screens/Select/EditSongSelect.cs +++ b/osu.Game/Screens/Select/EditSongSelect.cs @@ -1,5 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Screens; namespace osu.Game.Screens.Select { @@ -9,7 +11,7 @@ namespace osu.Game.Screens.Select protected override bool OnStart() { - Exit(); + this.Exit(); return true; } } diff --git a/osu.Game/Screens/Select/Filter/GroupMode.cs b/osu.Game/Screens/Select/Filter/GroupMode.cs index b3bd73ee59..d794c215a3 100644 --- a/osu.Game/Screens/Select/Filter/GroupMode.cs +++ b/osu.Game/Screens/Select/Filter/GroupMode.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,32 +9,46 @@ namespace osu.Game.Screens.Select.Filter { [Description("All")] All, + [Description("Artist")] Artist, + [Description("Author")] Author, + [Description("BPM")] BPM, + [Description("Collections")] Collections, + [Description("Date Added")] DateAdded, + [Description("Difficulty")] Difficulty, + [Description("Favourites")] Favourites, + [Description("Length")] Length, + [Description("My Maps")] MyMaps, + [Description("No Grouping")] NoGrouping, + [Description("Rank Achieved")] RankAchieved, + [Description("Ranked Status")] RankedStatus, + [Description("Recently Played")] RecentlyPlayed, + [Description("Title")] Title } diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index f38b0c89ef..be76fbc3ba 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel; @@ -9,18 +9,25 @@ namespace osu.Game.Screens.Select.Filter { [Description("Artist")] Artist, + [Description("Author")] Author, + [Description("BPM")] BPM, + [Description("Date Added")] DateAdded, + [Description("Difficulty")] Difficulty, + [Description("Length")] Length, + [Description("Rank Achieved")] RankAchieved, + [Description("Title")] Title } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index faffdbf31a..bd0b0dd5cd 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Select public SortMode Sort { - get { return sort; } + get => sort; set { if (sort != value) @@ -47,7 +47,7 @@ namespace osu.Game.Screens.Select public GroupMode Group { - get { return group; } + get => group; set { if (group != value) @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Select Group = group, Sort = sort, SearchText = searchTextBox.Text, - AllowConvertedBeatmaps = showConverted, + AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value }; @@ -146,12 +146,12 @@ namespace osu.Game.Screens.Select } }; - searchTextBox.Current.ValueChanged += t => FilterChanged?.Invoke(CreateCriteria()); + searchTextBox.Current.ValueChanged += _ => FilterChanged?.Invoke(CreateCriteria()); groupTabs.PinItem(GroupMode.All); groupTabs.PinItem(GroupMode.RecentlyPlayed); - groupTabs.Current.ValueChanged += val => Group = val; - sortTabs.Current.ValueChanged += val => Sort = val; + groupTabs.Current.ValueChanged += group => Group = group.NewValue; + sortTabs.Current.ValueChanged += sort => Sort = sort.NewValue; } public void Deactivate() @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Select sortTabs.AccentColour = colours.GreenLight; showConverted = config.GetBindable(OsuSetting.ShowConvertedBeatmaps); - showConverted.ValueChanged += val => updateCriteria(); + showConverted.ValueChanged += _ => updateCriteria(); ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria(), true); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 71cfedfdbf..140010ff54 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Select public string SearchText { - get { return searchText; } + get => searchText; set { searchText = value; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index c4123884e0..03b9826e9b 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 3c32c18f05..9b98e344ce 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Select public string Text { - get { return spriteText?.Text; } + get => spriteText?.Text; set { if (spriteText != null) @@ -29,9 +29,10 @@ namespace osu.Game.Screens.Select } private Color4 deselectedColour; + public Color4 DeselectedColour { - get { return deselectedColour; } + get => deselectedColour; set { deselectedColour = value; @@ -41,9 +42,10 @@ namespace osu.Game.Screens.Select } private Color4 selectedColour; + public Color4 SelectedColour { - get { return selectedColour; } + get => selectedColour; set { selectedColour = value; diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs index a52b5bab2a..537736a4ec 100644 --- a/osu.Game/Screens/Select/ImportFromStablePopup.cs +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 9f8726c86a..ebb1d78ba0 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select.Leaderboards public BeatmapInfo Beatmap { - get { return beatmap; } + get => beatmap; set { if (beatmap == value) @@ -43,7 +43,7 @@ namespace osu.Game.Screens.Select.Leaderboards private IBindable ruleset { get; set; } [Resolved] - private APIAccess api { get; set; } + private IAPIProvider api { get; set; } [BackgroundDependencyLoader] private void load() @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select.Leaderboards { if (Scope == BeatmapLeaderboardScope.Local) { - Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray(); + Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).ToArray(); PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; return null; } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs index 39d9580792..9e480b61c6 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboardScope.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 5763b84e89..fa5dc4c1d1 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -1,9 +1,17 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; +using System.Linq; using Humanizer; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi; namespace osu.Game.Screens.Select @@ -15,6 +23,20 @@ namespace osu.Game.Screens.Select public string ShortTitle => "song selection"; public override string Title => ShortTitle.Humanize(); + [Resolved(typeof(Room))] + protected Bindable CurrentItem { get; private set; } + + [Resolved] + private Bindable> selectedMods { get; set; } + + [Resolved] + private BeatmapManager beatmaps { get; set; } + + public MatchSongSelect() + { + Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; + } + protected override bool OnStart() { var item = new PlaylistItem @@ -28,10 +50,36 @@ namespace osu.Game.Screens.Select Selected?.Invoke(item); - if (IsCurrentScreen) - Exit(); + if (this.IsCurrentScreen()) + this.Exit(); return true; } + + public override bool OnExiting(IScreen next) + { + if (base.OnExiting(next)) + return true; + + if (CurrentItem.Value != null) + { + Ruleset.Value = CurrentItem.Value.Ruleset; + Beatmap.Value = beatmaps.GetWorkingBeatmap(CurrentItem.Value.Beatmap); + Beatmap.Value.Mods.Value = selectedMods.Value = CurrentItem.Value.RequiredMods ?? Enumerable.Empty(); + } + + Beatmap.Disabled = true; + Ruleset.Disabled = true; + + return false; + } + + public override void OnEntering(IScreen last) + { + base.OnEntering(last); + + Beatmap.Disabled = false; + Ruleset.Disabled = false; + } } } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 9659d537f1..758e1c24c3 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -28,26 +28,26 @@ namespace osu.Game.Screens.Select.Options public Color4 ButtonColour { - get { return background.Colour; } - set { background.Colour = value; } + get => background.Colour; + set => background.Colour = value; } public FontAwesome Icon { - get { return iconText.Icon; } - set { iconText.Icon = value; } + get => iconText.Icon; + set => iconText.Icon = value; } public string FirstLineText { - get { return firstLine.Text; } - set { firstLine.Text = value; } + get => firstLine.Text; + set => firstLine.Text = value; } public string SecondLineText { - get { return secondLine.Text; } - set { secondLine.Text = value; } + get => secondLine.Text; + set => secondLine.Text = value; } public Key? HotKey; @@ -150,14 +150,14 @@ namespace osu.Game.Screens.Select.Options { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = @"", }, secondLine = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = @"", }, }, diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index dcadefebae..5fedb2f8cc 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index a7de93b11d..d06436c92e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Linq; using osu.Framework.Allocation; @@ -15,6 +15,8 @@ namespace osu.Game.Screens.Select private bool removeAutoModOnResume; private OsuScreen player; + public override bool AllowExternalScreenChange => true; + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -25,7 +27,7 @@ namespace osu.Game.Screens.Select }, Key.Number3); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { player = null; @@ -58,13 +60,12 @@ namespace osu.Game.Screens.Select } Beatmap.Value.Track.Looping = false; - Beatmap.Disabled = true; SampleConfirm?.Play(); LoadComponentAsync(player = new PlayerLoader(() => new Player()), l => { - if (IsCurrentScreen) Push(player); + if (this.IsCurrentScreen()) this.Push(player); }); return true; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index f65cc0e49d..8758df5151 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -1,20 +1,15 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; -using System.Linq; -using osuTK; -using osuTK.Input; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Logging; using osu.Framework.Input.Events; +using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; @@ -31,21 +26,25 @@ using osu.Game.Screens.Menu; using osu.Game.Screens.Play; using osu.Game.Screens.Select.Options; using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; +using osuTK.Input; +using System; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen { private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); - private static readonly Vector2 background_blur = new Vector2(20); + protected const float BACKGROUND_BLUR = 20; private const float left_area_padding = 20; public readonly FilterControl FilterControl; protected virtual bool ShowFooter => true; - public override bool AllowExternalScreenChange => true; - /// /// Can be null if is false. /// @@ -62,7 +61,11 @@ namespace osu.Game.Screens.Select /// protected readonly Container FooterPanels; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); + protected override BackgroundScreen CreateBackground() + { + var background = new BackgroundScreenBeatmap(); + return background; + } protected readonly BeatmapCarousel Carousel; private readonly BeatmapInfoWedge beatmapInfoWedge; @@ -77,7 +80,7 @@ namespace osu.Game.Screens.Select protected readonly BeatmapDetailArea BeatmapDetails; - protected new readonly Bindable Ruleset = new Bindable(); + private readonly Bindable decoupledRuleset = new Bindable(); [Cached] [Cached(Type = typeof(IBindable>))] @@ -88,7 +91,7 @@ namespace osu.Game.Screens.Select const float carousel_width = 640; const float filter_height = 100; - AddRange(new Drawable[] + AddRangeInternal(new Drawable[] { new ParallaxContainer { @@ -156,8 +159,8 @@ namespace osu.Game.Screens.Select Background = { Width = 2 }, Exit = () => { - if (IsCurrentScreen) - Exit(); + if (this.IsCurrentScreen()) + this.Exit(); }, }, } @@ -182,7 +185,7 @@ namespace osu.Game.Screens.Select if (ShowFooter) { - Add(FooterPanels = new Container + AddInternal(FooterPanels = new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -193,7 +196,7 @@ namespace osu.Game.Screens.Select Bottom = Footer.HEIGHT, }, }); - Add(Footer = new Footer + AddInternal(Footer = new Footer { OnBack = ExitFromBack, }); @@ -210,7 +213,7 @@ namespace osu.Game.Screens.Select }); } - BeatmapDetails.Leaderboard.ScoreSelected += s => Push(new SoloResults(s)); + BeatmapDetails.Leaderboard.ScoreSelected += s => this.Push(new SoloResults(s)); } [BackgroundDependencyLoader(true)] @@ -227,7 +230,7 @@ namespace osu.Game.Screens.Select BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.fa_trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1); - BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, null, Key.Number2); + BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2); } if (this.beatmaps == null) @@ -267,8 +270,8 @@ namespace osu.Game.Screens.Select { dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); dependencies.CacheAs(this); - dependencies.CacheAs(Ruleset); - dependencies.CacheAs>(Ruleset); + dependencies.CacheAs(decoupledRuleset); + dependencies.CacheAs>(decoupledRuleset); return dependencies; } @@ -281,13 +284,13 @@ namespace osu.Game.Screens.Select return; } - Exit(); + this.Exit(); } public void Edit(BeatmapInfo beatmap = null) { Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap ?? beatmapNoDebounce); - Push(new Editor()); + this.Push(new Editor()); } /// @@ -297,14 +300,18 @@ namespace osu.Game.Screens.Select /// Whether to trigger . public void FinaliseSelection(BeatmapInfo beatmap = null, bool performStartAction = true) { - // avoid attempting to continue before a selection has been obtained. - // this could happen via a user interaction while the carousel is still in a loading state. - if (Carousel.SelectedBeatmap == null) return; + // This is very important as we have not yet bound to screen-level bindables before the carousel load is completed. + if (!Carousel.BeatmapSetsLoaded) + return; // if we have a pending filter operation, we want to run it now. // it could change selection (ie. if the ruleset has been changed). Carousel.FlushPendingFilterOperations(); + // avoid attempting to continue before a selection has been obtained. + // this could happen via a user interaction while the carousel is still in a loading state. + if (Carousel.SelectedBeatmap == null) return; + if (beatmap != null) Carousel.SelectBeatmap(beatmap); @@ -327,16 +334,16 @@ namespace osu.Game.Screens.Select private ScheduledDelegate selectionChangedDebounce; - private void workingBeatmapChanged(WorkingBeatmap beatmap) + private void workingBeatmapChanged(ValueChangedEvent e) { - if (beatmap is DummyWorkingBeatmap) return; + if (e.NewValue is DummyWorkingBeatmap) return; - if (IsCurrentScreen && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false)) + if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch - if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value) + if (e.NewValue?.BeatmapInfo?.Ruleset != null && e.NewValue.BeatmapInfo.Ruleset != decoupledRuleset.Value) { - base.Ruleset.Value = beatmap.BeatmapInfo.Ruleset; - Carousel.SelectBeatmap(beatmap.BeatmapInfo); + Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; + Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); } } @@ -370,18 +377,25 @@ namespace osu.Game.Screens.Select var beatmap = beatmapNoDebounce; var ruleset = rulesetNoDebounce; + selectionChangedDebounce?.Cancel(); + + if (beatmap == null) + run(); + else + selectionChangedDebounce = Scheduler.AddDelayed(run, 200); + void run() { Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}"); bool preview = false; - if (ruleset?.Equals(Ruleset.Value) == false) + if (ruleset?.Equals(decoupledRuleset.Value) == false) { - Logger.Log($"ruleset changed from \"{Ruleset.Value}\" to \"{ruleset}\""); + Logger.Log($"ruleset changed from \"{decoupledRuleset.Value}\" to \"{ruleset}\""); Beatmap.Value.Mods.Value = Enumerable.Empty(); - Ruleset.Value = ruleset; + decoupledRuleset.Value = ruleset; // force a filter before attempting to change the beatmap. // we may still be in the wrong ruleset as there is a debounce delay on ruleset changes. @@ -411,16 +425,9 @@ namespace osu.Game.Screens.Select } } - if (IsCurrentScreen) ensurePlayingSelected(preview); + if (this.IsCurrentScreen()) ensurePlayingSelected(preview); UpdateBeatmap(Beatmap.Value); } - - selectionChangedDebounce?.Cancel(); - - if (beatmap == null) - run(); - else - selectionChangedDebounce = Scheduler.AddDelayed(run, 200); } private void triggerRandom() @@ -431,11 +438,11 @@ namespace osu.Game.Screens.Select Carousel.SelectNextRandom(); } - protected override void OnEntering(Screen last) + public override void OnEntering(IScreen last) { base.OnEntering(last); - Content.FadeInFromZero(250); + this.FadeInFromZero(250); FilterControl.Activate(); } @@ -445,7 +452,6 @@ namespace osu.Game.Screens.Select { base.LogoArriving(logo, resuming); - logo.RelativePositionAxes = Axes.Both; Vector2 position = new Vector2(0.95f, 0.96f); if (logo.Alpha > 0.8f) @@ -476,7 +482,7 @@ namespace osu.Game.Screens.Select logo.FadeOut(logo_transition / 2, Easing.Out); } - protected override void OnResuming(Screen last) + public override void OnResuming(IScreen last) { BeatmapDetails.Leaderboard.RefreshScores(); @@ -490,38 +496,33 @@ namespace osu.Game.Screens.Select base.OnResuming(last); - Content.FadeIn(250); + this.FadeIn(250); - Content.ScaleTo(1, 250, Easing.OutSine); + this.ScaleTo(1, 250, Easing.OutSine); FilterControl.Activate(); } - protected override void OnSuspending(Screen next) + public override void OnSuspending(IScreen next) { ModSelect.Hide(); - Content.ScaleTo(1.1f, 250, Easing.InSine); + this.ScaleTo(1.1f, 250, Easing.InSine); - Content.FadeOut(250); + this.FadeOut(250); FilterControl.Deactivate(); base.OnSuspending(next); } - protected override bool OnExiting(Screen next) + public override bool OnExiting(IScreen next) { - if (ModSelect.State == Visibility.Visible) - { - ModSelect.Hide(); + if (base.OnExiting(next)) return true; - } - - FinaliseSelection(performStartAction: false); beatmapInfoWedge.State = Visibility.Hidden; - Content.FadeOut(100); + this.FadeOut(100); FilterControl.Deactivate(); @@ -531,14 +532,14 @@ namespace osu.Game.Screens.Select SelectedMods.UnbindAll(); Beatmap.Value.Mods.Value = new Mod[] { }; - return base.OnExiting(next); + return false; } protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - Ruleset.UnbindAll(); + decoupledRuleset.UnbindAll(); if (beatmaps != null) { @@ -563,8 +564,8 @@ namespace osu.Game.Screens.Select if (Background is BackgroundScreenBeatmap backgroundModeBeatmap) { backgroundModeBeatmap.Beatmap = beatmap; - backgroundModeBeatmap.BlurTo(background_blur, 750, Easing.OutQuint); - backgroundModeBeatmap.FadeTo(1, 250); + backgroundModeBeatmap.BlurAmount.Value = BACKGROUND_BLUR; + backgroundModeBeatmap.FadeColour(Color4.White, 250); } beatmapInfoWedge.Beatmap = beatmap; @@ -589,23 +590,14 @@ namespace osu.Game.Screens.Select } } - private void onBeatmapSetAdded(BeatmapSetInfo s, bool existing, bool silent) => Carousel.UpdateBeatmapSet(s); + private void onBeatmapSetAdded(BeatmapSetInfo s, bool existing) => Carousel.UpdateBeatmapSet(s); private void onBeatmapSetRemoved(BeatmapSetInfo s) => Carousel.RemoveBeatmapSet(s); private void onBeatmapRestored(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); private void onBeatmapHidden(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID)); private void carouselBeatmapsLoaded() { - if (rulesetNoDebounce == null) - { - // manual binding to parent ruleset to allow for delayed load in the incoming direction. - rulesetNoDebounce = Ruleset.Value = base.Ruleset.Value; - base.Ruleset.ValueChanged += updateSelectedRuleset; - Ruleset.ValueChanged += r => base.Ruleset.Value = r; - - Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true); - Beatmap.BindValueChanged(workingBeatmapChanged); - } + bindBindables(); if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false && Beatmap.Value.BeatmapSetInfo?.Protected == false && Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false)) @@ -619,15 +611,45 @@ namespace osu.Game.Screens.Select } } + private bool boundLocalBindables; + + private void bindBindables() + { + if (boundLocalBindables) + return; + + // manual binding to parent ruleset to allow for delayed load in the incoming direction. + rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; + Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); + + decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; + decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r; + + Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true); + Beatmap.BindValueChanged(workingBeatmapChanged); + + boundLocalBindables = true; + } + private void delete(BeatmapSetInfo beatmap) { if (beatmap == null || beatmap.ID <= 0) return; + dialogOverlay?.Push(new BeatmapDeleteDialog(beatmap)); } + private void clearScores(BeatmapInfo beatmap) + { + if (beatmap == null || beatmap.ID <= 0) return; + + dialogOverlay?.Push(new BeatmapClearScoresDialog(beatmap, () => + // schedule done here rather than inside the dialog as the dialog may fade out and never callback. + Schedule(() => BeatmapDetails.Leaderboard.RefreshScores()))); + } + public override bool OnPressed(GlobalAction action) { - if (!IsCurrentScreen) return false; + if (!this.IsCurrentScreen()) return false; switch (action) { diff --git a/osu.Game/Screens/Select/WedgeBackground.cs b/osu.Game/Screens/Select/WedgeBackground.cs index 6e9ee0704b..f1337a8119 100644 --- a/osu.Game/Screens/Select/WedgeBackground.cs +++ b/osu.Game/Screens/Select/WedgeBackground.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs b/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs index 49fb39c6da..36af1389ff 100644 --- a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs +++ b/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Configuration; using osu.Framework.Platform; diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs index 1453d4e78f..6b0888313b 100644 --- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs +++ b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -19,7 +19,7 @@ namespace osu.Game.Screens.Tournament.Components /// public int Lines { - get { return allLines.Count; } + get => allLines.Count; set { while (value > allLines.Count) diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 754f34f00f..f8445a4a7d 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -22,6 +22,8 @@ using osuTK; using osuTK.Graphics; using osu.Framework.IO.Stores; using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osu.Game.Graphics; namespace osu.Game.Screens.Tournament { @@ -29,7 +31,7 @@ namespace osu.Game.Screens.Tournament { private const string results_filename = "drawings_results.txt"; - protected override bool HideOverlaysOnEnter => true; + public override bool HideOverlaysOnEnter => true; protected override BackgroundScreen CreateBackground() => new BackgroundScreenDefault(); @@ -70,13 +72,13 @@ namespace osu.Game.Screens.Tournament if (!TeamList.Teams.Any()) { - Exit(); + this.Exit(); return; } drawingsConfig = new DrawingsConfigManager(storage); - Children = new Drawable[] + InternalChildren = new Drawable[] { new Box { @@ -150,8 +152,7 @@ namespace osu.Game.Screens.Tournament Alpha = 0, - Font = "Exo2.0-Light", - TextSize = 42f + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), } } }, @@ -174,8 +175,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.TopCentre, Text = "Control Panel", - TextSize = 22f, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22), }, new FillFlowContainer { diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game/Screens/Tournament/Group.cs index e9825b8d31..4fed10b94d 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game/Screens/Tournament/Group.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using System.Linq; @@ -14,6 +14,7 @@ using osuTK; using osuTK.Graphics; using osu.Game.Screens.Tournament.Teams; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; namespace osu.Game.Screens.Tournament { @@ -52,8 +53,7 @@ namespace osu.Game.Screens.Tournament Position = new Vector2(0, 7f), Text = $"GROUP {name.ToUpperInvariant()}", - TextSize = 8f, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 8), Colour = new Color4(255, 204, 34, 255), }, teams = new FillFlowContainer @@ -162,8 +162,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.TopCentre, Text = team.Acronym.ToUpperInvariant(), - TextSize = 10f, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10), } } } diff --git a/osu.Game/Screens/Tournament/GroupContainer.cs b/osu.Game/Screens/Tournament/GroupContainer.cs index 73d4f13132..211a28ca38 100644 --- a/osu.Game/Screens/Tournament/GroupContainer.cs +++ b/osu.Game/Screens/Tournament/GroupContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index d401332e06..0bcf1b1816 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -84,9 +84,10 @@ namespace osu.Game.Screens.Tournament } private ScrollState _scrollState; + private ScrollState scrollState { - get { return _scrollState; } + get => _scrollState; set { @@ -326,9 +327,10 @@ namespace osu.Game.Screens.Tournament private readonly Box outline; private bool selected; + public bool Selected { - get { return selected; } + get => selected; set { diff --git a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs b/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs index 0926ed2748..192a978721 100644 --- a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs +++ b/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Screens.Tournament.Teams { diff --git a/osu.Game/Screens/Tournament/Teams/ITeamList.cs b/osu.Game/Screens/Tournament/Teams/ITeamList.cs index 728c702173..e998c5dce4 100644 --- a/osu.Game/Screens/Tournament/Teams/ITeamList.cs +++ b/osu.Game/Screens/Tournament/Teams/ITeamList.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; diff --git a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs b/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs index bb112c7e2d..fad47c0922 100644 --- a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs +++ b/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 292889d4a3..c7556dddd5 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; -using osuTK.Graphics; namespace osu.Game.Skinning { @@ -13,16 +12,7 @@ namespace osu.Game.Skinning public DefaultSkin() : base(SkinInfo.Default) { - Configuration = new SkinConfiguration - { - ComboColours = - { - new Color4(17, 136, 170, 255), - new Color4(102, 136, 0, 255), - new Color4(204, 102, 0, 255), - new Color4(121, 9, 13, 255) - } - }; + Configuration = new SkinConfiguration(); } public override Drawable GetDrawableComponent(string componentName) => null; diff --git a/osu.Game/Skinning/ISkinSource.cs b/osu.Game/Skinning/ISkinSource.cs index 609f8e4ac4..6d2b9e6fe2 100644 --- a/osu.Game/Skinning/ISkinSource.cs +++ b/osu.Game/Skinning/ISkinSource.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Audio.Sample; @@ -21,8 +21,6 @@ namespace osu.Game.Skinning SampleChannel GetSample(string sampleName); - TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class; - - TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct; + TValue GetValue(Func query) where TConfiguration : SkinConfiguration; } } diff --git a/osu.Game/Skinning/LegacyBeatmapSkin.cs b/osu.Game/Skinning/LegacyBeatmapSkin.cs index 0b17bc6f3a..6770da3c66 100644 --- a/osu.Game/Skinning/LegacyBeatmapSkin.cs +++ b/osu.Game/Skinning/LegacyBeatmapSkin.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio; using osu.Framework.IO.Stores; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 23367c58c9..358b2b222b 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.IO; @@ -28,7 +28,8 @@ namespace osu.Game.Skinning { } - protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) : base(skin) + protected LegacySkin(SkinInfo skin, IResourceStore storage, AudioManager audioManager, string filename) + : base(skin) { Stream stream = storage.GetStream(filename); if (stream != null) @@ -58,7 +59,14 @@ namespace osu.Game.Skinning componentName = "hit300"; break; case "Play/osu/number-text": - return !hasFont(Configuration.HitCircleFont) ? null : new LegacySpriteText(Textures, Configuration.HitCircleFont) { Scale = new Vector2(0.96f) }; + return !hasFont(Configuration.HitCircleFont) + ? null + : new LegacySpriteText(Textures, Configuration.HitCircleFont) + { + Scale = new Vector2(0.96f), + // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size + Spacing = new Vector2(-Configuration.HitCircleOverlap * 0.89f, 0) + }; } var texture = GetTexture(componentName); @@ -101,9 +109,10 @@ namespace osu.Game.Skinning bool hasExtension = filename.Contains('.'); string lastPiece = filename.Split('/').Last(); + var legacyName = filename.StartsWith("Gameplay/taiko/") ? "taiko-" + lastPiece : lastPiece; var file = source.Files.Find(f => - string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), lastPiece, StringComparison.InvariantCultureIgnoreCase)); + string.Equals(hasExtension ? f.Filename : Path.ChangeExtension(f.Filename, null), legacyName, StringComparison.InvariantCultureIgnoreCase)); return file?.FileInfo.StoragePath; } diff --git a/osu.Game/Skinning/LegacySkinDecoder.cs b/osu.Game/Skinning/LegacySkinDecoder.cs index 67a031fb50..96a9116c51 100644 --- a/osu.Game/Skinning/LegacySkinDecoder.cs +++ b/osu.Game/Skinning/LegacySkinDecoder.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps.Formats; @@ -30,6 +30,9 @@ namespace osu.Game.Skinning case @"Author": skin.SkinInfo.Creator = pair.Value; break; + case @"CursorExpand": + skin.CursorExpand = pair.Value != "0"; + break; } break; @@ -43,6 +46,9 @@ namespace osu.Game.Skinning case "HitCirclePrefix": skin.HitCircleFont = pair.Value; break; + case "HitCircleOverlap": + skin.HitCircleOverlap = int.Parse(pair.Value); + break; } break; diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index d7d2737d35..955ef7b65b 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -12,6 +12,9 @@ using osu.Game.Configuration; namespace osu.Game.Skinning { + /// + /// A container which overrides existing skin options with beatmap-local values. + /// public class LocalSkinOverrideContainer : Container, ISkinSource { public event Action SourceChanged; @@ -19,48 +22,6 @@ namespace osu.Game.Skinning private readonly Bindable beatmapSkins = new Bindable(); private readonly Bindable beatmapHitsounds = new Bindable(); - public Drawable GetDrawableComponent(string componentName) - { - Drawable sourceDrawable; - if (beatmapSkins && (sourceDrawable = source.GetDrawableComponent(componentName)) != null) - return sourceDrawable; - return fallbackSource?.GetDrawableComponent(componentName); - } - - public Texture GetTexture(string componentName) - { - Texture sourceTexture; - if (beatmapSkins && (sourceTexture = source.GetTexture(componentName)) != null) - return sourceTexture; - return fallbackSource.GetTexture(componentName); - } - - public SampleChannel GetSample(string sampleName) - { - SampleChannel sourceChannel; - if (beatmapHitsounds && (sourceChannel = source.GetSample(sampleName)) != null) - return sourceChannel; - return fallbackSource?.GetSample(sampleName); - } - - public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct - { - TValue? val = null; - if ((source as Skin)?.Configuration is TConfiguration conf) - val = query?.Invoke(conf); - - return val ?? fallbackSource?.GetValue(query); - } - - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class - { - TValue val = null; - if ((source as Skin)?.Configuration is TConfiguration conf) - val = query?.Invoke(conf); - - return val ?? fallbackSource?.GetValue(query); - } - private readonly ISkinSource source; private ISkinSource fallbackSource; @@ -69,6 +30,43 @@ namespace osu.Game.Skinning this.source = source; } + public Drawable GetDrawableComponent(string componentName) + { + Drawable sourceDrawable; + if (beatmapSkins.Value && (sourceDrawable = source.GetDrawableComponent(componentName)) != null) + return sourceDrawable; + + return fallbackSource?.GetDrawableComponent(componentName); + } + + public Texture GetTexture(string componentName) + { + Texture sourceTexture; + if (beatmapSkins.Value && (sourceTexture = source.GetTexture(componentName)) != null) + return sourceTexture; + + return fallbackSource.GetTexture(componentName); + } + + public SampleChannel GetSample(string sampleName) + { + SampleChannel sourceChannel; + if (beatmapHitsounds.Value && (sourceChannel = source.GetSample(sampleName)) != null) + return sourceChannel; + + return fallbackSource?.GetSample(sampleName); + } + + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + { + TValue val; + if ((source as Skin)?.Configuration is TConfiguration conf) + if (beatmapSkins.Value && (val = query.Invoke(conf)) != null) + return val; + + return fallbackSource == null ? default : fallbackSource.GetValue(query); + } + private void onSourceChanged() => SourceChanged?.Invoke(); protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -76,31 +74,27 @@ namespace osu.Game.Skinning var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); fallbackSource = dependencies.Get(); + if (fallbackSource != null) + fallbackSource.SourceChanged += onSourceChanged; + dependencies.CacheAs(this); + var config = dependencies.Get(); + + config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); + config.BindWith(OsuSetting.BeatmapHitsounds, beatmapHitsounds); + + beatmapSkins.BindValueChanged(_ => onSourceChanged()); + beatmapHitsounds.BindValueChanged(_ => onSourceChanged()); + return dependencies; } - [BackgroundDependencyLoader] - private void load(OsuConfigManager config) - { - config.BindWith(OsuSetting.BeatmapSkins, beatmapSkins); - config.BindWith(OsuSetting.BeatmapHitsounds, beatmapHitsounds); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - if (fallbackSource != null) - fallbackSource.SourceChanged += onSourceChanged; - - beatmapSkins.BindValueChanged(_ => onSourceChanged()); - beatmapHitsounds.BindValueChanged(_ => onSourceChanged(), true); - } - protected override void Dispose(bool isDisposing) { + // Must be done before base.Dispose() + SourceChanged = null; + base.Dispose(isDisposing); if (fallbackSource != null) diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs index 29130f45df..1d14f9cd6a 100644 --- a/osu.Game/Skinning/Skin.cs +++ b/osu.Game/Skinning/Skin.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Audio.Sample; @@ -22,11 +22,8 @@ namespace osu.Game.Skinning public abstract Texture GetTexture(string componentName); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class - => Configuration is TConfiguration conf ? query?.Invoke(conf) : null; - - public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct - => Configuration is TConfiguration conf ? query?.Invoke(conf) : null; + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration + => Configuration is TConfiguration conf ? query.Invoke(conf) : default; protected Skin(SkinInfo skin) { @@ -52,6 +49,7 @@ namespace osu.Game.Skinning { if (isDisposed) return; + isDisposed = true; } diff --git a/osu.Game/Skinning/SkinConfiguration.cs b/osu.Game/Skinning/SkinConfiguration.cs index 7d354d108c..82faec4e9d 100644 --- a/osu.Game/Skinning/SkinConfiguration.cs +++ b/osu.Game/Skinning/SkinConfiguration.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; using osu.Game.Beatmaps.Formats; @@ -11,10 +11,20 @@ namespace osu.Game.Skinning { public readonly SkinInfo SkinInfo = new SkinInfo(); - public List ComboColours { get; set; } = new List(); + public List ComboColours { get; set; } = new List + { + new Color4(17, 136, 170, 255), + new Color4(102, 136, 0, 255), + new Color4(204, 102, 0, 255), + new Color4(121, 9, 13, 255) + }; public Dictionary CustomColours { get; set; } = new Dictionary(); public string HitCircleFont { get; set; } = "default"; + + public int HitCircleOverlap { get; set; } + + public bool? CursorExpand { get; set; } = true; } } diff --git a/osu.Game/Skinning/SkinFileInfo.cs b/osu.Game/Skinning/SkinFileInfo.cs index 8f0f2b536a..8a7019e1a3 100644 --- a/osu.Game/Skinning/SkinFileInfo.cs +++ b/osu.Game/Skinning/SkinFileInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.ComponentModel.DataAnnotations; using osu.Game.Database; diff --git a/osu.Game/Skinning/SkinInfo.cs b/osu.Game/Skinning/SkinInfo.cs index 60162ed224..07318b473a 100644 --- a/osu.Game/Skinning/SkinInfo.cs +++ b/osu.Game/Skinning/SkinInfo.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index ce179d43ef..f6bbbc8355 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -8,7 +8,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; @@ -42,10 +42,10 @@ namespace osu.Game.Skinning CurrentSkinInfo.Value = SkinInfo.Default; }; - CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = getSkin(info); + CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = getSkin(skin.NewValue); CurrentSkin.ValueChanged += skin => { - if (skin.SkinInfo != CurrentSkinInfo.Value) + if (skin.NewValue.SkinInfo != CurrentSkinInfo.Value) throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead."); SourceChanged?.Invoke(); @@ -116,8 +116,6 @@ namespace osu.Game.Skinning public SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName); - public TValue GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : class => CurrentSkin.Value.GetValue(query); - - public TValue? GetValue(Func query) where TConfiguration : SkinConfiguration where TValue : struct => CurrentSkin.Value.GetValue(query); + public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => CurrentSkin.Value.GetValue(query); } } diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 0b94697405..c09d5b1f92 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Skinning/SkinStore.cs b/osu.Game/Skinning/SkinStore.cs index e1dab17283..31cadb0a24 100644 --- a/osu.Game/Skinning/SkinStore.cs +++ b/osu.Game/Skinning/SkinStore.cs @@ -1,22 +1,16 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using System.Linq; -using Microsoft.EntityFrameworkCore; using osu.Framework.Platform; using osu.Game.Database; namespace osu.Game.Skinning { - public class SkinStore : MutableDatabaseBackedStore + public class SkinStore : MutableDatabaseBackedStoreWithFileIncludes { public SkinStore(DatabaseContextFactory contextFactory, Storage storage = null) : base(contextFactory, storage) { } - - protected override IQueryable AddIncludesForConsumption(IQueryable query) => - base.AddIncludesForConsumption(query) - .Include(s => s.Files).ThenInclude(f => f.FileInfo); } } diff --git a/osu.Game/Skinning/SkinnableDrawable.cs b/osu.Game/Skinning/SkinnableDrawable.cs index 12bbde67fb..3ca58dc625 100644 --- a/osu.Game/Skinning/SkinnableDrawable.cs +++ b/osu.Game/Skinning/SkinnableDrawable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics; diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 4f881a917e..d6f3625be8 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; diff --git a/osu.Game/Skinning/SkinnableSpriteText.cs b/osu.Game/Skinning/SkinnableSpriteText.cs index 8b09417bed..36e646d743 100644 --- a/osu.Game/Skinning/SkinnableSpriteText.cs +++ b/osu.Game/Skinning/SkinnableSpriteText.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics.Sprites; @@ -30,6 +30,7 @@ namespace osu.Game.Skinning { if (text == value) return; + text = value; if (Drawable is IHasText textDrawable) diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 9836d490af..c22ca0d8c0 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index 64b0a45fcd..aa1f137cf3 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Caching; using osu.Framework.Graphics; @@ -52,6 +52,7 @@ namespace osu.Game.Storyboards { var result = StartTime.CompareTo(other.StartTime); if (result != 0) return result; + return EndTime.CompareTo(other.EndTime); } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index b81b954f37..b1cc0436de 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs index 2e355faf7c..011f345df2 100644 --- a/osu.Game/Storyboards/CommandTrigger.cs +++ b/osu.Game/Storyboards/CommandTrigger.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Storyboards { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index bbb9491b0a..1182cacfc1 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Game.IO; +using osu.Game.Screens.Play; namespace osu.Game.Storyboards.Drawables { @@ -20,12 +21,14 @@ namespace osu.Game.Storyboards.Drawables protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); private bool passing = true; + public bool Passing { - get { return passing; } + get => passing; set { if (passing == value) return; + passing = value; updateLayerVisibility(); } @@ -34,6 +37,7 @@ namespace osu.Game.Storyboards.Drawables public override bool RemoveCompletedTransforms => false; private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -52,9 +56,12 @@ namespace osu.Game.Storyboards.Drawables }); } - [BackgroundDependencyLoader] - private void load(FileStore fileStore) + [BackgroundDependencyLoader(true)] + private void load(FileStore fileStore, GameplayClock clock) { + if (clock != null) + Clock = clock; + dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 2330c25443..0b9ebaf3a7 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; @@ -63,7 +64,7 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, TextureStore textureStore) + private void load(IBindable beatmap, TextureStore textureStore) { var basePath = Animation.Path.ToLowerInvariant(); for (var frame = 0; frame < Animation.FrameCount; frame++) @@ -77,6 +78,7 @@ namespace osu.Game.Storyboards.Drawables var texture = textureStore.Get(path); AddFrame(texture, Animation.FrameDelay); } + Animation.ApplyTransforms(this); } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 74eaab33ca..106ebfaf5d 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Storyboards.Drawables { - public class DrawableStoryboardLayer : Container + public class DrawableStoryboardLayer : LifetimeManagementContainer { public StoryboardLayer Layer { get; private set; } public bool Enabled; @@ -29,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables foreach (var element in Layer.Elements) { if (element.IsDrawable) - Add(element.CreateDrawable()); + AddInternal(element.CreateDrawable()); } } } diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 4f469ae593..9fa481b8b6 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System.IO; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; @@ -28,7 +29,7 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap) + private void load(IBindable beatmap) { // Try first with the full name, then attempt with no path channel = beatmap.Value.Skin.GetSample(sample.Path) ?? beatmap.Value.Skin.GetSample(Path.ChangeExtension(sample.Path, null)); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index b03285b419..604260a38c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -62,7 +63,7 @@ namespace osu.Game.Storyboards.Drawables } [BackgroundDependencyLoader] - private void load(IBindableBeatmap beatmap, TextureStore textureStore) + private void load(IBindable beatmap, TextureStore textureStore) { var spritePath = Sprite.Path.ToLowerInvariant(); var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath; diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index de8a1c2e71..7e31e1135e 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index 94cf0a891d..9e12de5833 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 18424339e6..454db2afc2 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index c3bce27b56..0cc753ff7e 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Beatmaps; using osu.Game.Storyboards.Drawables; @@ -76,6 +76,7 @@ namespace osu.Game.Storyboards { if (isDisposed) return; + isDisposed = true; } diff --git a/osu.Game/Storyboards/StoryboardAnimation.cs b/osu.Game/Storyboards/StoryboardAnimation.cs index b1c5720d99..1a4b6bb923 100644 --- a/osu.Game/Storyboards/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/StoryboardAnimation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/StoryboardLayer.cs b/osu.Game/Storyboards/StoryboardLayer.cs index 402c2c0add..daf03b00b4 100644 --- a/osu.Game/Storyboards/StoryboardLayer.cs +++ b/osu.Game/Storyboards/StoryboardLayer.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Game.Storyboards.Drawables; using System.Collections.Generic; diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index c34a39a7bf..1bdf774e74 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 173f403cc2..b91b05bd04 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK; using osu.Framework.Graphics; @@ -34,6 +34,7 @@ namespace osu.Game.Storyboards public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands); private delegate void DrawablePropertyInitializer(Drawable drawable, T value); + private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); public StoryboardSprite(string path, Anchor origin, Vector2 initialPosition) @@ -70,8 +71,7 @@ namespace osu.Game.Storyboards applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); applyCommands(drawable, getCommands(g => g.BlendingMode, triggeredGroups), (d, value) => d.Blending = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); - var flippable = drawable as IFlippable; - if (flippable != null) + if (drawable is IFlippable flippable) { applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); @@ -90,6 +90,7 @@ namespace osu.Game.Storyboards initializeProperty.Invoke(drawable, command.StartValue); initialized = true; } + using (drawable.BeginAbsoluteSequence(command.StartTime)) { transform(drawable, command.StartValue, 0, Easing.None); diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index ff57ef41c5..44ac38044d 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -39,6 +39,7 @@ namespace osu.Game.Tests.Beatmaps { if (mappingCounter >= ourResult.Mappings.Count && mappingCounter >= expectedResult.Mappings.Count) break; + if (mappingCounter >= ourResult.Mappings.Count) Assert.Fail($"A conversion did not generate any hitobjects, but should have, for hitobject at time: {expectedResult.Mappings[mappingCounter].StartTime}\n"); else if (mappingCounter >= expectedResult.Mappings.Count) @@ -64,6 +65,7 @@ namespace osu.Game.Tests.Beatmaps { if (objectCounter >= ourMapping.Objects.Count && objectCounter >= expectedMapping.Objects.Count) break; + if (objectCounter >= ourMapping.Objects.Count) Assert.Fail($"The conversion did not generate a hitobject, but should have, for hitobject at time: {expectedMapping.StartTime}:\n" + $"Expected: {JsonConvert.SerializeObject(expectedMapping.Objects[objectCounter])}\n"); @@ -189,7 +191,10 @@ namespace osu.Game.Tests.Beatmaps public List Objects = new List(); [JsonProperty("Objects")] - private List setObjects { set => Objects = value; } + private List setObjects + { + set => Objects = value; + } public virtual bool Equals(ConvertMapping other) => StartTime.Equals(other?.StartTime); } diff --git a/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs new file mode 100644 index 0000000000..108fa8ff71 --- /dev/null +++ b/osu.Game/Tests/Beatmaps/DifficultyCalculatorTest.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.IO; +using System.Reflection; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Formats; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Tests.Beatmaps +{ + [TestFixture] + public abstract class DifficultyCalculatorTest + { + private const string resource_namespace = "Testing.Beatmaps"; + + protected abstract string ResourceAssembly { get; } + + protected void Test(double expected, string name, params Mod[] mods) + => Assert.AreEqual(expected, CreateDifficultyCalculator(getBeatmap(name)).Calculate(mods).StarRating); + + private WorkingBeatmap getBeatmap(string name) + { + using (var resStream = openResource($"{resource_namespace}.{name}.osu")) + using (var stream = new StreamReader(resStream)) + { + var decoder = Decoder.GetDecoder(stream); + ((LegacyBeatmapDecoder)decoder).ApplyOffsets = false; + + var working = new TestWorkingBeatmap(decoder.Decode(stream)); + working.BeatmapInfo.Ruleset = CreateRuleset().RulesetInfo; + + return working; + } + } + + private Stream openResource(string name) + { + var localPath = Path.GetDirectoryName(Uri.UnescapeDataString(new UriBuilder(Assembly.GetExecutingAssembly().CodeBase).Path)); + return Assembly.LoadFrom(Path.Combine(localPath, $"{ResourceAssembly}.dll")).GetManifestResourceStream($@"{ResourceAssembly}.Resources.{name}"); + } + + protected abstract DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap); + + protected abstract Ruleset CreateRuleset(); + } +} diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index 6bad08baaa..b77a8508ad 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using System.IO; using System.Text; using osu.Game.Beatmaps; @@ -21,6 +22,18 @@ namespace osu.Game.Tests.Beatmaps HitObjects = baseBeatmap.HitObjects; BeatmapInfo.Ruleset = ruleset; + BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata; + BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo }; + BeatmapInfo.BeatmapSet.OnlineInfo = new BeatmapSetOnlineInfo + { + Status = BeatmapSetOnlineStatus.Ranked, + Covers = new BeatmapSetOnlineCovers + { + Cover = "https://assets.ppy.sh/beatmaps/163112/covers/cover.jpg", + Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg", + List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg" + } + }; } private static Beatmap createTestBeatmap() @@ -30,8 +43,7 @@ namespace osu.Game.Tests.Beatmaps return Decoder.GetDecoder(reader).Decode(reader); } - private const string test_beatmap_data = -@"osu file format v14 + private const string test_beatmap_data = @"osu file format v14 [General] AudioLeadIn: 500 diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 2f5c887726..78f9103a74 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,8 +1,10 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -10,20 +12,121 @@ namespace osu.Game.Tests.Beatmaps { public class TestWorkingBeatmap : WorkingBeatmap { - public TestWorkingBeatmap(RulesetInfo ruleset) - : this(new TestBeatmap(ruleset)) + private readonly TrackVirtualManual track; + private readonly IBeatmap beatmap; + + /// + /// Create an instance which creates a for the provided ruleset when requested. + /// + /// The target ruleset. + /// A clock which should be used instead of a stopwatch for virtual time progression. + public TestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock) + : this(new TestBeatmap(ruleset), referenceClock) { } - public TestWorkingBeatmap(IBeatmap beatmap) + /// + /// Create an instance which provides the when requested. + /// + /// The beatmap + /// An optional clock which should be used instead of a stopwatch for virtual time progression. + public TestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock = null) : base(beatmap.BeatmapInfo) { this.beatmap = beatmap; + + if (referenceClock != null) + track = new TrackVirtualManual(referenceClock); } - private readonly IBeatmap beatmap; protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; - protected override Track GetTrack() => null; + protected override Track GetTrack() => track; + + /// + /// A virtual track which tracks a reference clock. + /// + public class TrackVirtualManual : Track + { + private readonly IFrameBasedClock referenceClock; + + private readonly ManualClock clock = new ManualClock(); + + private bool running; + + /// + /// Local offset added to the reference clock to resolve correct time. + /// + private double offset; + + public TrackVirtualManual(IFrameBasedClock referenceClock) + { + this.referenceClock = referenceClock; + Length = double.PositiveInfinity; + } + + public override bool Seek(double seek) + { + offset = Math.Min(seek, Length); + lastReferenceTime = null; + return true; + } + + public override void Start() + { + running = true; + } + + public override void Reset() + { + Seek(0); + base.Reset(); + } + + public override void Stop() + { + if (running) + { + running = false; + // on stopping, the current value should be transferred out of the clock, as we can no longer rely on + // the referenceClock (which will still be counting time). + offset = clock.CurrentTime; + lastReferenceTime = null; + } + } + + public override bool IsRunning => running; + + private double? lastReferenceTime; + + public override double CurrentTime => clock.CurrentTime; + + protected override void UpdateState() + { + base.UpdateState(); + + if (running) + { + double refTime = referenceClock.CurrentTime; + + if (!lastReferenceTime.HasValue) + { + // if the clock just started running, the current value should be transferred to the offset + // (to zero the progression of time). + offset -= refTime; + } + + lastReferenceTime = refTime; + } + + clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length); + + if (CurrentTime >= Length) + { + Stop(); + RaiseCompleted(); + } + } + } } } diff --git a/osu.Game/Tests/CleanRunHeadlessGameHost.cs b/osu.Game/Tests/CleanRunHeadlessGameHost.cs index 2308e541c1..746dd936de 100644 --- a/osu.Game/Tests/CleanRunHeadlessGameHost.cs +++ b/osu.Game/Tests/CleanRunHeadlessGameHost.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Platform; diff --git a/osu.Game/Tests/OsuTestBrowser.cs b/osu.Game/Tests/OsuTestBrowser.cs index 217af8eb77..71b0b02fa6 100644 --- a/osu.Game/Tests/OsuTestBrowser.cs +++ b/osu.Game/Tests/OsuTestBrowser.cs @@ -1,7 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Framework.Platform; +using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Screens.Backgrounds; @@ -14,10 +16,10 @@ namespace osu.Game.Tests { base.LoadComplete(); - LoadComponentAsync(new BackgroundScreenDefault + LoadComponentAsync(new ScreenStack(new BackgroundScreenDefault { Colour = OsuColour.Gray(0.5f) }) { - Colour = OsuColour.Gray(0.5f), - Depth = 10 + Depth = 10, + RelativeSizeAxes = Axes.Both, }, AddInternal); // Have to construct this here, rather than in the constructor, because diff --git a/osu.Game/Tests/Visual/AllPlayersTestCase.cs b/osu.Game/Tests/Visual/AllPlayersTestCase.cs new file mode 100644 index 0000000000..03bd7b218a --- /dev/null +++ b/osu.Game/Tests/Visual/AllPlayersTestCase.cs @@ -0,0 +1,90 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Screens; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + /// + /// A base class which runs test for all available rulesets. + /// Steps to be run for each ruleset should be added via . + /// + public abstract class AllPlayersTestCase : RateAdjustedBeatmapTestCase + { + protected Player Player; + + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) + { + Add(new Box + { + RelativeSizeAxes = Framework.Graphics.Axes.Both, + Colour = Color4.Black, + Depth = int.MaxValue + }); + + foreach (var r in rulesets.AvailableRulesets) + { + Player p = null; + AddStep(r.Name, () => p = loadPlayerFor(r)); + AddUntilStep(() => + { + if (p?.IsLoaded == true) + { + p = null; + return true; + } + + return false; + }, "player loaded"); + + AddCheckSteps(); + } + } + + protected abstract void AddCheckSteps(); + + protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); + + protected virtual WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock) => + new TestWorkingBeatmap(beatmap, Clock); + + private Player loadPlayerFor(RulesetInfo ri) + { + Ruleset.Value = ri; + var r = ri.CreateInstance(); + + var beatmap = CreateBeatmap(r); + var working = CreateWorkingBeatmap(beatmap, Clock); + + Beatmap.Value = working; + Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; + + Player?.Exit(); + Player = null; + + Player = CreatePlayer(r); + + LoadScreen(Player); + + return Player; + } + + protected virtual Player CreatePlayer(Ruleset ruleset) => new Player + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + }; + } +} diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 479ed385e2..7f36a0e142 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -41,10 +42,10 @@ namespace osu.Game.Tests.Visual Beatmap.BindValueChanged(beatmapChanged, true); } - private void beatmapChanged(WorkingBeatmap working) + private void beatmapChanged(ValueChangedEvent e) { - Clock.ControlPointInfo = working.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)working.Track ?? new StopwatchClock()); + Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; + Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/EditorTestCase.cs b/osu.Game/Tests/Visual/EditorTestCase.cs index 2d02509b58..96e70e018e 100644 --- a/osu.Game/Tests/Visual/EditorTestCase.cs +++ b/osu.Game/Tests/Visual/EditorTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -24,9 +24,9 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo, null); - LoadComponentAsync(new Editor(), LoadScreen); + LoadScreen(new Editor()); } } } diff --git a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs index 01676ad56e..7c7c5938aa 100644 --- a/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs +++ b/osu.Game/Tests/Visual/ManualInputManagerTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Tests/Visual/MultiplayerTestCase.cs b/osu.Game/Tests/Visual/MultiplayerTestCase.cs new file mode 100644 index 0000000000..bb866cf750 --- /dev/null +++ b/osu.Game/Tests/Visual/MultiplayerTestCase.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Game.Online.Multiplayer; + +namespace osu.Game.Tests.Visual +{ + public abstract class MultiplayerTestCase : ScreenTestCase + { + [Cached] + private readonly Bindable currentRoom = new Bindable(new Room()); + + protected Room Room + { + get => currentRoom.Value; + set => currentRoom.Value = value; + } + + private CachedModelDependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + dependencies = new CachedModelDependencyContainer(base.CreateChildDependencies(parent)); + dependencies.Model.BindTo(currentRoom); + return dependencies; + } + } +} diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 80c9b2ab47..2fbf6f7e46 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; @@ -32,8 +32,8 @@ namespace osu.Game.Tests.Visual // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures beatmap.Default = new DummyWorkingBeatmap(Dependencies.Get()); - Dependencies.CacheAs(beatmap); - Dependencies.CacheAs(beatmap); + Dependencies.CacheAs>(beatmap); + Dependencies.CacheAs>(beatmap); Dependencies.CacheAs(Ruleset); Dependencies.CacheAs>(Ruleset); @@ -58,11 +58,7 @@ namespace osu.Game.Tests.Visual { base.Dispose(isDisposing); - if (beatmap != null) - { - beatmap.Disabled = true; - beatmap.Value.Track.Stop(); - } + beatmap?.Value.Track.Stop(); if (localStorage.IsValueCreated) { diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs index ca762c6be2..ec4b0a1f62 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Tests/Visual/PlayerTestCase.cs b/osu.Game/Tests/Visual/PlayerTestCase.cs new file mode 100644 index 0000000000..50cb839ed9 --- /dev/null +++ b/osu.Game/Tests/Visual/PlayerTestCase.cs @@ -0,0 +1,66 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public abstract class PlayerTestCase : RateAdjustedBeatmapTestCase + { + private readonly Ruleset ruleset; + + protected Player Player; + + protected PlayerTestCase(Ruleset ruleset) + { + this.ruleset = ruleset; + + Add(new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Depth = int.MaxValue + }); + } + + [SetUpSteps] + public void SetUpSteps() + { + AddStep(ruleset.RulesetInfo.Name, loadPlayer); + AddUntilStep(() => Player.IsLoaded, "player loaded"); + } + + protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); + + protected virtual bool AllowFail => false; + + private void loadPlayer() + { + var beatmap = CreateBeatmap(ruleset); + + Beatmap.Value = new TestWorkingBeatmap(beatmap, Clock); + + if (!AllowFail) + Beatmap.Value.Mods.Value = new[] { ruleset.GetAllMods().First(m => m is ModNoFail) }; + + Player = CreatePlayer(ruleset); + LoadScreen(Player); + } + + protected virtual Player CreatePlayer(Ruleset ruleset) => new Player + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + }; + } +} diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs new file mode 100644 index 0000000000..3b3adb4d76 --- /dev/null +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Tests.Visual +{ + /// + /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. + /// + public abstract class RateAdjustedBeatmapTestCase : ScreenTestCase + { + protected override void Update() + { + base.Update(); + + // note that this will override any mod rate application + Beatmap.Value.Track.TempoAdjust = Clock.Rate; + } + } +} diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestCase.cs index e610fafa7b..eec60d01c5 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestCase.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Screens; +using osu.Framework.Graphics; using osu.Game.Screens; namespace osu.Game.Tests.Visual @@ -11,38 +11,18 @@ namespace osu.Game.Tests.Visual /// public abstract class ScreenTestCase : OsuTestCase { - private readonly TestOsuScreen baseScreen; + private readonly OsuScreenStack stack; protected ScreenTestCase() { - Add(baseScreen = new TestOsuScreen()); + Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }; } - protected void LoadScreen(OsuScreen screen) => baseScreen.LoadScreen(screen); - - public class TestOsuScreen : OsuScreen + protected void LoadScreen(OsuScreen screen) { - private OsuScreen nextScreen; - - public void LoadScreen(OsuScreen screen) => Schedule(() => - { - nextScreen = screen; - - if (IsCurrentScreen) - { - Push(screen); - nextScreen = null; - } - else - MakeCurrent(); - }); - - protected override void OnResuming(Screen last) - { - base.OnResuming(last); - if (nextScreen != null) - LoadScreen(nextScreen); - } + if (stack.CurrentScreen != null) + stack.Exit(); + stack.Push(screen); } } } diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index bc251fddbe..f2e03208fd 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Lists; using osu.Game.Configuration; @@ -20,9 +20,15 @@ namespace osu.Game.Tests.Visual { public SortedList ControlPoints => scrollingInfo.Algorithm.ControlPoints; - public ScrollVisualisationMethod ScrollAlgorithm { set => scrollingInfo.Algorithm.Algorithm = value; } + public ScrollVisualisationMethod ScrollAlgorithm + { + set => scrollingInfo.Algorithm.Algorithm = value; + } - public double TimeRange { set => scrollingInfo.TimeRange.Value = value; } + public double TimeRange + { + set => scrollingInfo.TimeRange.Value = value; + } public IScrollingInfo ScrollingInfo => scrollingInfo; diff --git a/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs b/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs index 183bef7602..d17f670a2d 100644 --- a/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs +++ b/osu.Game/Tests/Visual/SelectionBlueprintTestCase.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; using osu.Framework.Graphics; diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs deleted file mode 100644 index 47bf787bb5..0000000000 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; -using osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Play; -using osu.Game.Tests.Beatmaps; -using osuTK.Graphics; - -namespace osu.Game.Tests.Visual -{ - public abstract class TestCasePlayer : ScreenTestCase - { - private readonly Ruleset ruleset; - - protected Player Player; - - protected TestCasePlayer(Ruleset ruleset) - { - this.ruleset = ruleset; - } - - protected TestCasePlayer() - { - } - - [BackgroundDependencyLoader] - private void load(RulesetStore rulesets) - { - Add(new Box - { - RelativeSizeAxes = Framework.Graphics.Axes.Both, - Colour = Color4.Black, - Depth = int.MaxValue - }); - - if (ruleset != null) - { - Player p = null; - AddStep(ruleset.RulesetInfo.Name, () => p = loadPlayerFor(ruleset)); - AddUntilStep(() => ContinueCondition(p)); - } - else - { - foreach (var r in rulesets.AvailableRulesets) - { - Player p = null; - AddStep(r.Name, () => p = loadPlayerFor(r)); - AddUntilStep(() => ContinueCondition(p)); - - AddUntilStep(() => - { - p = null; - - GC.Collect(); - GC.WaitForPendingFinalizers(); - int count = 0; - - workingWeakReferences.ForEachAlive(_ => count++); - return count == 1; - }, "no leaked beatmaps"); - - AddUntilStep(() => - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - int count = 0; - - playerWeakReferences.ForEachAlive(_ => count++); - return count == 1; - }, "no leaked players"); - } - } - } - - protected virtual bool ContinueCondition(Player player) => player.IsLoaded; - - protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); - - private readonly WeakList workingWeakReferences = new WeakList(); - private readonly WeakList playerWeakReferences = new WeakList(); - - private Player loadPlayerFor(RulesetInfo ri) - { - Ruleset.Value = ri; - return loadPlayerFor(ri.CreateInstance()); - } - - private Player loadPlayerFor(Ruleset r) - { - var beatmap = CreateBeatmap(r); - var working = new TestWorkingBeatmap(beatmap); - - workingWeakReferences.Add(working); - - Beatmap.Value = working; - Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; - - Player?.Exit(); - - var player = CreatePlayer(r); - - playerWeakReferences.Add(player); - - LoadComponentAsync(player, p => - { - Player = p; - LoadScreen(p); - }); - - return player; - } - - protected override void Update() - { - base.Update(); - - // note that this will override any mod rate application - Beatmap.Value.Track.Rate = Clock.Rate; - } - - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player - { - AllowPause = false, - AllowLeadIn = false, - AllowResults = false, - }; - } -} diff --git a/osu.Game/Tests/VisualTestRunner.cs b/osu.Game/Tests/VisualTestRunner.cs index 2340371aab..d63b3d48b2 100644 --- a/osu.Game/Tests/VisualTestRunner.cs +++ b/osu.Game/Tests/VisualTestRunner.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework; diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 24864cce51..3df5957ff9 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -65,7 +65,7 @@ namespace osu.Game.Users private void openProfile() { - if (!OpenOnClick) + if (!OpenOnClick.Value) return; if (user != null) @@ -78,8 +78,9 @@ namespace osu.Game.Users protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return false; + return base.OnClick(e); } } diff --git a/osu.Game/Users/Badge.cs b/osu.Game/Users/Badge.cs index 25ef8ffdf4..9d46a1992b 100644 --- a/osu.Game/Users/Badge.cs +++ b/osu.Game/Users/Badge.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 80039eadad..b513b460bc 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; @@ -33,9 +33,10 @@ namespace osu.Game.Users private TextureStore textures; private Country country; + public Country Country { - get { return country; } + get => country; set { if (value == country) diff --git a/osu.Game/Users/Medal.cs b/osu.Game/Users/Medal.cs index 727eaefbc5..2e4f6de1d7 100644 --- a/osu.Game/Users/Medal.cs +++ b/osu.Game/Users/Medal.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Users { diff --git a/osu.Game/Users/Team.cs b/osu.Game/Users/Team.cs index 955bf8ec92..b56a083fdf 100644 --- a/osu.Game/Users/Team.cs +++ b/osu.Game/Users/Team.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Users { diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index a8d9d3d66b..7259468674 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -1,7 +1,7 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -23,7 +23,7 @@ namespace osu.Game.Users public User User { - get { return user; } + get => user; set { if (user?.Id == value?.Id) @@ -57,9 +57,9 @@ namespace osu.Game.Users var avatar = new Avatar(user) { RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), }; + avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint); avatar.OpenOnClick.BindTo(OpenOnClick); Add(displayedAvatar = new DelayedLoadWrapper(avatar)); diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index a5d8c03a67..292ac90245 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -1,9 +1,9 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Users { @@ -34,8 +34,8 @@ namespace osu.Game.Users [JsonProperty(@"cover_url")] public string CoverUrl { - get { return Cover?.Url; } - set { Cover = new UserCover { Url = value }; } + get => Cover?.Url; + set => Cover = new UserCover { Url = value }; } [JsonProperty(@"cover")] diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index fddbd57f9c..4c72762498 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Allocation; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 1d302ef04f..65062dc58e 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -59,6 +59,8 @@ namespace osu.Game.Users FillFlowContainer infoContainer; + UserCoverBackground coverBackground; + AddInternal(content = new Container { RelativeSizeAxes = Axes.Both, @@ -73,13 +75,12 @@ namespace osu.Game.Users Children = new Drawable[] { - new DelayedLoadWrapper(new UserCoverBackground(user) + new DelayedLoadWrapper(coverBackground = new UserCoverBackground(user) { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) }, 300) { RelativeSizeAxes = Axes.Both }, new Box { @@ -116,8 +117,7 @@ namespace osu.Game.Users new OsuSpriteText { Text = user.Username, - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 18, italics: true), }, infoContainer = new FillFlowContainer { @@ -173,7 +173,7 @@ namespace osu.Game.Users { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-Semibold", + Font = OsuFont.GetFont(weight: FontWeight.SemiBold), }, }, }, @@ -182,6 +182,8 @@ namespace osu.Game.Users } }); + coverBackground.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out); + if (user.IsSupporter) { infoContainer.Add(new SupporterIcon @@ -191,8 +193,8 @@ namespace osu.Game.Users }); } - Status.ValueChanged += displayStatus; - Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); + Status.ValueChanged += status => displayStatus(status.NewValue); + Status.ValueChanged += status => statusBg.FadeColour(status.NewValue?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); base.Action = ViewProfile = () => { diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index f04bfb62bb..2de54ed8be 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; @@ -23,7 +23,10 @@ namespace osu.Game.Users public decimal? PP; [JsonProperty(@"pp_rank")] // the API sometimes only returns this value in condensed user responses - private int rank { set => Ranks.Global = value; } + private int rank + { + set => Ranks.Global = value; + } [JsonProperty(@"rank")] public UserRanks Ranks; @@ -78,6 +81,5 @@ namespace osu.Game.Users [JsonProperty(@"country")] public int? Country; } - } } diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 6b27ff18a7..14b4538a00 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using osuTK.Graphics; using osu.Game.Graphics; @@ -39,7 +39,7 @@ namespace osu.Game.Users public override string Message => @"in Multiplayer Lobby"; } - public class UserStatusSoloGame : UserStatusBusy + public class UserStatusSoloGame : UserStatusBusy { public override string Message => @"Solo Game"; } diff --git a/osu.Game/Utils/DebugUtils.cs b/osu.Game/Utils/DebugUtils.cs index 191662c690..9b1d355a83 100644 --- a/osu.Game/Utils/DebugUtils.cs +++ b/osu.Game/Utils/DebugUtils.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. namespace osu.Game.Utils { diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index c6e6d1e9d7..7f4faa60ae 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; @@ -20,14 +20,14 @@ namespace osu.Game.Utils private readonly List tasks = new List(); - private Exception lastException; - public RavenLogger(OsuGame game) { raven.Release = game.Version; if (!game.IsDeployedBuild) return; + Exception lastException = null; + Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; diff --git a/osu.Game/Utils/ZipUtils.cs b/osu.Game/Utils/ZipUtils.cs index c96ea9c80a..98e24590a8 100644 --- a/osu.Game/Utils/ZipUtils.cs +++ b/osu.Game/Utils/ZipUtils.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using SharpCompress.Archives.Zip; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8f00e81237..71324ea0f0 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -10,16 +10,14 @@ - - - - - - + + + - - + + + diff --git a/osu.TestProject.props b/osu.TestProject.props index 456ecfd468..a5c70f4edc 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -8,7 +8,6 @@ - diff --git a/osu.iOS.props b/osu.iOS.props new file mode 100644 index 0000000000..02099a59bb --- /dev/null +++ b/osu.iOS.props @@ -0,0 +1,116 @@ + + + {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Resources + PackageReference + --nolinkaway -gcc_flags "-lstdc++ -framework AudioToolbox -framework SystemConfiguration -framework CFNetwork -framework Accelerate + + + true + full + false + bin\iPhoneSimulator\Debug + DEBUG;ENABLE_TEST_CLOUD; + prompt + 4 + iPhone Developer + true + true + true + 25823 + None + x86_64 + NSUrlSessionHandler + false + + Default + $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + false + cjk,mideast,other,rare,west + + + pdbonly + true + bin\iPhone\Release + + prompt + 4 + iPhone Distribution + true + true + Entitlements.plist + SdkOnly + ARM64 + NSUrlSessionHandler + + Default + $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + false + cjk,mideast,other,rare,west + + + pdbonly + true + bin\iPhoneSimulator\Release + + prompt + 4 + iPhone Developer + true + None + x86_64 + NSUrlSessionHandler + + Default + $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + false + cjk,mideast,other,rare,west + + + true + full + false + bin\iPhone\Debug + DEBUG;ENABLE_TEST_CLOUD; + prompt + 4 + iPhone Developer + true + true + true + true + Entitlements.plist + 28126 + SdkOnly + ARM64 + NSUrlSessionHandler + + Default + $(DefaultMtouchExtraArgs) -force_load $(OutputPath)\libbass.a -force_load $(OutputPath)\libbass_fx.a" + false + cjk,mideast,other,rare,west + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.iOS.sln b/osu.iOS.sln new file mode 100644 index 0000000000..21d02d33ab --- /dev/null +++ b/osu.iOS.sln @@ -0,0 +1,187 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2006 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.iOS", "osu.iOS\osu.iOS.csproj", "{3F082D0B-A964-43D7-BDF7-C256D76A50D0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests.iOS", "osu.Game.Tests.iOS\osu.Game.Tests.iOS.csproj", "{65FF8E19-6934-469B-B690-23C6D6E56A17}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests.iOS", "osu.Game.Rulesets.Taiko.Tests.iOS\osu.Game.Rulesets.Taiko.Tests.iOS.csproj", "{7E408809-66AC-49D1-AF4D-98834F9B979A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests.iOS", "osu.Game.Rulesets.Osu.Tests.iOS\osu.Game.Rulesets.Osu.Tests.iOS.csproj", "{6653CA6F-DB06-4604-A3FD-762E25C2AF96}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests.iOS", "osu.Game.Rulesets.Mania.Tests.iOS\osu.Game.Rulesets.Mania.Tests.iOS.csproj", "{39FD990E-B6CE-4B2A-999F-BC008CF2C64C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests.iOS", "osu.Game.Rulesets.Catch.Tests.iOS\osu.Game.Rulesets.Catch.Tests.iOS.csproj", "{4004C7B7-1A62-43F1-9DF2-52450FA67E70}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Debug|iPhoneSimulator = Debug|iPhoneSimulator + Release|iPhone = Release|iPhone + Release|iPhoneSimulator = Release|iPhoneSimulator + Debug|iPhone = Debug|iPhone + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|Any CPU.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhone.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}.Debug|iPhone.Build.0 = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|Any CPU.Build.0 = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.ActiveCfg = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhone.Build.0 = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}.Debug|iPhone.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|Any CPU.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhone.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C92A607B-1FDD-4954-9F92-03FF547D9080}.Debug|iPhone.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|Any CPU.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhone.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3}.Debug|iPhone.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|Any CPU.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhone.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {F167E17A-7DE6-4AF5-B920-A5112296C695}.Debug|iPhone.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhone.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|iPhone.Build.0 = Debug|Any CPU + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|Any CPU.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.ActiveCfg = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhone.Build.0 = Release|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.ActiveCfg = Debug|iPhone + {3F082D0B-A964-43D7-BDF7-C256D76A50D0}.Debug|iPhone.Build.0 = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|Any CPU.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.ActiveCfg = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhone.Build.0 = Release|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.ActiveCfg = Debug|iPhone + {65FF8E19-6934-469B-B690-23C6D6E56A17}.Debug|iPhone.Build.0 = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|Any CPU.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.ActiveCfg = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhone.Build.0 = Release|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.ActiveCfg = Debug|iPhone + {7E408809-66AC-49D1-AF4D-98834F9B979A}.Debug|iPhone.Build.0 = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|Any CPU.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.ActiveCfg = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhone.Build.0 = Release|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.ActiveCfg = Debug|iPhone + {6653CA6F-DB06-4604-A3FD-762E25C2AF96}.Debug|iPhone.Build.0 = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|Any CPU.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.ActiveCfg = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhone.Build.0 = Release|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.ActiveCfg = Debug|iPhone + {39FD990E-B6CE-4B2A-999F-BC008CF2C64C}.Debug|iPhone.Build.0 = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|Any CPU.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.ActiveCfg = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhone.Build.0 = Release|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.ActiveCfg = Debug|iPhone + {4004C7B7-1A62-43F1-9DF2-52450FA67E70}.Debug|iPhone.Build.0 = Debug|iPhone + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668} + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + Policies = $0 + $0.TextStylePolicy = $1 + $1.EolMarker = Windows + $1.scope = text/x-csharp + $1.FileWidth = 80 + $1.TabsToSpaces = True + $0.CSharpFormattingPolicy = $2 + $2.scope = text/x-csharp + EndGlobalSection +EndGlobal diff --git a/osu.iOS.sln.DotSettings b/osu.iOS.sln.DotSettings new file mode 100644 index 0000000000..3b2b851d45 --- /dev/null +++ b/osu.iOS.sln.DotSettings @@ -0,0 +1,816 @@ + + True + True + True + True + ExplicitlyExcluded + ExplicitlyExcluded + SOLUTION + HINT + WARNING + + True + WARNING + WARNING + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + HINT + WARNING + HINT + SUGGESTION + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + HINT + WARNING + WARNING + DO_NOT_SHOW + HINT + WARNING + DO_NOT_SHOW + WARNING + HINT + HINT + HINT + ERROR + HINT + HINT + HINT + WARNING + WARNING + HINT + DO_NOT_SHOW + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + HINT + HINT + HINT + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + WARNING + + WARNING + WARNING + WARNING + ERROR + WARNING + WARNING + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + DO_NOT_SHOW + DO_NOT_SHOW + DO_NOT_SHOW + WARNING + WARNING + HINT + WARNING + HINT + HINT + HINT + HINT + HINT + HINT + HINT + + HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + HINT + WARNING + WARNING + HINT + HINT + WARNING + <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> + Code Cleanup (peppy) + True + True + True + True + True + True + True + True + NEXT_LINE + NEXT_LINE + True + NEVER + NEVER + False + NEVER + False + True + False + False + True + True + False + CHOP_IF_LONG + True + 200 + CHOP_IF_LONG + False + False + AABB + API + BPM + GC + GL + GLSL + HID + HUD + ID + IP + IPC + LTRB + MD5 + NS + OS + RGB + RNG + SHA + SRGB + TK + SS + PP + GMT + QAT + BNG + UI + False + HINT + <?xml version="1.0" encoding="utf-16"?> +<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> + <TypePattern DisplayName="COM interfaces or structs"> + <TypePattern.Match> + <Or> + <And> + <Kind Is="Interface" /> + <Or> + <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" /> + <HasAttribute Name="System.Runtime.InteropServices.ComImport" /> + </Or> + </And> + <Kind Is="Struct" /> + </Or> + </TypePattern.Match> + </TypePattern> + <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All"> + <TypePattern.Match> + <And> + <Kind Is="Class" /> + <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> + </And> + </TypePattern.Match> + <Entry DisplayName="Setup/Teardown Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <Or> + <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> + <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="All other members" /> + <Entry Priority="100" DisplayName="Test Methods"> + <Entry.Match> + <And> + <Kind Is="Method" /> + <HasAttribute Name="NUnit.Framework.TestAttribute" /> + </And> + </Entry.Match> + <Entry.SortBy> + <Name /> + </Entry.SortBy> + </Entry> + </TypePattern> + <TypePattern DisplayName="Default Pattern"> + <Group DisplayName="Fields/Properties"> + <Group DisplayName="Public Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Public Properties"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Internal Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Internal Properties"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Protected Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Protected Properties"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + <Group DisplayName="Private Fields"> + <Entry DisplayName="Constant Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Or> + <Kind Is="Constant" /> + <Readonly /> + <And> + <Static /> + <Readonly /> + </And> + </Or> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Static Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Not> + <Readonly /> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Normal Fields"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Or> + <Static /> + <Readonly /> + </Or> + </Not> + <Kind Is="Field" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Entry DisplayName="Private Properties"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Kind Is="Property" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Constructor/Destructor"> + <Entry DisplayName="Ctor"> + <Entry.Match> + <Kind Is="Constructor" /> + </Entry.Match> + </Entry> + <Region Name="Disposal"> + <Entry DisplayName="Dtor"> + <Entry.Match> + <Kind Is="Destructor" /> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose()"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Dispose(true)"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Or> + <Virtual /> + <Override /> + </Or> + <Kind Is="Method" /> + <Name Is="Dispose" /> + </And> + </Entry.Match> + </Entry> + </Region> + </Group> + <Group DisplayName="Methods"> + <Group DisplayName="Public"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Public" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Internal"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Internal" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Protected"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Protected" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + <Group DisplayName="Private"> + <Entry DisplayName="Static Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Static /> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + <Entry DisplayName="Methods"> + <Entry.Match> + <And> + <Access Is="Private" /> + <Not> + <Static /> + </Not> + <Kind Is="Method" /> + </And> + </Entry.Match> + </Entry> + </Group> + </Group> + </TypePattern> +</Patterns> + Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +See the LICENCE file in the repository root for full licence text. + + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True + True + True + True + True + o!f – Object Initializer: Anchor&Origin + True + constant("Centre") + 0 + True + True + 2.0 + InCSharpFile + ofao + True + Anchor = Anchor.$anchor$, +Origin = Anchor.$anchor$, + True + True + o!f – InternalChildren = [] + True + True + 2.0 + InCSharpFile + ofic + True + InternalChildren = new Drawable[] +{ + $END$ +}; + True + True + o!f – new GridContainer { .. } + True + True + 2.0 + InCSharpFile + ofgc + True + new GridContainer +{ + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] { $END$ }, + new Drawable[] { } + } +}; + True + True + o!f – new FillFlowContainer { .. } + True + True + 2.0 + InCSharpFile + offf + True + new FillFlowContainer +{ + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – new Container { .. } + True + True + 2.0 + InCSharpFile + ofcont + True + new Container +{ + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + $END$ + } +}, + True + True + o!f – BackgroundDependencyLoader load() + True + True + 2.0 + InCSharpFile + ofbdl + True + [BackgroundDependencyLoader] +private void load() +{ + $END$ +} + True + True + o!f – new Box { .. } + True + True + 2.0 + InCSharpFile + ofbox + True + new Box +{ + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, +}, + True + True + o!f – Children = [] + True + True + 2.0 + InCSharpFile + ofc + True + Children = new Drawable[] +{ + $END$ +}; + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True diff --git a/osu.iOS/AppDelegate.cs b/osu.iOS/AppDelegate.cs new file mode 100644 index 0000000000..058e246ed8 --- /dev/null +++ b/osu.iOS/AppDelegate.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Foundation; +using osu.Framework.iOS; +using osu.Game; + +namespace osu.iOS +{ + [Register("AppDelegate")] + public class AppDelegate : GameAppDelegate + { + protected override Framework.Game CreateGame() => new OsuGameIOS(); + } +} diff --git a/osu.iOS/Application.cs b/osu.iOS/Application.cs new file mode 100644 index 0000000000..cb75e5c159 --- /dev/null +++ b/osu.iOS/Application.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using UIKit; + +namespace osu.iOS +{ + public class Application + { + public static void Main(string[] args) + { + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..bbd5f4f3ba --- /dev/null +++ b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,249 @@ +{ + "images": [ + { + "filename": "Icon-App-20x20@2x.png", + "size": "20x20", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-20x20@3x.png", + "size": "20x20", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-29x29@2x.png", + "size": "29x29", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-29x29@3x.png", + "size": "29x29", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-40x40@2x.png", + "size": "40x40", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-40x40@3x.png", + "size": "40x40", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-60x60@2x.png", + "size": "60x60", + "scale": "2x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-60x60@3x.png", + "size": "60x60", + "scale": "3x", + "idiom": "iphone" + }, + { + "filename": "Icon-App-20x20@1x.png", + "size": "20x20", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-20x20@2x.png", + "size": "20x20", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-29x29@1x.png", + "size": "29x29", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-29x29@2x.png", + "size": "29x29", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-40x40@1x.png", + "size": "40x40", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-40x40@2x.png", + "size": "40x40", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-83.5x83.5@2x.png", + "size": "83.5x83.5", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-76x76@1x.png", + "size": "76x76", + "scale": "1x", + "idiom": "ipad" + }, + { + "filename": "Icon-App-76x76@2x.png", + "size": "76x76", + "scale": "2x", + "idiom": "ipad" + }, + { + "filename": "ItunesArtwork@2x.png", + "size": "1024x1024", + "scale": "1x", + "idiom": "ios-marketing" + }, + { + "size": "60x60", + "scale": "2x", + "idiom": "car" + }, + { + "size": "60x60", + "scale": "3x", + "idiom": "car" + }, + { + "role": "notificationCenter", + "size": "24x24", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "notificationCenter", + "size": "27.5x27.5", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "companionSettings", + "size": "29x29", + "scale": "3x", + "idiom": "watch" + }, + { + "role": "appLauncher", + "size": "40x40", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "appLauncher", + "size": "44x44", + "subtype": "40mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "appLauncher", + "size": "50x50", + "subtype": "44mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "86x86", + "subtype": "38mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "98x98", + "subtype": "42mm", + "scale": "2x", + "idiom": "watch" + }, + { + "role": "quickLook", + "size": "108x108", + "subtype": "44mm", + "scale": "2x", + "idiom": "watch" + }, + { + "size": "1024x1024", + "scale": "1x", + "idiom": "watch-marketing" + }, + { + "size": "16x16", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "16x16", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "32x32", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "128x128", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "256x256", + "scale": "2x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "1x", + "idiom": "mac" + }, + { + "size": "512x512", + "scale": "2x", + "idiom": "mac" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000..dfcce1297b Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000..d563e8cf5e Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000..8a21d9f81d Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000..4477ece73a Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000..1fe354a7fa Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000..0f8c36a038 Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000..d563e8cf5e Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000..0208f80e3b Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000..f7ad8bb6bb Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000..f7ad8bb6bb Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000..3d85a133aa Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000..edd53bc954 Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000..b13a6e7a1e Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000..edff3788f0 Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000000..c04f6f3ec4 Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/osu.iOS/Assets.xcassets/Contents.json b/osu.iOS/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..4caf392f92 --- /dev/null +++ b/osu.iOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/osu.iOS/Entitlements.plist b/osu.iOS/Entitlements.plist new file mode 100644 index 0000000000..9ae599370b --- /dev/null +++ b/osu.iOS/Entitlements.plist @@ -0,0 +1,6 @@ + + + + + + diff --git a/osu.iOS/Info.plist b/osu.iOS/Info.plist new file mode 100644 index 0000000000..0627feab78 --- /dev/null +++ b/osu.iOS/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleIdentifier + sh.ppy.osulazer + CFBundleName + osu! + CFBundleShortVersionString + 0.1 + CFBundleVersion + 0.1.0 + LSRequiresIPhoneOS + + MinimumOSVersion + 10.0 + UIDeviceFamily + + 1 + 2 + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/osu.iOS/LaunchScreen.storyboard b/osu.iOS/LaunchScreen.storyboard new file mode 100644 index 0000000000..3655e9f2f0 --- /dev/null +++ b/osu.iOS/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.iOS/Linker.xml b/osu.iOS/Linker.xml new file mode 100644 index 0000000000..04591c55d0 --- /dev/null +++ b/osu.iOS/Linker.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.iOS/OsuGameIOS.cs b/osu.iOS/OsuGameIOS.cs new file mode 100644 index 0000000000..6cf18df9a6 --- /dev/null +++ b/osu.iOS/OsuGameIOS.cs @@ -0,0 +1,14 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using Foundation; +using osu.Game; + +namespace osu.iOS +{ + public class OsuGameIOS : OsuGame + { + public override Version AssemblyVersion => new Version(NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString()); + } +} diff --git a/osu.iOS/iTunesArtwork b/osu.iOS/iTunesArtwork new file mode 100644 index 0000000000..ef7441433a Binary files /dev/null and b/osu.iOS/iTunesArtwork differ diff --git a/osu.iOS/iTunesArtwork@2x b/osu.iOS/iTunesArtwork@2x new file mode 100644 index 0000000000..c04f6f3ec4 Binary files /dev/null and b/osu.iOS/iTunesArtwork@2x differ diff --git a/osu.iOS/libbass.a b/osu.iOS/libbass.a new file mode 100644 index 0000000000..c34e6a0a0c Binary files /dev/null and b/osu.iOS/libbass.a differ diff --git a/osu.iOS/libbass_fx.a b/osu.iOS/libbass_fx.a new file mode 100644 index 0000000000..007cd28647 Binary files /dev/null and b/osu.iOS/libbass_fx.a differ diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj new file mode 100644 index 0000000000..9df3ad5516 --- /dev/null +++ b/osu.iOS/osu.iOS.csproj @@ -0,0 +1,84 @@ + + + + + Debug + iPhoneSimulator + Exe + {3F082D0B-A964-43D7-BDF7-C256D76A50D0} + osu.iOS + osu.iOS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + {2A66DD92-ADB1-4994-89E2-C94E04ACDA0D} + osu.Game + + + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} + osu.Game.Rulesets.Catch + + + {48F4582B-7687-4621-9CBE-5C24197CB536} + osu.Game.Rulesets.Mania + + + {C92A607B-1FDD-4954-9F92-03FF547D9080} + osu.Game.Rulesets.Osu + + + {F167E17A-7DE6-4AF5-B920-A5112296C695} + osu.Game.Rulesets.Taiko + + + + + + + + + \ No newline at end of file diff --git a/osu.licenseheader b/osu.licenseheader index 798b25e550..ab8af1984b 100644 --- a/osu.licenseheader +++ b/osu.licenseheader @@ -1,9 +1,9 @@ -extensions: .cs -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -extensions: .xml .config .xsd - \ No newline at end of file diff --git a/osu.sln b/osu.sln index bf1b6d60e1..3c38309d86 100644 --- a/osu.sln +++ b/osu.sln @@ -3,29 +3,27 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27004.2006 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game", "osu.Game\osu.Game.csproj", "{2A66DD92-ADB1-4994-89E2-C94E04ACDA0D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Resources", "osu-resources\osu.Game.Resources\osu.Game.Resources.csproj", "{D9A367C9-4C1A-489F-9B05-A0CEA2B53B58}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop", "osu.Desktop\osu.Desktop.csproj", "{419659FD-72EA-4678-9EB8-B22A746CED70}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Tests", "osu.Game.Tests\osu.Game.Tests.csproj", "{54377672-20B1-40AF-8087-5CF73BF3953A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests", "osu.Game.Tests\osu.Game.Tests.csproj", "{28F040EA-536D-442B-B0CA-004075182EB6}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Desktop", "osu.Desktop\osu.Desktop.csproj", "{419659FD-72EA-4678-9EB8-B22A746CED70}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch.Tests", "osu.Game.Rulesets.Catch.Tests\osu.Game.Rulesets.Catch.Tests.csproj", "{608C7588-9CAE-4443-A431-96FC9DE72A25}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Catch.Tests", "osu.Game.Rulesets.Catch.Tests\osu.Game.Rulesets.Catch.Tests.csproj", "{3AD63355-D6B1-4365-8D31-5652C989BEF1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania.Tests", "osu.Game.Rulesets.Mania.Tests\osu.Game.Rulesets.Mania.Tests.csproj", "{BE8F48E4-7EEE-4C13-B8ED-7705BD9EE443}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Mania.Tests", "osu.Game.Rulesets.Mania.Tests\osu.Game.Rulesets.Mania.Tests.csproj", "{7E9E9C34-B204-406B-82E2-E01E900699CD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko.Tests", "osu.Game.Rulesets.Taiko.Tests\osu.Game.Rulesets.Taiko.Tests.csproj", "{4F0BF44A-7ECA-49A6-B0BB-B676657D9896}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Taiko.Tests", "osu.Game.Rulesets.Taiko.Tests\osu.Game.Rulesets.Taiko.Tests.csproj", "{B698561F-FB28-46B1-857E-3CA7B92F9D70}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu.Tests", "osu.Game.Rulesets.Osu.Tests\osu.Game.Rulesets.Osu.Tests.csproj", "{DECCCC75-67AD-4C3D-BB84-FD0E01323511}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -57,30 +55,30 @@ Global {48F4582B-7687-4621-9CBE-5C24197CB536}.Debug|Any CPU.Build.0 = Debug|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.ActiveCfg = Release|Any CPU {48F4582B-7687-4621-9CBE-5C24197CB536}.Release|Any CPU.Build.0 = Release|Any CPU - {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54377672-20B1-40AF-8087-5CF73BF3953A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54377672-20B1-40AF-8087-5CF73BF3953A}.Release|Any CPU.Build.0 = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Debug|Any CPU.Build.0 = Debug|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.ActiveCfg = Release|Any CPU {419659FD-72EA-4678-9EB8-B22A746CED70}.Release|Any CPU.Build.0 = Release|Any CPU - {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3AD63355-D6B1-4365-8D31-5652C989BEF1}.Release|Any CPU.Build.0 = Release|Any CPU - {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E9E9C34-B204-406B-82E2-E01E900699CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E9E9C34-B204-406B-82E2-E01E900699CD}.Release|Any CPU.Build.0 = Release|Any CPU - {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B698561F-FB28-46B1-857E-3CA7B92F9D70}.Release|Any CPU.Build.0 = Release|Any CPU - {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6A2D5D58-0261-4A75-BE84-2BE8B076B7C2}.Release|Any CPU.Build.0 = Release|Any CPU + {28F040EA-536D-442B-B0CA-004075182EB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28F040EA-536D-442B-B0CA-004075182EB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28F040EA-536D-442B-B0CA-004075182EB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28F040EA-536D-442B-B0CA-004075182EB6}.Release|Any CPU.Build.0 = Release|Any CPU + {608C7588-9CAE-4443-A431-96FC9DE72A25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {608C7588-9CAE-4443-A431-96FC9DE72A25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {608C7588-9CAE-4443-A431-96FC9DE72A25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {608C7588-9CAE-4443-A431-96FC9DE72A25}.Release|Any CPU.Build.0 = Release|Any CPU + {BE8F48E4-7EEE-4C13-B8ED-7705BD9EE443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE8F48E4-7EEE-4C13-B8ED-7705BD9EE443}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE8F48E4-7EEE-4C13-B8ED-7705BD9EE443}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE8F48E4-7EEE-4C13-B8ED-7705BD9EE443}.Release|Any CPU.Build.0 = Release|Any CPU + {4F0BF44A-7ECA-49A6-B0BB-B676657D9896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F0BF44A-7ECA-49A6-B0BB-B676657D9896}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F0BF44A-7ECA-49A6-B0BB-B676657D9896}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F0BF44A-7ECA-49A6-B0BB-B676657D9896}.Release|Any CPU.Build.0 = Release|Any CPU + {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DECCCC75-67AD-4C3D-BB84-FD0E01323511}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -92,29 +90,10 @@ Global Policies = $0 $0.TextStylePolicy = $1 $1.EolMarker = Windows - $1.inheritsSet = VisualStudio - $1.inheritsScope = text/plain $1.scope = text/x-csharp + $1.FileWidth = 80 + $1.TabsToSpaces = True $0.CSharpFormattingPolicy = $2 - $2.IndentSwitchSection = True - $2.NewLinesForBracesInProperties = True - $2.NewLinesForBracesInAccessors = True - $2.NewLinesForBracesInAnonymousMethods = True - $2.NewLinesForBracesInControlBlocks = True - $2.NewLinesForBracesInAnonymousTypes = True - $2.NewLinesForBracesInObjectCollectionArrayInitializers = True - $2.NewLinesForBracesInLambdaExpressionBody = True - $2.NewLineForElse = True - $2.NewLineForCatch = True - $2.NewLineForFinally = True - $2.NewLineForMembersInObjectInit = True - $2.NewLineForMembersInAnonymousTypes = True - $2.NewLineForClausesInQuery = True - $2.SpacingAfterMethodDeclarationName = False - $2.SpaceAfterMethodCallName = False - $2.SpaceBeforeOpenSquareBracket = False - $2.inheritsSet = Mono - $2.inheritsScope = text/x-csharp $2.scope = text/x-csharp EndGlobalSection EndGlobal diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 6b8e9dc808..71cbd83e3e 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -6,7 +6,11 @@ ExplicitlyExcluded ExplicitlyExcluded SOLUTION - HINT + WARNING + WARNING + WARNING + HINT + HINT WARNING True @@ -16,6 +20,32 @@ HINT HINT HINT + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING + WARNING WARNING WARNING WARNING @@ -48,6 +78,7 @@ HINT HINT ERROR + WARNING HINT HINT HINT @@ -62,18 +93,29 @@ WARNING WARNING WARNING + WARNING + WARNING + WARNING + WARNING WARNING + WARNING + WARNING + WARNING WARNING HINT + WARNING HINT HINT HINT + HINT HINT WARNING WARNING + HINT WARNING WARNING WARNING + WARNING HINT DO_NOT_SHOW DO_NOT_SHOW @@ -83,6 +125,8 @@ WARNING WARNING WARNING + WARNING + WARNING ERROR WARNING WARNING @@ -136,13 +180,18 @@ WARNING WARNING WARNING + WARNING HINT DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW + WARNING + WARNING + WARNING WARNING WARNING HINT + WARNING HINT HINT HINT @@ -156,16 +205,22 @@ WARNING WARNING WARNING + + True WARNING WARNING - HINT + WARNING WARNING WARNING HINT HINT WARNING + WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + ExpressionBody + ExpressionBody + True True True True @@ -176,6 +231,8 @@ True NEXT_LINE NEXT_LINE + 1 + 1 True NEVER NEVER @@ -203,8 +260,10 @@ HID HUD ID + IL IP IPC + JIT LTRB MD5 NS @@ -220,6 +279,7 @@ QAT BNG UI + False HINT <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> @@ -605,8 +665,8 @@ </Group> </TypePattern> </Patterns> - Copyright (c) 2007-$CURRENT_YEAR$ ppy Pty Ltd <contact@ppy.sh>. -Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. +See the LICENCE file in the repository root for full licence text. <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />